C#呼叫FFMPEG實現桌面錄製(視訊+音訊+生成本地檔案)【筆記】
阿新 • • 發佈:2019-02-03
不得不說FFMPEG真是個神奇的玩意,所接觸的部分不過萬一。網上有個很火的例子是c++方面的,當然這個功能還是用c++來實現比較妥當。
然而我不會c++
因為我的功能需求比較簡單,只要實現基本的錄製就可以了,其實就是一句命令的事
先來程式碼:RecordHelper類
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.DirectX; using Microsoft.DirectX.DirectSound; using System.Runtime.InteropServices; namespace ClassTool { public class RecordHelper { #region 模擬控制檯訊號需要使用的api [DllImport("kernel32.dll")] static extern bool GenerateConsoleCtrlEvent(int dwCtrlEvent, int dwProcessGroupId); [DllImport("kernel32.dll")] static extern bool SetConsoleCtrlHandler(IntPtr handlerRoutine, bool add); [DllImport("kernel32.dll")] static extern bool AttachConsole(int dwProcessId); [DllImport("kernel32.dll")] static extern bool FreeConsole(); #endregion // ffmpeg程序 static Process p = new Process(); // ffmpeg.exe實體檔案路徑 static string ffmpegPath = AppDomain.CurrentDomain.BaseDirectory + "ffmpeg\\ffmpeg.exe"; /// <summary> /// 獲取聲音輸入裝置列表 /// </summary> /// <returns>聲音輸入裝置列表</returns> public static CaptureDevicesCollection GetAudioList() { CaptureDevicesCollection collection = new CaptureDevicesCollection(); return collection; } /// <summary> /// 功能: 開始錄製 /// </summary> public static void Start(string audioDevice, string outFilePath) { if (File.Exists(outFilePath)) { File.Delete(outFilePath); } /*轉碼,視訊錄製裝置:gdigrab;錄製物件:桌面; * 音訊錄製方式:dshow; * 視訊編碼格式:h.264;*/ ProcessStartInfo startInfo = new ProcessStartInfo(ffmpegPath); startInfo.WindowStyle = ProcessWindowStyle.Normal; startInfo.Arguments = "-f gdigrab -framerate 15 -i desktop -f dshow -i audio=\"" + audioDevice + "\" -vcodec libx264 -preset:v ultrafast -tune:v zerolatency -acodec libmp3lame \"" + outFilePath + "\""; p.StartInfo = startInfo; p.Start(); } /// <summary> /// 功能: 停止錄製 /// </summary> public static void Stop() { AttachConsole(p.Id); SetConsoleCtrlHandler(IntPtr.Zero, true); GenerateConsoleCtrlEvent(0, 0); FreeConsole(); } } }
開始那幾個api介面是用來模擬ctrl+c命令的。本來以為在停止錄製的時候直接kill掉程序就好,結果導致生成的視訊檔案直接損壞了。手動使用ffmpeg.exe的時候發現ctrl+c可以直接結束錄製並且不會損壞視訊檔案,於是採用這種方法,在點選停止按鈕時模擬ctrl+c來退出ffmpeg。
ffmpeg的命令引數裡,gdigrab是ffmpeg內建的螢幕錄製裝置,但是這個裝置不能同時採集音訊,於是又用到了後面的dshow。這裡有個問題很奇怪,用ffmpeg獲取音訊裝置列表時,裝置的名稱如果超過31個字元的話會被截斷,而若是將完整的裝置名傳到引數裡則無法進行音訊採集,只能將截斷的裝置名稱傳進去,不知道為什麼……