从 Windows 中的 OpenGL 窗口捕获视频

Capturing video out of an OpenGL window in Windows

本文关键字:视频 窗口 OpenGL Windows 中的      更新时间:2023-10-16

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

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

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

  • 具有 startRecording(文件名)、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'd。您的项目是否可以接受 LGPL?Windows这样做的方式(DirectShow)使用起来有点头疼。

编辑:由于LGPL是可以的,您可以使用ffmpeg,请参阅此处以获取有关如何编码视频的示例。

这看起来确实与合并到 AVI 中非常相关(如 Andrew 所建议的那样),但我真的希望避免使用 LPBITMAPINFOHEADER 等。

感谢您的回答,如果有任何:),我将报告成功

同时,有关将原始帧从glReadPixels编码为视频剪辑的其他提示将不胜感激。

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

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

在获取每一帧方面,您可以通过按照建议渲染到屏幕外纹理或直接使用后台缓冲区作为源(如果您的硬件支持)来实现这一点。做其中任何一个(并保存每一帧)如果不对帧率造成严重损失,这将是困难的。

如果您的应用程序是确定性的,您可以将用户操作"记录"为一系列输入,然后具有导出模式,该模式按顺序将这些操作渲染到屏幕外表面以生成 AVI。

我必须创建一个演示项目,将OpenGL渲染录制成视频。我使用glReadPixels来获取像素数据,并使用OpenCV的cvWriteFrame创建了视频。OpenCV允许你用divx甚至x264/vp8(编译ffmpeg)编写。

我在我的博客文章中有一个更详细的文章以及一个示例项目。http://tommy.chheng.com/2013/09/09/encode-opengl-to-video-with-opencv/