C#調用FFMPEG實現桌面錄制(視頻+音頻+生成本地文件)


不得不說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個字符的話會被截斷,而若是將完整的設備名傳到參數里則無法進行音頻采集,只能將截斷的設備名稱傳進去,不知道為什么……


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM