【问题标题】:Capturing video out of an OpenGL window in Windows在 Windows 中从 OpenGL 窗口中捕获视频
【发布时间】:2010-09-14 08:38:51
【问题描述】:

我应该为我的用户提供一种非常简单的方法来从我的 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 对我来说还是很新的:到目前为止,我真的只学到了实际完成工作所需的一些知识。

我并不急需解决方案,所以请慢慢来 :)

【问题讨论】:

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


    【解决方案1】:

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

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

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

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

    【讨论】:

    • glReadPixels() 确实似乎是我第一个问题所需要的,谢谢!
    【解决方案2】:

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

    感谢大家的回答,如果有成功我会报告成功的:)

    在此期间,我们将不胜感激将来自glReadPixels 的原始帧编码为视频剪辑的其他提示。

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

    【讨论】:

    • 请注意,使用 VfW 和 DirectShow 只能使用用户机器上安装的任何编解码器,因此您需要捆绑您计划使用的编解码器或找出它们是哪些编解码器 保证已经有了。
    【解决方案3】:

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

    就获取每一帧而言,您可以按照您的建议通过渲染到屏幕外纹理来完成此操作,或者如果您的硬件支持,则直接使用后台缓冲区作为源。如果不对帧率造成严重影响,执行其中任何一项(并保存每一帧)都将很困难。

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

    【讨论】:

    • 帧率损失是完全可以接受的,只要它只适用于真正捕获视频时。该应用程序是确定性的,不是随机的,但显示的内容除了用户操作外,还基于外部测量设备的结果。
    【解决方案4】:

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

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

    【讨论】:

    • 感谢您发布您的答案!请注意,您应该在此处、此站点上发布答案的基本部分,否则您的帖子有被删除的风险See the FAQ where it mentions answers that are 'barely more than a link'. 如果您愿意,您仍然可以包含该链接,但仅作为“参考”。答案应该是独立的,不需要链接。
    • 嗨,bluefeet,答案的基本部分已经出现:“使用 glReadPixels 获取像素数据”并使用 OpenCV 的“cvWriteFrame”。博客文章更详细,但这就是答案的要点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-13
    • 2011-06-20
    • 1970-01-01
    • 2012-01-04
    • 1970-01-01
    相关资源
    最近更新 更多