微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何录制在图片框上播放的视频?

如何解决如何录制在图片框上播放的视频?

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

我使用的是 .NET 框架 4.7.2

解决方法

我编写了这个类来环绕 ffmpeg(遵循 ffmpeg 文档中的“how to record your screen”帮助)并使一些更容易:

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 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 列出你系统上的声音设备,并把其中一个代替,甚至省略它如果你不想要声音。

设置编辑器截图:

enter image description here

然后你用一个矩形来记录一个 FfmpegRecorder 的实例——这将是你的图片框的坐标,translated to screen coords(注意 DPI/如果你的 Windows 没有运行,你必须调整你的值100%“缩放”)

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。