繁体   English   中英

如何录制在pictureBox上播放的视频?

[英]How to record video playing on a pictureBox?

我正在访问 Microsoft Azure Kinect 深度相机的视频片段,并使用 C# WinForm 应用程序在图片框上显示视频。 我正在寻找一种方法来录制这个视频。 有没有办法在应用程序运行时录制在我的整个图片框上播放的视频?

我正在使用 .NET 框架 4.7.2

我写了这个 class 来环绕 ffmpeg (遵循 ffmpeg 文档中的“如何记录屏幕”帮助)并使一些位更容易:

using System;
using System.Diagnostics;
using System.Drawing;
using System.Text;

namespace CJCam
{
    public class FfmpegRecorder : Recorder
    {
        public string OutputPath { get; set; }

        private Process _ffmpeg = null;
        private readonly StringBuilder _ffLog = new StringBuilder();

        //like STDERR: frame=113987 fps= 10 q=-1.0 Lsize=  204000kB time=03:09:58.50 bitrate= 146.6kbits/s    
        private string _streamStats = "";

        ~FfmpegRecorder()
        {
            Dispose();
        }

        public override void Dispose()
        {
        }

        public FfmpegRecorder(string outputPath, Rectangle recordingRect)
        {
            ScreenCaptureRecorderRegistry.SetRecordRegion(recordingRect);

            OutputPath = outputPath;
        }

        public override void StartRecording()
        {
            ProcessStartInfo psi = new ProcessStartInfo
            {
                FileName = Properties.Settings.Default.CommandLineFfmpegPath,
                Arguments = string.Format(
                    Properties.Settings.Default.CommandLineFfmpegArgs,
                    OutputPath
                ),
                WindowStyle = ProcessWindowStyle.Hidden,
                CreateNoWindow = true,
                UseShellExecute = false,
                RedirectStandardInput = true,
                RedirectStandardOutput = true,
                RedirectStandardError = true
            };

            _ffmpeg = System.Diagnostics.Process.Start(psi);
            _ffmpeg.OutputDataReceived += Ffmpeg_OutputDataReceived;
            _ffmpeg.ErrorDataReceived += Ffmpeg_ErrorDataReceived;
            _ffmpeg.BeginOutputReadLine();
            _ffmpeg.BeginErrorReadLine();

            _ffmpeg.PriorityClass = ProcessPriorityClass.High;
        }

        void Ffmpeg_OutputDataReceived(object sender, DataReceivedEventArgs e)
        {
            if (e.Data != null && IsInteresting(e.Data))
            {
                _ffLog.Append("STDOUT: ").AppendLine(e.Data);
            }
        }
        void Ffmpeg_ErrorDataReceived(object sender, DataReceivedEventArgs e)
        {
            if (e.Data != null && IsInteresting(e.Data))
            {
                _ffLog.Append("STDERR: ").AppendLine(e.Data);
            }
        }

        bool IsInteresting(string data)
        {
            if (data.StartsWith("frame="))
            {
                _streamStats = data;
                return false;
            }

            return true;
        }

        public override void PauseRecording()
        {
            throw new NotImplementedException("Cannot pause FFmpeg at this time");
        }

        public override void StopRecording()
        {
            if (_ffmpeg == null)
                return;

            if (_ffmpeg.HasExited)
                return;

            _ffmpeg.StandardInput.WriteLine("q");

            _ffmpeg.WaitForExit(5000);
        }

        public override string GetLogFile()
        {
            return _ffLog.AppendLine().Append("CURRENT FRAME:").AppendLine(_streamStats).ToString();
        }
    }
}

它从这个 class 得到一些帮助:

    class ScreenCaptureRecorderRegistry
    {
        public static void SetRecordRegion(Rectangle region)
        {
            RegistryKey key = Registry.CurrentUser.OpenSubKey("Software\\screen-capture-recorder");

            // If the return value is null, the key doesn't exist
            if (key == null)
                key = Registry.CurrentUser.CreateSubKey("Software\\screen-capture-recorder");

            key = Registry.CurrentUser.OpenSubKey("Software\\screen-capture-recorder", true);

            key.SetValue("start_x", region.X, RegistryValueKind.DWord);
            key.SetValue("start_y", region.Y, RegistryValueKind.DWord);
            key.SetValue("capture_width", region.Width, RegistryValueKind.DWord);
            key.SetValue("capture_height", region.Height, RegistryValueKind.DWord);
        }
    }

然后,您只需将 ffmpeg 二进制文件放在某个位置,并将路径放入设置( CommandLineFfmpegPath )和一些合适的参数(设置名称CommandLineFfmpegArgs )以记录您想要记录的内容

我的参数是-rtbufsize 2048M -thread_queue_size 512 -f dshow -i video="screen-capture-recorder" -thread_queue_size 512 -f dshow -i audio="Line 1 (Virtual Audio Cable)" -x264opts keyint=50 -map 0:v -map 1:a -pix_fmt yuv420p -y "{0}" - 如果您安装它,您将只有一条虚拟音频电缆,但您可以让 ffmpeg 列出您系统上的声音设备并放置其中一个相反,如果您不想要声音,甚至可以省略它。

设置编辑器截图:

在此处输入图像描述

然后你制作一个带有矩形记录的 FfmpegRecorder 实例——这将是你的图片框的坐标, 转换为屏幕坐标(注意 DPI/如果你的 Windows 没有以 100%“缩放”运行,你必须调整你的值")

如果你想让你的生活更轻松/获得我提到的“单行记录”,只要确保你的图片框一直在同一个地方(最大化表格),使用 regedit 设置一次 reg 设置,然后启动关闭进程。开始使用一些参数启动Process.Start 这个答案中的其他大部分内容是因为我想捕获FF的日志,或者与之交互,或者一直将记录区域调整到不同的地方

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM