如何使用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,
    }
相关推荐
因我你好久不见11 小时前
springboot java ffmpeg 视频压缩、提取视频帧图片、获取视频分辨率
java·spring boot·ffmpeg
cuijiecheng201818 小时前
音视频入门基础:MPEG2-TS专题(21)——FFmpeg源码中,获取TS流的视频信息的实现
ffmpeg·音视频
cuijiecheng201819 小时前
音视频入门基础:AAC专题(13)——FFmpeg源码中,获取ADTS格式的AAC裸流音频信息的实现
ffmpeg·音视频·aac
流氓也是种气质 _Cookie1 天前
uniapp blob格式转换为video .mp4文件使用ffmpeg工具
ffmpeg·uni-app
网络安全queen1 天前
网络安全-企业环境渗透2-wordpress任意文件读&&FFmpeg任意文件读
安全·web安全·ffmpeg
yerennuo2 天前
FFmpeg库之ffmpeg
qt·ffmpeg
韩曙亮2 天前
【FFmpeg】解封装 ① ( 封装与解封装流程 | 解封装函数简介 | 查找码流标号和码流参数信息 | 使用 MediaInfo 分析视频文件 )
ffmpeg·音视频·视频流·mediainfo·解封装·码流
yerennuo2 天前
FFmpeg 框架简介和文件解复用
ffmpeg
悠着,大嘟嘟2 天前
FFmpeg 视频解码详解
ffmpeg·音视频
小白旗2 天前
ffmpeg翻页转场动效的安装及使用
ffmpeg·gl-transition·xfade·转场动效