使用AForge.Video.FFMPEG / AForge.Video.VFW进行屏幕捕捉视频。帧速率问题。

5
我的WinForms .NET 4 C#应用程序在用户与之交互时记录桌面。
根据系统速度,它使用AForge FFMPEG或VFW包装器。当然,捕获是在后台线程中完成的。
在任一情况下,包装器需要预先指定帧速率。这是有问题的,因为捕获频率是不确定的,并且很容易受到目标计算机的繁忙程度的影响。在一个好的系统上,我最多可以获得10 FPS。
所以这里有两个问题:
  • 如何基于实际捕获帧速率对齐帧?
  • 如何增加帧速率,也许通过使用除AForge之外的解决方案?
为了清晰起见,下面列出了我使用的代码:
private void ThreadWork ()  
{  
    int count = 0;  
    string filename = "";  
    RECT rect = new RECT();  
    System.Drawing.Bitmap bitmap = null;  
    System.Drawing.Graphics graphics = null;  
    System.DateTime dateTime = System.DateTime.Now;  
    System.IntPtr hWndForeground = System.IntPtr.Zero;  
    AForge.Video.FFMPEG.VideoFileWriter writer = null;  

    filename = @"c:\Users\Raheel Khan\Desktop\Temp\Capture.avi";
    if (System.IO.File.Exists(filename))
        System.IO.File.Delete(filename);

    writer = new AForge.Video.FFMPEG.VideoFileWriter();
    writer.Open
    (
        filename,
        System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
        System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height,
        10, // FPS
        AForge.Video.FFMPEG.VideoCodec.MPEG4
    );

    bitmap = new Bitmap
    (
        System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
        System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height,
        System.Drawing.Imaging.PixelFormat.Format24bppRgb
    );
    graphics = System.Drawing.Graphics.FromImage(bitmap);

    dateTime = System.DateTime.Now;

    while (System.DateTime.Now.Subtract(dateTime).TotalSeconds < 10) // 10 seconds.
    {
        graphics.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 0, 0, Screen.PrimaryScreen.Bounds.Size);

        rect = new RECT();
        hWndForeground = GetForegroundWindow();
        GetWindowRect(hWndForeground, ref rect);
        graphics.DrawRectangle(Pens.Red, rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top);
        graphics.DrawString(count++.ToString(), this.Font, Brushes.Red, 10, 10);

        writer.WriteVideoFrame(bitmap);

        System.Threading.Thread.Sleep(10);
    }

    writer.Close();
    writer.Dispose();

    System.Diagnostics.Process.Start(System.IO.Path.GetDirectoryName(filename));
}
1个回答

3
你可以将帧捕获为JPEG格式或MJPEG格式的文件并保存到临时文件夹中,然后在用户需要时重新处理成AVI视频文件。这样能减少实时处理的工作量,释放资源,并使系统达到更高和更稳定的帧率。

谢谢。这将正确计算实际帧速率,但不幸的是会比当前方法花费更多的时间在磁盘IO上。我在一台相当不错的开发机器上测试了一下。现在我正在寻找商业替代方案,比如LeadTools,尽管他们的许可证太贵了。 - Raheel Khan
1
如果您缓冲帧,则可以解决磁盘IO问题。以jpeg格式获取每个帧并存储在内存中。 10mb的RAM可以存储约100帧,这相当于25fps下的4秒钟。然后将它们作为单个具有MIME格式头的mjpeg文件写入磁盘。例如,Mencoder可以通过传递命令行参数直接将此类文件转换为avi。这意味着您可以跳过aforge,并在不同的进程中制作avi,这在多核机器中可能更资源有效。 - Sugrue

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接