最近負責一個錄屏的小項目,需要錄制Windows窗口內容並壓縮保存到指定文件夾,本想使用已有的錄屏軟件,但是本着學習的態度去探索了FFMpeg,本文主要介紹基於FFMpeg開源項目的C#錄屏軟件開發。
在Windows平台下開發錄屏相比Linux比較復雜,Windows平台下錄屏有gdigrab和dshow兩種方法,由於gdigrab可修改屬性受限,所以本文采用dshow方法實現錄屏的功能,原理是注冊錄屏dshow濾鏡(例如screen-capture-recorder),然后通過dshow獲取錄屏圖像然后編碼處理,其中gdigrab可以詳見http://www.ffmpeg.org/ffmpeg-devices.html#gdigrab。
軟件開發環境:
Windows7 32位
Visual Studio2013
screen capture recorder(需要Java運行環境Java Runtime Environment)
1、軟件安裝完成后,可以在CMD命令行中檢測軟件安裝是否正確,首先進入FFMpeg.exe的根目錄文件夾,輸入命令:ffmpeg -list_devices true -f dshow -i dummy 命令執行后檢查輸出的結果是否有[dshow @xxx] "screen-capture-recorder" ,如果有則“screen capture recorder”軟件安裝正確。
2、錄屏測試:
在CMD窗口中進入FFMpeg.exe所在的根目錄文件夾,輸入錄屏指令:ffmpeg -f dshow -i video="screen-capture-recorder" -r 15 -vcodec libx264 -preset:v ultrafast -tune:v zerolatency MyDesktop.mkv
如果上述指令執行后,可以在FFMpeg軟件的根目錄生成MyDesktop.mkv的視頻文件則錄屏成功,如果MyDesktop.mkv無法播放,需要注意播放器是否支持H264協議,可以考慮使用VLC media player播放器,或者安裝Win7codecs解碼包。
3、C#開發
C#程序中調用FFMpeg.exe程序,並且不顯示命令行窗口界面,來完成FFMpeg.exe的錄屏功能,在視頻錄制完成后對視頻文件進行壓縮,其中主要函數如下所示。注意:在CMD命令行中FFMpeg.exe輸出的結果需要在ErrorDataReceived中創建事件才可以顯示。
1 public void RunFFmpeg() 2 3 { 4 5 Process[] KillProcessArray = Process.GetProcessesByName("ffmpeg"); 6 7 Debug.WriteLine(KillProcessArray.Length.ToString()); 8 9 foreach (var KillProcess in KillProcessArray) 10 11 { 12 13 KillProcess.Kill(); 14 15 } 16 17 Process p = new Process();//建立外部調用線程 18 19 p.StartInfo.FileName = @"E:\ffmpeg\ffmpeg.exe"; //ffmpeg.exe的絕對路徑 20 21 p.StartInfo.Arguments = @"-f dshow -i video=""screen-capture-recorder"" -r 15 -vcodec libx264 -preset:v ultrafast -tune:v zerolatency D:\MyDesktop.mkv"; //ffmpeg的參數 22 23 p.StartInfo.UseShellExecute = false; //是否使用操作系統shell啟動 24 25 p.StartInfo.RedirectStandardError = true; //重定向標准錯誤輸出 26 27 p.StartInfo.CreateNoWindow = true; //不顯示程序窗口 28 29 p.ErrorDataReceived += new DataReceivedEventHandler(Output); 30 31 p.Start(); 32 33 myProcessId = p.Id; //獲取關聯進程的唯一標識符 34 35 p.BeginErrorReadLine(); 36 37 } 38 39 public void StopFFmpeg() 40 41 { 42 43 Process myProcess = Process.GetProcessById(myProcessId); //通過ID關聯進程 44 45 myProcess.Kill(); 46 47 } 48 49 private void Output(object sendProcess,DataReceivedEventArgs output) 50 51 { 52 53 if (!String.IsNullOrEmpty(output.Data)) 54 55 Debug.WriteLine(output.Data.ToString()); 56 57 } 58 59 static void Main(string[] args) 60 61 { 62 63 CmdHelper ch = new CmdHelper(); 64 65 ch.RunFFmpeg(); 66 67 Console.WriteLine("Hello"); 68 69 Thread.Sleep(10000); 70 71 Console.WriteLine("10s passed"); 72 73 ch.StopFFmpeg(); 74 75 }
參考鏈接:
http://blog.csdn.net/zhichao2001/article/details/12526095
http://blog.csdn.net/leixiaohua1020/article/details/38284961
http://www.ffmpeg.org/ffmpeg-devices.html#gdigrab