如何使用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,
    }
相关推荐
追随远方1 天前
Android平台FFmpeg音视频开发深度指南
android·ffmpeg·音视频
charlie1145141912 天前
编译日志:关于编译opencv带有ffmpeg视频解码支持的若干办法
opencv·ffmpeg·音视频·imx6ull·移植教程
追随远方3 天前
Android平台FFmpeg视频解码全流程指南
android·ffmpeg·音视频
urhero4 天前
Python+ffmpeg 实现给视频添加字幕
ffmpeg·音视频·python编程·视频编辑·实用视频工具·添加字幕
追随远方4 天前
Android NDK版本迭代与FFmpeg交叉编译完全指南
android·ffmpeg
带鱼工作室4 天前
ffmpeg多媒体(音视频)处理常用命令
ffmpeg·音视频
批量小王子4 天前
2025-05-07-FFmpeg视频裁剪(尺寸调整,画面比例不变)
ffmpeg·音视频
人间花木6 天前
1. 视频基础知识
c++·ffmpeg·音视频·视频基础知识
追随远方6 天前
详解 FFMPEG 交叉编译 `FLAGS` 和 `INCLUDES` 的作用
android·ffmpeg·myeclipse·音频编解码
LDM>W<8 天前
Easy云盘总结篇-文件上传01
java·spring boot·学习·ffmpeg