• WPF之录制桌面视频(FFMPeg)


    FFmpeg的视频录制,本身代码就是一个工具类,直接复制即可用,RecordHelper是基础的视频开始录制和视频停止录制

      public class RecordHelper
        {
    
            public static RecordHelper Instance = new RecordHelper();
            // ffmpeg进程
            static Process process;
            /// <summary>
            /// 开始录制
            /// </summary>
            /// <param name="FileName">文件名称.mp4</param>
            /// <param name="Framerate">帧数</param>
            /// <param name="ffmpegPath">ffmpeg.exe的路径</param>
            /// <param name="Path">输出文件路径</param>
            public  void Start(string FileName, int Framerate, string ffmpegPath, string Path)
            {
                try
                {
                    process = new Process();
                    string curDir = System.Environment.CurrentDirectory;
                    process.StartInfo.FileName = ffmpegPath;
                    process.StartInfo.Arguments = @"-f gdigrab -framerate " + Framerate + " -i desktop -preset ultrafast -pix_fmt yuv420p  -vf "scale = 1280:720" " + FileName;//parameters
                   // ffmpeg - f avfoundation - i 1 - r 30 out.yuv
                    process.StartInfo.UseShellExecute = false;//是否使用操作系统shell启动
                    process.StartInfo.RedirectStandardInput = true;//接受来自调用程序的输入信息
                    process.StartInfo.RedirectStandardOutput = true;//由调用程序获取输出信息
                    process.StartInfo.RedirectStandardError = true;//重定向标准错误输出
                    process.StartInfo.CreateNoWindow = true;//不显示程序窗口
                    process.ErrorDataReceived += ErrorDataReceived;
                    process.OutputDataReceived += OutputDataReceived;
                    process.StartInfo.WorkingDirectory = Path; // The output directory  
                    process.Start();//Start
                    process.BeginErrorReadLine();
                    process.BeginOutputReadLine();
                    // AudioRecorderProcess_ID = p.Id;
                    //p.BeginErrorReadLine();//Start asynchronous reading
                }
                catch (Exception ex)
                {
    
    
                }
            }
            private static void ErrorDataReceived(object sender, DataReceivedEventArgs e)
            {
                Log.Debug($"pdf 操作 错误信息: {e.Data}");
                //Process process = sender as Process;
             
            }
    
            private static void OutputDataReceived(object sender, DataReceivedEventArgs e)
            {
                Log.Debug($"pdf 操作 命令行输出: {e.Data}");
            }
            private const int ProcessTimeOut = 1000;
            /// <summary>
            /// 功能: 停止录制
            /// </summary>
            public  void Stop()
            {
                try
                {
                    process.StandardInput.WriteLine("q");//In the console of this process, the analog input q is used to pause recording.
                    process.StandardInput.AutoFlush = true;
                    process.WaitForExit(ProcessTimeOut);//等待程序执行完退出进程  
                    process.Close();
                    process.Dispose();
                }
                catch (Exception ex)
                {
                    Log.Error("视频录制停止时异常:" + ex.Message);
                }
            }
    
    
            public void MianSuspend()
            {
                //process.Suspend();
            }
    
            public  void Play()
            {
                //process.Resume();
            }
        }

    接下来需要暂停和继续视频的录制,这里只是一个扩展方法,用来暂停和继续视频录制

     static class Helper
        {
            public static T[] ToArray<T>(this ICollection collection)
            {
                var items = new T[collection.Count];
                collection.CopyTo(items, 0);
    
                return items;
            }
        }
    
        public static class ProcessExtensions
        {
            #region Methods
    
            public static void Suspend(this Process process)
            {
                Action<ProcessThread> suspend = pt =>
                {
                    var threadHandle = NativeMethods.OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pt.Id);
    
                    if (threadHandle != IntPtr.Zero)
                    {
                        try
                        {
                            NativeMethods.SuspendThread(threadHandle);
                        }
                        finally
                        {
                            NativeMethods.CloseHandle(threadHandle);
                        }
                    };
                };
    
                var threads = process.Threads.ToArray<ProcessThread>();
    
                if (threads.Length > 1)
                {
                    Parallel.ForEach(threads, new ParallelOptions { MaxDegreeOfParallelism = threads.Length }, pt =>
                    {
                        suspend(pt);
                    });
                }
                else
                {
                    suspend(threads[0]);
                }
            }
    
            public static void Resume(this Process process)
            {
                Action<ProcessThread> resume = pt =>
                {
                    var threadHandle = NativeMethods.OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pt.Id);
                    if (threadHandle != IntPtr.Zero)
                    {
                        try
                        {
                            NativeMethods.ResumeThread(threadHandle);
                        }
                        finally
                        {
                            NativeMethods.CloseHandle(threadHandle);
                        }
                    }
                };
    
                var threads = process.Threads.ToArray<ProcessThread>();
    
                if (threads.Length > 1)
                {
                    Parallel.ForEach(threads, new ParallelOptions { MaxDegreeOfParallelism = threads.Length }, pt =>
                    {
                        resume(pt);
                    });
                }
                else
                {
                    resume(threads[0]);
                }
            }
    
    
            #endregion
    
            #region Interop
    
            static class NativeMethods
            {
                [DllImport("kernel32.dll")]
                [return: MarshalAs(UnmanagedType.Bool)]
                public static extern bool CloseHandle(IntPtr hObject);
    
                [DllImport("kernel32.dll")]
                public static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
    
                [DllImport("kernel32.dll")]
                public static extern uint SuspendThread(IntPtr hThread);
    
                [DllImport("kernel32.dll")]
                public static extern uint ResumeThread(IntPtr hThread);
            }
    
            [Flags]
            enum ThreadAccess : int
            {
                TERMINATE = (0x0001),
                SUSPEND_RESUME = (0x0002),
                GET_CONTEXT = (0x0008),
                SET_CONTEXT = (0x0010),
                SET_INFORMATION = (0x0020),
                QUERY_INFORMATION = (0x0040),
                SET_THREAD_TOKEN = (0x0080),
                IMPERSONATE = (0x0100),
                DIRECT_IMPERSONATION = (0x0200)
            }
    
            #endregion
        }
  • 相关阅读:
    最短路最基本算法———Floyd算法
    最短路最基本算法———Floyd算法
    浅谈最基础的三种背包问题
    浅谈最基础的三种背包问题
    Java中的反射机制Reflection
    Linux下抓包命令tcpdump的使用
    SSRF(服务端请求伪造)漏洞
    Cookie、Session和Token认证
    使用BurpSuite抓取HTTPS网站的数据包
    堆、栈和队列的区别
  • 原文地址:https://www.cnblogs.com/ACBJTR/p/11854843.html
Copyright © 2020-2023  润新知