不得不说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个字符的话会被截断,而若是将完整的设备名传到参数里则无法进行音频采集,只能将截断的设备名称传进去,不知道为什么……


 
					 
					