ffmpeg使用

ffmpeg使用说明

介绍

ffmpeg是一个音视频处理软件,很多工具内部都是调用这个
可以剪辑,裁剪,转码音视频,甚至能压缩图片

文档: https://ffmpeg.org/ffmpeg-all.html

安装

官网 http://ffmpeg.org/download.html
本地 游戏开发\软件\辅助软件\ffmpeg
一般下载 release full 版本
用来处理音视频转码,合并,分割等
主要包含2个工具:

  • ffprobe
    获取音视频信息,比如分辨率、码率等
  • ffmpeg
    对音视频进行处理,包括裁剪、截取、转码等

ffprobe使用

该工具主要用来获取音视频信息

  • 参数说明:

    • -v [loglevel] 设置日志等级
      ffprobe -v quiet 不想让log影响输出显示,一般设置为 quiet
    • -of [format] 设置输出打印格式,可选 json xml
      ffprobe -of xml
    • -select_streams [stream_type] 只选择 stream_specifier 指定的流。可选 a v, 该选项只影响那些与流相关的选项(例如:show_streams, show_packets, 等)。
      ffprobe -show_streams -select_streams a INPUT 只显示音频流信息
      ffprobe -show_streams -select_streams v INPUT 只显示视频流信息
    • -show_format 显示输入多媒体流的容器格式信息
    • -show_frames 显示输入多媒体流中的每一帧以及字幕的信息
    • -show_packets 显示输入多媒体流中每一个包的信息,输出信息和show_frames差不多
    • -show_streams 显示输入多媒体流中每一个流的信息
    • -show_data 显示有效载荷数据,以十六进制和ASCII转储。与 ‘-show_packets’ 结合使用,它将dump 包数据;与 ‘-show_streams’ 结合使用,它将 dump codec 附加数据。
    • -show_programs 显示输入多媒体流中程序以及它们的流的信息
    • -count_frames 计算每一个流中的帧数,在相应的段中进行显示
      如:ffprobe -show_streams -count_frames -i sample.mp4
      n_read_frames会有数据,否则为N/A
    • -count_packets 计算每一个流中的包数,在相应的段中进行显示
    • -show_error 显示探测输入文件时的错误信息
  • 常用命令:

    • 显示视频流信息
      ffprobe -show_streams -select_streams v input.mp4 -v quiet
    • 获得视频宽高的代码:
          set inputVideo=%~1
          for /f "tokens=1,2 delims==" %%i in ('ffprobe  -show_streams -select_streams v -v quiet "%inputVideo%"') do (
              if "%%i" == "width" set width=%%j
              if "%%i" == "height" set height=%%j
          )
          echo video width %width%
          echo video height %height%
      

ffmpeg使用

文档: https://ffmpeg.org/ffmpeg-all.html
该工具主要用来对音视频进行处理,包括裁剪、截取、转码等
音频转换,会自动检测格式,ogg会默认用 -acodec libvorbis
ffmpeg -i aaa.wav -vn aaa.ogg

  • 主要参数

    • -i 设定输入流
    • -f 设定输出格式
    • -ss 截取时间 如 -ss 00:00:15
    • -t 截取时长 如 -t 00:00:05 ,一定要写在 "-i"前面,否则会有问题
    • -to 截止时间,一定要写在"-i"前面!!否则就和"-t"一样
    • -c 编码,相当于-acodec和-vcodec,放在输入文件前表示输入编码,放在输出文件前表示输出编码
      -c:v 等于 -vcodec , -c:a 等于 -acodec
    • -y 覆盖已有文件
    • map 选择输出流,没有该参数将启用默认流选择行为
      默认流选择行为每种类型仅选择 1 个流,比如有3个输入流,则只会选择1个
          -map 0:0  第一个输入文件的第一个流
          -map 0:2?  如果第一个输入文件的第3个流存在就选择
          -map 0 -map -0:1  选择第1个视频中的除第2个流外的其它流
          -map 0:v:0  第一个输入文件的第一个视频流
          -map 1:a:2  第二个输入文件的第三个音频流
          -map 1:s:1  第二个输入文件的第二个字幕流
      
  • 视频参数

    • -b 设定视频流量(码率),默认为200Kbit/s
    • -r 设定帧速率,默认为25
    • -s 设定画面的宽与高
    • -aspect 设定画面的比例
    • -vn 不处理视频
    • -vcodec 设定视频编解码器,未设定时则使用与输入流相同的编解码器 ,可以用 -vcodec copy 表示跟输入编码一致
      放在输入文件前表示输入编码,放在输出文件前表示输出编码
      ffmpeg –encoders 可以查看所有编码,常用有 libx264
    • -crf 设置视频输出质量,[0-51] 0表示无损,常用范围18-24,18表示视觉无损,一般建议22,差一点建议24
      经测试压缩率为 20:42%;22:31%;24:23.4%
    • -preset 指定处理速度,速度越慢,压缩率越高,选项有 placebo veryslow slower slow medium fast faster veryfast superfast ultrafast
      一般最慢用 veryslow,建议用 slower,placebo以极高的编码时间为代价,只换取了大概1%的视频质量提升。slow 与 medium相比提升了5%~10%;
      slower 与 slow相比提升了5%;veryslow 与 slower相比提升了3%。
  • 音频参数

    • -ar 设定采样率
    • -ac 设定声音的Channel数
    • -acodec 设定声音编解码器,未设定时则使用与输入流相同的编解码器 ,可以用 -acodec copy 表示跟输入编码一致
      放在输入文件前表示输入编码,放在输出文件前表示输出编码
    • -an 不处理音频
  • 时间格式

    • [HH:]MM:SS[.m…]
      比如 12:10:11.123 表示 12时10分11.123秒
      10 表示10秒
      10:11 表示10分11秒
    • S+[.m…][s|ms|us]
      比如 10.12 表示 10.12秒
      10.12ms 表示 10.12毫秒
      10.12us 表示 10.12微秒
  • 过滤器参数

    • vf
      视频过滤器参数,针对单个视频应用过滤器,后面可以跟多个过滤器参数,参数之间用,分隔

      • 语法: [视频流1]过滤器1=过滤器1参数,过滤器2=过滤器2参数[视频流1输出];[视频流2]过滤器3=过滤器3参数[视频流2输出]
        也就是不同视频流的处理用分号隔开,同一个视频流中的不同的滤镜用逗号隔开,滤镜的不同参数用冒号隔开,参数名和值用等号隔开,视频流用中括号括起来
      • 示例:
        -vf “[in]split[split_main][split_delogo];[split_delogo]trim=start=360:end=371,delogo=0:0:640:480[delogoed];[split_main][delogoed]overlay=eof_action=pass[out]”
        把输入流拆分成2个流,一个去除水印后再叠加到另一个上面
    • filter_complex
      复杂过滤器参数,可以针对多个视频应用过滤器,后面跟多个过滤器参数,参数之间用;分隔,参数开始必须指定应用过滤器的视频流,参数结束可以指定过滤后的视频流名称

      • filter_complex “[0:v]scale=640:400[v0];color=c=black:s=640x400[bg];[v0][bg]xstack=inputs=2:layout=0_0|w0_0[out]”
        包含有3个过滤器参数, [0:v]scale=640:400[v0] 处理的视频流为 [0:v] 也就是第1个视频的视频流,scale 为过滤器,[v0] 把处理后的视频流赋值给 [v0] 后续可通过 [v0] 引用该视频流
    • split
      将1个视频流拆分成多个,每个视频流都跟原视频流一样
      比如 你可能拆成2个,把1个缩小后叠加到另一个上
      [0:v]split=2[ref][out]; 把视频流[0:v] 拆成2个视频流 [ref] 和 [out]
      [ref]split[ref1][ref2]; 把视频流 [ref] 拆成2个视频流 [ref1] 和 [ref2]

    • trim
      剪辑视频流,剪出某个时间段

      • 语法 : trim=start=0:end=1000
        start 开始时间,参考上面的时间格式
        end 结束时间,参考上面的时间格式
        duration 输出视频的最长时长
    • scale
      对视频流缩放

      • 语法: scale=ow:oh[:force_original_aspect_ratio=decrease/increase]
        ow oh 输出视频的大小,填-1时会等比计算高度,填-2时会等比计算高度并保证为偶数
        可以使用变量 iw ih dar(输入宽高比)
        由于ffmpeg只支持宽/高为偶数,因此如果是等比缩放,要这样写 trunc(ow/2)*2 ,trunc 是取整函数
        force_original_aspect_ratio 强制等比缩放,=increase 最终屏幕>=设置的分辨率,=decrease 最终屏幕<=设置的分辨率
      • -vf “scale=720:1280” 跟-s 720x1280 效果是一样的,都会对视频进行拉伸
    • scaleref
      对视频流缩放,以另一个视频流的大小为基准,也就是变量中可以用 main_w main_h 引用另一个视频的宽高
      scale=ow:oh[:force_original_aspect_ratio=decrease/increase][ref]
      [ref] 表示做为基准的视频流

    • pad
      对视频画布进行填充,也就是本来视频跟画布一样大,填充后画布更大,多出来的部分填充黑边
      pad=ow[:oh[:ox[:oy[:color]]]]
      ow oh 画布宽高
      ox oy 黑边起点相对画布左上点坐标为 [-ox,-oy]
      black 画布颜色

    • color
      生成纯色的视频流,常用于背景
      color=c=black:s=640x400[bg] 生成颜色为黑色,大小为640x400的纯色视频流并赋值给 [bg]

    • xstack
      多路视频流合并,视频之间不会重叠,空间不够会缩小,空间太大不放大,只是摆在左上角
      [v0][bg]xstack=inputs=2:layout=0_0|w0_0[out] [v0]和[bg] 视频流合并,总共2路视频,[v0] 摆在 0_0 位置,[bg] 摆在 w0_0 位置

    • hstack
      多路视频流合并,视频之间不会重叠,高度必须相同,否则报错
      [0:v][1:v]hstack=inputs=2[out] 第1个视频的视频流和第2个视频的视频流合并,赋值给 [out]

    • vstack
      多路视频流合并,视频之间不会重叠,宽度必须相同,否则报错
      [0:v][1:v]hstack=inputs=2[out] 第1个视频的视频流和第2个视频的视频流合并,赋值给 [out]

    • overlay
      把某个视频流叠加到另一个视频流上

      • 语法:overlay[=x:y[:rgb={0, 1}]]
        x(可选) 从左上角的水平坐标,默认值为 0
        y(可选) 从左上角的垂直坐标,默认值为 0
        rgb(可选) 值为 0 表示输入颜色空间不改变,默认为 0;值为 1 表示将输入的颜色空间设置为 RGB
      • 变量说明:如下变量可用在 x 和 y 的表达式中
        main_w 或 W 主输入(背景窗口)宽度
        main_h 或 H 主输入(背景窗口)高度
        overlay_w 或 w overlay 输入(前景窗口)宽度
        overlay_h 或 h overlay 输入(前景窗口)高度
    • delogo
      去除水印,

      • 语法:delogo=x:y:w:h[:t[band:[:show]]]
        x 水印左上角的水平坐标
        y 水印左上角的垂直坐标
        w 水印宽度
        h 水印高度
        show(可选) 1 会显示一个矩形框表示去除范围用于调试,默认是0不显示
      • 示例
            delogo=x=10:y=10:w=100:h=100:show=1
            delogo=10:10:100:100:show=1   按顺序可以省略参数名
            ffmpeg -i input.mp4 -vf "delogo=x=50:y=50:w=150:h=50" -c:a copy output.mp4
        
      • 去除多个水印
        可以有多个 delogo,用逗号隔开
        delogo=10:10:100:100:show=1,delogo=100:100:100:100:show=1
        
      • 去除某个时间段内的水印
        可以配合enable参数来指定条件,下面只去除10到20秒内的水印
        delogo=x=50:y=50:w=150:h=50:enable=‘between(t,10,20)’
    • enable
      这个不是过滤器,而是可以应用到过滤器的参数,可以指定过滤器触发的条件

      • 语法:enable=‘条件表达式’
        • 条件表达式:
          between(参数,起始值,结束值) 在某个时间内
          eq(参数,值) 等于某个时间
          gt(参数,值) 大于某个时间
          gte(参数,值) 大于等于某个时间
          lt(参数,值) 小于某个时间
        • 逻辑运算符
          ! 非
          || 或
          && 与
      • 示例
        ffmpeg -i input.mp4 -vf “delogo=x=50:y=50:w=150:h=50:enable=‘!lt(t,10) || gt(t,90)’” -c:a copy output.mp4
    • amerge
      把多个音频流合并成1个音频流,但是声道数不变,比如 2个音频流各有2个声道,则最终有4个声道
      每个声道的音量被保留
      [0:a][1:a]amerge=inputs=2[a] 把视频1和2的音频流合并,并赋值给[a]

    • amix
      把多个音频流合并成1个音频流,声道数只有一个,比如 2个音频流各有2个声道,则最终有1个声道
      每个原始声道的音量在最终声道中各占 1/4
      [0:a][1:a]amerge=inputs=2[a] 把视频1和2的音频流合并,并赋值给[a]

  • 一些参数性能对比
    与 veryslow相比,placebo以极高的编码时间为代价,只换取了大概1%的视频质量提升。
    这是一种收益递减准则:slow 与 medium相比提升了5%~10%;slower 与 slow相比提升了5%;veryslow 与 slower相比提升了3%。

  • 使用 ffmpeg 时可以在命令行中使用函数:

    • bitand(ow,65534) 做与运算,该代码使ow变偶数
    • trunc(ow) 取整
    • ceil 向上取整
  • 常用命令

    • 有时候网上抓到类似这样的视频地址可以用ffmepg保存
      ffmpeg -i “https://vdn.vzuu.com/SD/49c84c7c-c61a-11e8-8bad-0242ac112a0a.mp4?auth_key=1539832492-0-0-c61c22f39c&expiration=1539832492&disable_local_cache=1” ouput.mp4

    • 获取视频信息
      ffmpeg -i input.mp4 -hide_banner

      • 获取视频时长(bat中)
          ::这里获得的是毫秒
          for /f "tokens=2-5 delims=:., " %%a in ('ffmpeg -i "%inFile%" 2^>^&1 ^| find "Duration:"') do (
              set /a "t=(1%%a%%100*3600+1%%b%%100*60+1%%c%%100)*1000+1%%d0%%1000"
          )
          ::把毫秒转成  hh:mm:ss.ms 格式
          set /a "ms=t%%1000,t/=1000"
          set /a h=t/3600,m=t%%3600/60,s=t%%60,h+=100,m+=100,s+=100,ms+=1000
          set "tt=!h:~1!:!m:~1!:!s:~1!.!ms:~1!"
      
          echo millsecond=%t% ffmpegTime=%tt%
      
      • 获得视频流/音频流时长
            :: 获得视频流时长
            :: %1 视频文件
            :: %2 接收时长的变量名
            :GetVideoDuration
            set %2=
            for /f "tokens=1,2 delims==" %%i in ('ffprobe  -show_streams -select_streams v -v quiet "%~1"') do (
                if "%%i" == "duration" set %2=%%j
            )
            goto :EOF
        
            :GetAudioDuration
            set %2=
            for /f "tokens=1,2 delims==" %%i in ('ffprobe  -show_streams -select_streams a -v quiet "%~1"') do (
                if "%%i" == "duration" set %2=%%j
            )
            goto :EOF
        
    • 选择视频中的流

      • 仅视频流
        ffmpeg -i input.mp4 -map 0:v output.mp4
      • 来自不同文件的视频和音频
        ffmpeg -i video.mp4 -i audio.m4a -map 0:v -map 1:a output.mp4
      • 过滤音频
        ffmpeg -i input.mp4 -map 0 -map -0:a output.mp4
    • 去掉视频中的音频
      ffmpeg -i input.mp4 -vcodec copy -an output.mp4
      -an: 去掉音频;-vcodec:视频选项,一般后面加copy表示拷贝

    • 提取视频中的音频
      ffmpeg -i input.mp4 -acodec copy -vn output.mp3
      -vn: 去掉视频;-acodec: 音频选项, 一般后面加copy表示拷贝

    • 音视频合成
      ffmpeg -y –i input.mp4 –i input.mp3 -c copy output.mp4
      -y 覆盖输出文件

    • 剪切视频,更精确的时间用 0:1:30.100,-c copy等价于 -vcodec copy -acodec copy
      ffmpeg -ss 0:1:30 -t 0:0:20 -i input.mp4 -c copy -avoid_negative_ts 1 output.mp4
      -ss 开始时间; -t 持续时间; -to 结束时间, -t 和 -to 同时存在则 -t 生效
      时间可以用 hh:mm:ss.xxx 格式,也可以直接用多少秒,比如 180.1 等价于 3:00.1

      • 要注意参数顺序问题
        • (推荐)-ss 和 -to 要放在 -i 的前面,从源文件中定位,会搜索到最近的关键帧,默认开启了 -accurate_seek
          此时会解码并精准定位到指定时间,但如果使用-c copy,则不会解码,直接从开始点前面最近的关键帧开始
        • 如果 -ss 和 -to 都在 -i 后面,则是从解码后的文件中定位,时间精确但速度慢,如果使用-c copy,
          则不会在剪裁处插入关键帧,也就是剪裁后的视频前面可能有几秒是不动的,可以加 -copyts
        • 如果 -ss在-i 前面而 -to在-i 的后面,则-to表示时长,因为定位到-ss后时间戳重置为0
          此时可以加 -copyts 参数来达到你要的效果
      • 使用 -c copy 的时侯,如果视频结尾不是关键帧,则视频后面会多出一段空白
        此时可以加 -avoid_negative_ts 1 来解决,它会找到下一个关键帧来补全视频
        但有一个问题,如果把一个视频分成2半,则这2个视频会有点交集
        想要彻底解决该问题,就不能用 -c copy,而是要 -c:v libx264 -c:a aac 重新编码
    • 剪裁视频,剪裁区域为 [x,y,x+ow,y+oh]
      ow默认为iw;oh默认为ih;x 默认为 (iw-ow)/2; y默认为 (ih-oh)/2;
      ow oh 可以使用变量 iw ih dar(输入视频宽高比)
      ffmpeg -i input.mp4 -vf crop=ow[:oh[:x[:y[:keep_aspect]]]] output.mp4
      ffmpeg -i input.mp4 -vf crop=iw/3:ih/2 output.mp4

    • 视频截图
      ffmpeg –i test.mp4 –f image2 -t 0.001 -s 320x240 image-%3d.jpg
      -s 设置分辨率; -f 强迫采用格式fmt;

    • 视频分解为图片
      ffmpeg –i test.mp4 –r 1 –f image2 image-%3d.jpg
      -r 指定截屏频率

    • 将图片合成视频
      ffmpeg -f image2 -i image%d.jpg output.mp4

    • 视频拼接,多个视频文件按照时间顺序连接在一起
      把视频文件列在 filelist.txt 中,每行一个文件
      如果视频帧率,屏幕大小不同,则会自动先转成相同再合并
      ffmpeg -f concat -i filelist.txt -c copy output.mp4

    • 视频合并,多个视频流的内容叠加在一起

      • 使用 xstack 进行合并
        保证拼接的视频不重叠,如果空间不够,则视频会缩小,如果空间太大,则视频不放大,只是摆在左上角

        • 简单拼接
          ffmpeg -i video1.mp4 -i video2.mp4 -i video3.mp4 -i video4.mp4 -i video5.mp4 -filter_complex “[0:v][1:v][2:v][3:v][4:v]xstack=inputs=5:layout=0_0|w0_0|0_h0|w0_h0|w0+w1_h0[v];[0:a][1:a][2:a][3:a][4:a]amix=inputs=5[a]” -map [v] -map [a] output.mp4

          • filter_complex 指定拼接参数
            • [0:v] [1:v] 指定要拼接的视频流,[0,v] 指第1个视频中的视频流
            • xstack滤镜用于将输入的视频流进行拼接
              • inputs=5表示有五个输入视频
              • layout用于指定拼接的布局
                • 0_0|w0_0|0_h0|w0_h0|w0+w1_h0表示五个视频的位置
                • 最终视频是矩形,没内容的会填充绿色背景,如果想填充黑色背景,可用 color=c=black:s=640x400[bg] 生成黑色视频流,然后使用 overlay 叠加
            • [v] 将拼接后的视频流赋值给 [v] ,后面要用到
            • [0:a][1:a][2:a][3:a][4:a] 指定音频流
            • amix=inputs=5将输入音频流混合
            • [a] 将混合后的音频流赋值给 [a],后面要用到
              -map [v] -map [a] 指定输出的视频流,音频流,使用filter_complex后,默认选择器没有选择任何视频流和音频流
        • 每个视频自定义缩放
          ffmpeg -i video1.mp4 -i video2.mp4 -i video3.mp4 -i video4.mp4 -i video5.mp4 -filter_complex “[0:v]scale=640:400[v0];[1:v]scale=640:400[v1];[2:v]scale=640:400[v2];[3:v]scale=640:400[v3];[4:v]scale=640:400[v4];color=c=black:s=640x400[bg];[v0][v1][v2][v3][v4][bg]xstack=inputs=6:layout=0_0|w0_0|w0+w1_0|0_h1|w0_h1|w0+w1_h1[out]” -map “[out]” -c:v libx264 output.mp4

          • filter_complex 指定拼接参数
            • [0:v]scale=640:400[v0] 把第1个视频中的视频流缩放后赋值给 [v0]
            • color=c=black:s=640x400[bg] 使用黑色填充一个640x400 的视频流并赋值给[bg]
            • [v0][v1][v2][v3][v4][bg]xstack=inputs=6:layout=0_0|w0_0|w0+w1_0|0_h1|w0_h1|w0+w1_h1[out] 使用前面缩放后的视频流按一定布局拼接后赋值给 [out]
              -map “[out]” 指定[out]做为输出的视频流
      • 使用 vstack 进行合并
        视频垂直排列,保证视频不重叠,视频必须具有相同的宽度,否则报错
        ffmpeg -i video1.mp4 -i video2.mp4 -i video3.mp4 -i video4.mp4 -filter_complex “[0:v][1:v][2:v][3:v]vstack=inputs=4[v];[0:a][1:a][2:a][3:a]amix=inputs=4[a]” -map [v] -map [a] output.mp4

      • 使用 hstack 进行合并
        视频水平排列,保证视频不重叠,视频必须具有相同的高度,否则报错
        ffmpeg -i video1.mp4 -i video2.mp4 -i video3.mp4 -i video4.mp4 -filter_complex “[0:v][1:v][2:v][3:v]hstack=inputs=4[v];[0:a][1:a][2:a][3:a]amix=inputs=4[a]” -map [v] -map [a] output.mp4

      • 使用 overlay 合并
        把第2个视频叠加到第1个视频中,视频是重叠在一起的,可以实现画中画功能
        ffmpeg -i video1.mp4 -i video2.mp4 -i video3.mp4 -i video4.mp4 -filter_complex"[0:v]pad=iw2:ih2[a];[a][1:v]overlay=w[b];[b][2:v]overlay=0:h[c];[c][3:v]overlay=w:h" output.mp4

        • filter_complex 指定拼接参数
          • [0:v]pad=iw2:ih2[a] 表示把第1个视频中的视频流画布宽度和高度都乘以2,注意视频大小并没有乘以2,并赋值给 [a]
          • [a][1:v]overlay=w[b] 把第2个视频中的视频流跟 [a] 拼接,坐标为 w:0(小w是叠加视频的宽度,大W是主视频的宽度),并赋值给 [b]
          • … 后续不断拼接新视频即可

        ffmpeg -i input.mp4 -i logo.jpg -filter_complex [0:v][1:v]overlay=main_w-overlay_w-10:main_h-overlay_h-10[out] -map [out] -map 0:a -codec:a copy output.mp4
        视频添加水印 main_w-overlay_w-10 视频的宽度-水印的宽度-水印边距;

    • 将视频转为gif
      ffmpeg -i input.mp4 -ss 0:0:30 -t 10 -s 320x240 -pix_fmt rgb24 output.gif
      -pix_fmt 指定编码

    • 将视频前30帧转为gif
      ffmpeg -i input.mp4 -vframes 30 -f gif output.gif

    • 旋转视频
      ffmpeg -i input.mp4 -vf rotate=PI/2 output.mp4

    • 缩放视频,oh不能省略,填-1时会等比计算高度,填-2时会等比计算高度并保证为偶数,可以使用变量 iw ih dar(输入宽高比)
      force_original_aspect_ratio 强制等比缩放,=increase 最终屏幕>=设置的分辨率,=decrease 最终屏幕<=设置的分辨率
      由于ffmpeg只支持宽/高为偶数,因此如果是等比缩放,要这样写 trunc(ow/2)*2 trunc 是取整函数
      -s 720x1280 跟 -vf “scale=720:1280” 效果是一样的,都会对视频进行拉伸
      ffmpeg -i input.mp4 -vf scale=ow:oh[:force_original_aspect_ratio=decrease/increase] output.mp4

    • iw 是输入的宽度,ow是输出宽度, iw/2就是一半;-1 为保持宽高比,如果高度必须是2的整数倍则填-2
      ffmpeg -i input.mp4 -vf scale=iw/2:-1 output.mp4

    • 等比缩放视频,如果输入是 496x368,则输出为 720x534,如果改成increase,则输出为 1725x1280(由于1725是奇数会报错,可用下面填黑边方法处理)
      ffmpeg -i input.mp4 -vf “scale=720:1280:force_original_aspect_ratio=decrease” output.mp4

    • 等比缩放视频,不足部分填充黑边,在上面的基础上填充黑边到分辨率为720x1280
      ffmpeg -i input.mp4 -vf “scale=720:1280:force_original_aspect_ratio=decrease,pad=720:1280:(ow-iw)/2:(oh-ih)/2” output.mp4

    • 视频变速
      ffmpeg -i input.mp4 -filter:v setpts=0.5*PTS output.mp4

    • 音频变速
      ffmpeg -i input.mp3 -filter:a atempo=2.0 output.mp3

    • 音视频同时变速,但是音视频为互倒关系
      ffmpeg -i input.mp4 -filter_complex “[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]” -map “[v]” -map “[a]” output.mp4

    • 视频压缩为h264
      ffmpeg -i D:\src.mov -c:v libx264 -preset veryslow -crf 20 -c:a copy D:\dest1.mp4

    • 下载m3u8文件,也就是一系列ts文件
      ffmpeg -i https://v6.438vip.com/2018/10/17/3JAHPTdvPhQb9LrE/playlist.m3u8 -c copy OUTPUT.mp4

    • 获取音频响度

          for /f tokens^=1^,2^,3^,4^ delims^=^" %%a in ('ffmpeg -hide_banner -i "%~1" -af "loudnorm=I=-16:TP=-1:LRA=11:print_format=json" -f null NUL 2^>^&1 ^| findstr "input_i input_tp input_lra input_thresh target_offset"') do (
              echo %%a %%b %%c %%d
              if "%%b" == "input_i" set _i=%%d
              if "%%b" == "input_tp" set _tp=%%d
              if "%%b" == "input_lra" set _lra=%%d
              if "%%b" == "input_thresh" set _thresh=%%d
              if "%%b" == "target_offset" set _offset=%%d
          )
      
    • 调整音频响度
      先了解下 音频基础知识
      ffmpeg响度调整
      ffmpeg音频过滤器

      • (推荐)方法一: 直接使用别人写的python插件 ffmpeg-normalize
        本质上也是是使用下面提到的loudnorm过滤器

        • 安装 ffmpeg 5.x+ , python 3.8+

        • 把 ffmpeg.exe 添加到环境变量 Path
          可以设置环境变量 FFMPEG_PATH 为 ffmpeg 路径,不设也可以但不能设置错误

        • python 安装插件: pip install ffmpeg-normalize
          帮助文档: https://github.com/slhck/ffmpeg-normalize

        • 调整声音
          ffmpeg-normalize input.mp4 -o output.mp4 -c:a aac -b:a 192k
          调整到EBU R128响度标准中广播常用的 -23
          默认是使用 wav 格式,如果是mp4一般是aac格式,要加 -c:a aac,如果是mp3要加 -c:a libmp3lame
          -b:a 192k 指定比特率,默认128K,192k算比较好的,一般音乐用192k,视频用128k

          ffmpeg-normalize input.mp4 -o output.mp4 -c:a aac -b:a 192k -t -16 -lrt 11 -tp -1
          调整到流行音乐的 I=-16:LRA=11:tp=-1,一般响度范围用 11 就够了,大多数在 6-9
          只有 -t 指定的响度是要匹配的, -tp 和 -lrt 指定的都是最大值,实际值可能差挺多

          ffmpeg-normalize input.mp4 -o output.mp4 -c:a aac -b:a 192k -t -16 --keep-loudness-range-target -tp -1
          调整到流行音乐的 I=-16:tp=-1,但保持原有的响度范围

        • 查看帮助
          ffmpeg-normalize -h

      • 方法二: 直接使用ffmpeg提供的高级过滤器

        • loudnorm
          响度平均标准化,最常用的标准化算法,广泛应用在有线电视/广播

          • 原理
            先计算出整体声音的平均音量,再根据平均音量到期望音量的差值,做为调整的依据,最后使的平均音量达到期望音量的大小,峰值声音调整后有可能被削除波峰
            会先尝试使用线性调整,也就是方法三的直接加音量,如果音量峰值超出设置的峰值就会改用动态调整,也就是类似 dynaudnorm 滤镜
            会把音量小的部分放大倍数大,音量大的部分放大倍数小,各部分音量调整后变得均衡
          • 应用场景
            适合有很多歌曲声音大小不同,通过该过滤器调整成同样的标准
          • 使用:
            需要执行2遍:
            • 第一遍测量、分析音频文件,得到响度标准化所需要的参数
              这里设置标准化为流行音乐的参数 I=-16:LRA=11:tp=-1
              第一遍输出的 normalization_type 一定是 dynamic
                  ffmpeg -hide_banner -i demux.aac -c:a:0 pcm_s24le -af "loudnorm=I=-16:TP=-1:LRA=11:print_format=json" -f null NUL
              
              得到参数如下
                  {
                      "input_i" : "-23.53",
                      "input_tp" : "-13.68",
                      "input_lra" : "3.10",
                      "input_thresh" : "-33.53",
                      "output_i" : "-16.45",
                      "output_tp" : "-6.32",
                      "output_lra" : "2.30",
                      "output_thresh" : "-26.45",
                      "normalization_type" : "dynamic",
                      "target_offset" : "0.45"
                  } 
              
            • 第二遍把得到的参数,填入 loudnorm 的滤镜设置中,对音频做标准化处理
              如果调整后峰值不超出 -tp 设定值,lra不小于原有lra,则采用 linear 处理
              否则使用 dynamic 处理,dynamic 会把 lra 调整到7以下
                  ffmpeg -hide_banner -y -i input.aac -af "loudnorm=I=-16:TP=-1:LRA=11:measured_I=-23.53:measured_tp=-13.68:measured_LRA=3.10:measured_thresh=-33.53:offset=0.45:print_format=summary" output.aac
              
        • dynaudnorm
          动态音频归一化器,使声音整体音量变得均衡

          • 原理
            对输入音频施加一定的增益,以使其峰值幅度达到目标电平,会动态调整增益使安静的部分增益变大,响亮部分增益变小,
            各自增益后都不会超出目标电平且保留各自的动态范围,但是整体的动态范围可能会变
          • 效果
            声音音量小的部分放大倍数大,音量大的部分放大倍数小,各部分音量调整后变得均衡
        • speechnorm

        • volume
          直接增益所有电平

          • 通过 volumedetect 获取音量值
            ffmpeg -i 01.mp3 -af “volumedetect” -vn -sn -dn -f null NUL
          • 根据获取的音量值确定调整的幅度,再使用 volume 调整音量,
            比如 获取到最大音量 -14dB,我们想要调整到 -9dB
            就要 +5dB
            ffmpeg -i 01.mp4 -af “volume=5dB” -c:v copy -c:a aac -cutoff 20000 output.mp4
          • 如果增益到峰值还不是达到需要的响度,可先调整动态范围
            调整动态范围可考虑以下方法
            • compand
              压缩动态范围并调整增益电平
              按电平范围进行压缩,比如 -30到-20区间怎么压缩,-20到-10区间怎么压缩
              跟 acompressor 区别是 compand 是
              acompressor 是

            • acompressor
              压缩器,压缩动态范围
              设定阈值,超出的电平超出部分按多少比例进行压缩

            • alimiter
              限制器,电平大于设定的值会进行压缩

常见问题

  • Too many packets buffered for output stream 0:1.
    有些视频数据有问题,导致视频处理过快,容器封装时队列溢出,常见的是转换rmvb时出现,导致不能转换
    在输出文件前加参数 -max_muxing_queue_size 1000

  • Non-monotonous DTS in output stream 0:1;
    多在合并多个视频文件时出现,这是由于音频码率不同,会导致声音错位或视频快进
    增加音频转换时固定码率,在输出文件前加参数 -ac 1 -ar 48000 表示单声道,采样率为 48000

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值