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 }