在Windows中从OpenGL窗口捕获视频

时间:2008-09-30 20:03:16

标签: c++ opengl video screenshot video-capture

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

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

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

  • 具有startRecording(filename),stopRecording和captureFrame等函数的编码库。我可以在渲染的每一帧之后调用captureFrame()(或者每隔一秒/三次/无论如何)。如果这样做会使我的程序运行速度变慢,那就不是问题了。

  • 可以从我的应用程序以编程方式控制的独立外部程序。毕竟,一个可以被控制的独立程序几乎可以满足我的需要......但是如上所述,用户操作应该非常简单,我也会欣赏它的无缝性;我的应用程序通常全屏运行。此外,应该可以作为我的应用程序的安装包的一部分进行分发,我目前正在使用NSIS进行准备。

  • 使用Windows API逐帧捕获屏幕截图,然后使用(例如)libraries mentioned here之一。似乎很容易找到如何在Windows中捕获屏幕截图的示例;但是,我会喜欢一个解决方案,它并没有真正迫使我在WinAPI级别上让我的手变得非常脏。

  • 使用OpenGL渲染到屏幕外目标,然后使用库生成视频。我不知道这是否可能,我担心它可能不是最不痛苦的道路。特别是,我不希望实际渲染采用不同的执行路径,具体取决于是否捕获视频。此外,我会避免在正常的非捕获模式下可能降低帧速率的任何内容。

如果解决方案在任何一个意义上都是免费的,那么这将是很好的,但这并不是一个绝对的要求。一般来说,臃肿越少越好。另一方面,由于这个问题之外的原因,遗憾的是我无法链接任何仅限GPL的代码。

关于文件格式,我不能指望我的用户开始使用谷歌搜索任何编解码器,但只要显示视频对于基本级别的Windows用户来说也很容易,我不会真正关心格式是什么。但是,如果可以控制输出的压缩质量,那就太棒了。

只是为了澄清:我需要从像摄像机这样的外部设备捕获视频,我也不是真的对鼠标移动感兴趣,即使它们也没有伤害。音频没有要求;应用程序不会产生任何噪音。

我使用Visual Studio 2008编写C ++,因为这个应用程序也受益于GLUT和GLUI。我对C ++和库中的链接以及那些东西有着深刻的理解,但另一方面,OpenGL对我来说是一个新的东西:到目前为止,我真的只学到了实际完成工作所必需的部分。

我不需要超级紧急的解决方案,所以请随时抽出时间:)

4 个答案:

答案 0 :(得分:8)

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

第一个问题很容易;你只需用glReadPixels()抓住每一帧(如果你需要表演,可以通过PBO)。

第二个问题有点困难,因为跨平台解决方案(ffmpeg)往往是GPL或LGPL。 LGPL是否可以接受您的项目? Windows的这种方式(DirectShow)使用起来有点令人头疼。

编辑:由于LGPL没问题且您可以使用ffmpeg,请参阅here以获取如何编码视频的示例。

答案 1 :(得分:1)

This看起来非常适合合并到AVI(正如安德鲁所建议的那样),但我真的希望避免使用LPBITMAPINFOHEADER等。

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

与此同时,我们将非常感谢将原始帧从glReadPixels编码为视频片段的其他提示。

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

答案 2 :(得分:0)

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

在获取每个帧时,您可以通过渲染到您建议的屏幕外纹理或直接使用backbuffer作为源来完成此操作(如果您的硬件支持此功能)。在没有严重的帧速率惩罚的情况下,执行其中任何一项(并保存每一帧)都会很困难。

提供您的应用程序是确定性的,您可以将用户操作“记录”为一系列输入,然后使用导出模式将这些操作依次呈现到屏幕外表面以生成AVI。

答案 3 :(得分:0)

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

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