在Windows中从OpenGL窗口捕获视频

时间:2020-03-06 14:56:40  来源:igfitidea点击:

我应该为我的用户提供一种从OpenGL应用程序的主窗口捕获视频剪辑的非常简单的方法。我正在考虑添加用于启动和停止捕获的按钮和/或者键盘快捷方式;启动时,我可能会要求提供文件名和其他选项(如果有)。它必须在Windows(XP / Vista)中运行,但是我也不想关闭到目前为止我一直能够保持打开状态的Linux门。

该应用程序使用OpenGL片段和着色器程序,最终在视频中绝对需要这些效果。

在我看来,甚至可能有几种不同的方法都可能满足我的要求(但我真的不知道应该从哪里开始):

  • 一个编码库,具有诸如startRecording(filename),stopRecording和captureFrame之类的功能。我可以在渲染的每一帧之后(或者每秒钟/三分之一/其他)调用captureFrame()。如果这样做会使我的程序运行速度变慢,那不是真正的问题。
  • 一个独立的外部程序,可以从我的应用程序以编程方式进行控制。毕竟,一个无法控制的独立程序几乎可以满足我的需要……但是,正如所说的那样,它对于用户来说应该非常简单,我也希望它具有无缝性。我的应用程序通常在全屏模式下运行。此外,应该有可能作为应用程序的安装包的一部分进行分发,而我目前正在使用NSIS准备该应用程序。
  • 使用Windows API逐帧捕获屏幕截图,然后使用(例如)此处提到的库之一。在Windows中找到如何捕获屏幕快照的示例似乎很容易;但是,我希望有一个解决方案并不能真正迫使我在WinAPI级别上变得超级肮脏。
  • 使用OpenGL渲染到屏幕外目标,然后使用库制作视频。我不知道这是否有可能,而且恐怕无论如何这也不是减轻痛苦的途径。特别是,我不希望实际的渲染根据是否捕获视频而采取不同的执行路径。另外,我将避免任何可能降低正常非捕获模式下的帧速率的事情。

如果从任何意义上说解决方案都是免费的,那将很棒,但这并不是绝对的要求。通常,肿越少越好。另一方面,不幸的是,出于这个问题之外的原因,我无法链接任何仅GPL的代码。

关于文件格式,我不能指望我的用户开始使用任何编解码器进行搜索,但是对于基本级别的Windows用户来说,只要显示视频就足够容易了,我也不在乎格式是什么。但是,如果有可能控制输出的压缩质量,那就太好了。

只是要澄清一下:我不需要从便携式摄像机之类的外部设备捕获视频,我也不真正对鼠标移动感兴趣,即使获取鼠标移动也不会造成伤害。对音频没有任何要求。该应用程序不会产生任何噪音。

我使用Visual Studio 2008编写C ++,为此应用程序还利用了GLUT和GLUI。我对C ++和库中的链接以及诸如此类的东西有扎实的了解,但是另一方面,OpenGL对我来说是个新事物:到目前为止,我实际上只学到了一些必要的知识,可以真正完成我的工作。

我不需要紧急解决方案,所以请花点时间:)

解决方案

这里有两个不同的问题,如何从OpenGL应用程序中获取帧,以及如何将它们转换为电影文件。

第一个问题很简单;我们只需使用glReadPixels()抓取每个帧(如果需要性能,可通过PBO抓取)。

第二个问题要难一些,因为跨平台解决方案(ffmpeg)倾向于使用GPL或者LGPL。 LGPL是否适合项目? Windows上执行此操作的方法(DirectShow)使用起来有些麻烦。

编辑:由于LGPL可以,我们可以使用ffmpeg,请参阅此处的有关如何对视频进行编码的示例。

最简单的选择是从应用程序中保存每个渲染的帧,然后将它们合并到AVI中。当我们拥有AVI时,有许多可用的库可以将其转换为更优化的格式,或者可能完全跳过AVI步骤。

就获取每一帧而言,我们可以按照建议将其渲染到屏幕外的纹理中,或者如果硬件支持,则直接使用后缓冲区作为源来实现。如果不对帧速率进行沉重的惩罚,那么执行上述任一操作(并保存每个帧)将很困难。

提供确定性的应用程序后,我们可以将用户的操作"记录"为一系列输入,然后具有导出模式,该模式将这些操作顺序呈现到屏幕外以生成AVI。

对于合并到AVI中,这确实很相关(如安德鲁所建议),但是我确实希望避免使用LPBITMAPINFOHEADER等。

感谢回答,如果有任何可能,我将报告成功的信息:)

同时,应该感谢将glReadPixels中的原始帧编码为视频片段的其他技巧。

编辑:到目前为止,迈克F建议的ffmpeg似乎是要走的路。但是,我还没有深入到实际的实现中,但是希望不久的将来会有所改变!