简体   繁体   English

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

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

I am accessing the Microsoft Azure Kinect depth camera's video footage and displaying the video on a pictureBox using a C# WinForm application.我正在访问 Microsoft Azure Kinect 深度相机的视频片段,并使用 C# WinForm 应用程序在图片框上显示视频。 I am looking for a way to record this video now.我正在寻找一种方法来录制这个视频。 Is there a way to record the video playing on my entire pictureBox during the application run time?有没有办法在应用程序运行时录制在我的整个图片框上播放的视频?

I am using .NET framework 4.7.2我正在使用 .NET 框架 4.7.2

I wrote this class to wrap around ffmpeg (follow the " how to record your screen " help in the ffmpeg docs) and make some bits easier:我写了这个 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();
        }
    }
}

It gets some help from this class:它从这个 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);
        }
    }

Then you just put an ffmpeg binary at some place and put the path in settings ( CommandLineFfmpegPath ) and some suitable args (settings name CommandLineFfmpegArgs ) for what you want to record然后,您只需将 ffmpeg 二进制文件放在某个位置,并将路径放入设置( CommandLineFfmpegPath )和一些合适的参数(设置名称CommandLineFfmpegArgs )以记录您想要记录的内容

My args are -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}" - you'll only have a virtual audio cable if you install it, but you can get ffmpeg to list the sound devices on your system and put one of those instead, or even omit it if you dont want sound.我的参数是-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 列出您系统上的声音设备并放置其中一个相反,如果您不想要声音,甚至可以省略它。

Screenshot of settings editor:设置编辑器截图:

在此处输入图像描述

Then you make an instance of FfmpegRecorder with a rectangle to record - that would be the coordinates of your picturebox, translated to screen coords (watch out for DPI/you have to adjust your values if your Windows doesn't run at 100% "zoom")然后你制作一个带有矩形记录的 FfmpegRecorder 实例——这将是你的图片框的坐标, 转换为屏幕坐标(注意 DPI/如果你的 Windows 没有以 100%“缩放”运行,你必须调整你的值")

If you want to make your life easier/get to the "one line record" I mentioned, just make sure your picturebox is in the same place all the time (maximize the form), set the reg settings one time using regedit, and fire off a Process.Start to launch ffmpeg with some args.如果你想让你的生活更轻松/获得我提到的“单行记录”,只要确保你的图片框一直在同一个地方(最大化表格),使用 regedit 设置一次 reg 设置,然后启动关闭进程。开始使用一些参数启动Process.Start Most of the other fluff in this answer is because I wanted to capture FF's logs, or interact with it, or adjust the recording region to different places all the time这个答案中的其他大部分内容是因为我想捕获FF的日志,或者与之交互,或者一直将记录区域调整到不同的地方

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

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