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 }