如何使用ffmpeg命令行进行录屏

录屏软件,我们去网上下载,发现有很多软件都是要收费的!但是录屏功能很难做吗?为啥都需要收费呢?

于是我整了个小demo,用于实现基础的屏幕录制功能。

思路很简单,考虑到 FFMpeg.exe是一个非常成熟的音视频处理软件,而且是开源的。我们完全可以基于 FFMpeg.exe来实现我们的要求。

使用 FFMpeg录屏通常有两种方式:

  1. 基于 gdigrab (使用CPU录制)

  2. 基于 DirectShow (使用显卡录制)

考虑到 gdigrab方式实现更简单,更轻量,兼容性也更好,所以我们采用 gdigrab方案。DirectShow方案需要额外下载 screen-capture-recorder!

基于该方法,主要核心就是 ffmpeg的命令编写,具体命令如下:

ffmpeg -f gdigrab -framerate 30 -offset_x 0 -offset_y 0 -video_size 1920x1080 -i desktop -r 30 -vcodec libx264 -pix_fmt yuv420p -y "output.mp4"

命令说明:

cs 复制代码
//注意:ffmpeg 的命令输入,也需要考虑输入顺序的。先指定输入参数,再指定输出参数。
    // -f 表示指定文件格式或采集数据的设备,如果是 DirectShow 方案,就需要指定为 screen-capture-recorder。    
    //对于输入,如果不指定-f, ffmpeg 会根据输入数据,来判断数据的封装格式.    
    //对于输出,如果不指定-f, ffmpeg 也可以通过输出文件名进行推导.    
//ffmpeg -formats 可以列出所有的formats
// -framerate 指定录制的视频帧率
// -offset_x -offset_y 指定录制的区域左上角坐标
// -video_size 指定录制的视频尺寸
// -i 指定从哪儿采集数据,它是一个文件索引号。这里是指定输入的视频源。(i 表示input,不一定是表示视频文件,表示输入。如也可以是音频文件输入等)
// -r 指定帧率
// -vcodec 指定编码格式。libx264 这种格式录制出来的视频,清晰度更清晰,占用的文件大小更小,推荐使用。
// -pix_fmt 像素格式,常规使用yuv420p
// -y 表示强制覆盖,如果输出文件已经存在,就覆盖
// 输出文件路径。这里需要注意下:输出文件路径带上 双引号 ,防止不合法路径将命令拆分了。

为了更方便代码实现相关编码,下面贴上核心代码(附加音视频合并的示例代码):

cs 复制代码
/// <summary>
    /// 视频录制命令构建类
    /// </summary>
    public class FFMpegScreenRecordArgs : FFMpegArgs
    {
        public int Framerate { get; set; }

        public int Rate { get; set; }

        public Rect Region { get; set; }

        public VideoCodec Codec { get; set; }

        public PixelFormat PixelFormat { get; set; }

        public string SavePath { get; set; }

        public override string ToArgs()
        {
            ArgsBuilder.SetRecordDevice();
            ArgsBuilder.SetFramerate(Framerate);
            ArgsBuilder.SetRecordRect((int)Region.Left, (int)Region.Top);
            ArgsBuilder.SetVideoSize((int)Region.Width, (int)Region.Height);
            ArgsBuilder.SetInput();
            ArgsBuilder.SetRate(Rate);
            ArgsBuilder.SetCodec(Codec);
            ArgsBuilder.SetPixFarmat(PixelFormat);
            return $"{ArgsBuilder.GetArgs()} -y {SavePath}\"";
        }
    }

    /// <summary>
    /// 音视频合成构建类
    /// </summary>
    public class FFMpegAVSynthesisArgs : FFMpegArgs
    {
        public string InputAudioPath { get; set; }
        public string InputVideoPath { get; set; }
        public string OutputVideoPath { get; set; }

        public override string ToArgs()
        {
            this.ArgsBuilder.SetInput(InputAudioPath);
            this.ArgsBuilder.SetInput(InputVideoPath);
            this.ArgsBuilder.SetCodec(AudioCodec.copy);
            this.ArgsBuilder.SetCodec(VideoCodec.copy);

            return $"{ArgsBuilder.GetArgs()} \"{OutputVideoPath}\"";
        }
    }

    //基础命名构建类
    public class FFmpegArgsBuilder
    {
        protected readonly List<string> Args = new List<string>();
        public FFmpegArgsBuilder AddArg<T>(string Key, T Value)
        {
            Args.Add($"-{Key} {Value}");

            return this;
        }

        public virtual string GetArgs()
        {
            return string.Join(" ", Args);
        }

        public void Reset()
        {
            Args.Clear();
        }

        #region args

        public FFmpegArgsBuilder SetRecordRect(int x, int y)
        {
            AddArg("offset_x", x);
            AddArg("offset_y", y);
            return this;
        }

        public FFmpegArgsBuilder SetVideoSize(int width, int height)
        {
            AddArg("video_size", $"{width}x{height}");
            return this;
        }

        public FFmpegArgsBuilder SetInput(string input = "desktop")
        {
            AddArg("i", input);
            return this;
        }

        public FFmpegArgsBuilder SetFramerate(int framerate)
        {
            AddArg("framerate", framerate);
            return this;
        }

        public FFmpegArgsBuilder SetRate(int rate)
        {
            AddArg("r", rate);
            return this;
        }

        public FFmpegArgsBuilder SetRecordDevice(string device = "gdigrab")
        {
            AddArg("f", device);
            return this;
        }

        public FFmpegArgsBuilder SetCodec(VideoCodec codec)
        {            
            AddArg("vcodec", codec);
            return this;
        }

        public FFmpegArgsBuilder SetCodec(AudioCodec audioCodec)
        {
            AddArg("acodec", audioCodec);
            return this;
        }

        public FFmpegArgsBuilder SetPixFarmat(PixelFormat x)
        {
            AddArg("pix_fmt", x);
            return this;
        }
        
        #endregion
    }

    //像素格式
    public enum PixelFormat
    {
        ///<summary>
        /// yuv420p
        ///</summary>
        yuv420p,
        //......省略......
    }

    //编码格式
    public enum VideoCodec
    {
        ///<summary>
        ///      libx264
        ///</summary>
        libx264,

        ///<summary>
        ///      copy
        ///</summary>
        copy,
        //......省略......
    }

    /// <summary>
    ///     Audio codec ("ffmpeg -codecs")
    /// </summary>
    public enum AudioCodec
    {
        ///<summary>
        ///      copy
        ///</summary>
        copy,
    }
相关推荐
韩曙亮12 小时前
【FFmpeg】FFmpeg 内存结构 ③ ( AVPacket 函数简介 | av_packet_ref 函数 | av_packet_clone 函数 )
ffmpeg·音视频·avpacket·av_packet_clone·av_packet_ref·ffmpeg内存结构
oushaojun216 小时前
ubuntu中使用ffmpeg和nginx推流rtmp视频
nginx·ubuntu·ffmpeg·rtmp
莫固执,朋友17 小时前
网络抓包工具tcpdump 在海思平台上的编译使用
网络·ffmpeg·音视频·tcpdump
lxkj_202418 小时前
修改ffmpeg实现https-flv内容加密
网络协议·https·ffmpeg
cuijiecheng201818 小时前
音视频入门基础:MPEG2-TS专题(6)——FFmpeg源码中,获取MPEG2-TS传输流每个transport packet长度的实现
ffmpeg·音视频
VisionX Lab1 天前
数据脱敏工具:基于 FFmpeg 的视频批量裁剪
python·ffmpeg·音视频
柳鲲鹏2 天前
全网首发:Ubuntu编译跨平台嵌入式支持ffmpeg的OpenCV
linux·ubuntu·ffmpeg
冰山一脚20132 天前
ffplay音频SDL播放处理
ffmpeg
cuijiecheng20182 天前
音视频入门基础:MPEG2-TS专题(7)——FFmpeg源码中,读取出一个transport packet数据的实现
ffmpeg·音视频
Maxwellhang2 天前
【java-ffmpeg】java 内存测试和集成
java·ffmpeg·jni