2012-04-26 24 views
5

Ứng dụng .NET 4 C# của WinForms của tôi ghi lại màn hình nền trong khi người dùng tương tác với nó.Quay video màn hình bằng AForge.Video.FFMPEG/AForge.Video.VFW. Vấn đề về Frame Rate

Sử dụng trình bao bọc AForge FFMPEG hoặc VFW tùy thuộc vào tốc độ của hệ thống. Việc chụp được thực hiện trong một chủ đề nền của khóa học.

Trong cả hai trường hợp, trình bao bọc yêu cầu tốc độ khung hình phải được chỉ định trước. Đây là vấn đề kể từ khi chụp tần số là không xác định và dễ bị ảnh hưởng bởi bận rộn như thế nào máy mục tiêu. Trên một hệ thống tốt, tôi nhận được tối đa 10 FPS.

Vì vậy, hai vấn đề ở đây:

  • Làm thế nào để sắp xếp khung dựa trên tỷ lệ khung hình chụp thực tế?
  • Cách tăng tốc độ khung hình, có lẽ bằng cách sử dụng một giải pháp khác ngoài AForge?

Code tôi sử dụng được liệt kê dưới đây cho rõ ràng:

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)); 
} 

Trả lời

3

Bạn có thể nắm bắt được khung vào một thư mục tạm thời như JPEG hoặc vào một tập tin mjpeg, và sau đó tái xử lý nó vào một tập tin avi video khi người dùng mong muốn nó. Điều này sẽ cắt giảm số lượng xử lý bạn cần thực hiện 'khi đang di chuyển' và giải phóng tài nguyên - đồng thời cho phép hệ thống của bạn đạt được tốc độ khung hình cao hơn và thường xuyên hơn.

+0

Cảm ơn. Điều đó sẽ chăm sóc tính toán tỷ lệ khung hình thực tế một cách chính xác nhưng tiếc là sẽ mất nhiều thời gian hơn trong đĩa IO so với phương pháp hiện tại. Tôi hẹn giờ nó trên một máy dev khá phong nha. Tôi hiện đang xem xét các lựa chọn thay thế thương mại như LeadTools, mặc dù việc cấp phép của họ quá đắt. –

+1

Nếu bạn đệm khung, bạn giải quyết vấn đề về đĩa IO. Lấy mỗi khung hình như một jpeg và lưu trữ trong bộ nhớ. 10mb ram sẽ lưu trữ khoảng 100 khung hình, tức là 4 giây ở tốc độ 25 khung hình/giây. Sau đó ghi chúng vào đĩa dưới dạng tệp mjpeg duy nhất với tiêu đề định dạng MIME. Mencoder, ví dụ, có thể chuyển đổi một tập tin trực tiếp thành avi, chỉ bằng cách chuyển các tham số dòng lệnh. Điều này có nghĩa là bạn có thể bỏ qua aforge, và nhận được avi của bạn được thực hiện trong quá trình khác nhau, có thể được nhiều tài nguyên hiệu quả trong một máy đa lõi. – Sugrue

Các vấn đề liên quan