FFmpeg 命令详解

FFmpeg是一款跨平台的开源音视频处理工具,可在命令行中使用,也可通过多种编程语言进行调用,如Python、Java等。

1 流协议

  • 流协议
    • 一种标准化的传递方法,用于分解视频为多个块,将其发送给视频播放器,播放器重新组合播放。
    • 编解码器是指视频压缩技术,即使不需要使用流协议,视频也需要使用编解码器进行编码和解码。
    • RTMP (Real-Time Messaging Protocol)
      • 流地址格式示例:rtmp://example.com/live/stream
      • RTMP是一种传统的流媒体协议,通常用于实时直播。
      • 低延迟,无需缓冲,兼容性较差,不适合大规模观众。
    • WebSocket
    • HTTP-FLV
    • HLS (HTTP Live Streaming)
      • 流地址格式示例:https://example.com/video/stream.m3u8。
      • 适合多种设备和操作系统,例如:移动设备、桌面浏览器、以及智能电视。
      • 兼容性强,安全性高,支持自适应比特率流,延迟较高,不适合视频采集。
      • HLS是苹果公司推出的流媒体协议,适用于iOS设备和其他平台。
    • DASH (Dynamic Adaptive Streaming Over HTTP) / MPEG-DASH
      • 流地址格式示例:https://example.com/video/stream.mpd。
      • DASH是一种开放标准的流媒体协议,逐渐取代了MPEG-DASH。
      • 支持自适应比特率流,适应性强,可定制性高,不兼容苹果设备。
    • WebRTC (Web Real-Time Communications)
      • 一种现代实时通信协议,用于浏览器间的实时音视频通信,通常不使用URL来传输流。
      • 适合实时视频聊天和会议应用,灵活性强,支持实时低延迟流,可能存在兼容性问题。
    • MSS (Microsoft Smooth Streaming)
      • 流地址格式示例:http://example.com/video/stream.ism/Manifest。
      • 微软推出的一种流媒体协议,支持自适应比特率流,已逐渐失去用户。
      • 若非Xbox用户或计划只开发Windows平台的app,否则不推荐使用MSS。
    • HDS (HTTP Dynamic Streaming)
      • 流地址格式示例:http://example.com/video/stream.f4m。
      • HDS增加了码率自适应,并以高质量著称,但延迟并不如RTMP低。
      • Adobe推出的流媒体协议,是RTMP的后继产品,依赖于Flash协议。

2 FFmpeg

  • FFmpeg
    • FFmpeg支持上述流媒体协议的处理和转换,可以用于流媒体的编码、解码、转码、推流和拉流等操作。
    • 官网“https://ffmpeg.org”下载,Windows安装时,需要将安装路径的bin目录设置到Path环境变量中。
    • 提供的命令行工具
      • ffmpeg(音视频编解码器)是FFmpeg提供的核心命令行工具,输出快品质高文件小。
      • ffplay是以FFmpeg框架为基础,外加渲染音视频的库libSDL构建的媒体文件播放器。
      • ffprobe是FFmpeg命令行工具中相对简单的命令工具,用于查看媒体文件格式等信息。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
sudo apt update                               # 更新源,添加源
sudo add-apt-repository ppa:kirillshkrogalev/ffmpeg-next
sudo apt-get install ffmpeg # Ubuntu和Debian安装
sudo yum install ffmpeg # CentOS和Fedora安装
brew install ffmpeg # macOS安装

ffmpeg -version # 查看安装版本
ffmpeg -encoders # 查看编码器和解码器

ffmpeg configure -encoders # 查看支持的编码器
ffmpeg configure -decoders # 查看支持的解码器
ffmpeg configure -protocols # 查看支持的通信协议

ffmpeg configure --help # 查看命令帮助

2-1 安装版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ffmpeg -version                               # 查看安装版本
ffmpeg version 6.0-essentials_build-www.gyan.dev Copyright (c) 2000-2023 the FFmpeg developers
built with gcc 12.2.0 (Rev10, Built by MSYS2 project)
configuration: --enable-gpl --enable-version3 --enable-static --disable-w32threads
--disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-libxml2
--enable-gmp --enable-bzlib --enable-lzma --enable-zlib --enable-libsrt --enable-libssh
--enable-libzmq --enable-avisynth --enable-sdl2 --enable-libwebp --enable-libx264
--enable-libx265 --enable-libxvid --enable-libaom --enable-libopenjpeg --enable-libvpx
--enable-mediafoundation --enable-libass --enable-libfreetype --enable-libfribidi
--enable-libvidstab --enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm
--enable-cuvid --enable-ffnvcodec --enable-nvdec --enable-nvenc --enable-d3d11va
--enable-dxva2 --enable-libvpl --enable-libgme --enable-libopenmpt --enable-libopencore-amrwb
--enable-libmp3lame --enable-libtheora --enable-libvo-amrwbenc --enable-libgsm
--enable-libopencore-amrnb --enable-libopus --enable-libspeex --enable-libvorbis
--enable-librubberband
libavutil 58. 2.100 / 58. 2.100
libavcodec 60. 3.100 / 60. 3.100
libavformat 60. 3.100 / 60. 3.100
libavdevice 60. 1.100 / 60. 1.100
libavfilter 9. 3.100 / 9. 3.100
libswscale 7. 1.100 / 7. 1.100
libswresample 4. 10.100 / 4. 10.100
libpostproc 57. 1.100 / 57. 1.100

2-2 文件播放

1
2
3
4
5
6
7
8
9
10
11
12
13
ffplay test.mp3                               # 播放音频
ffplay test.pcm -f s16le -ar 32000 -ac 2 # 播放双通道32K的PCM音频数据

ffplay test.mp4 # 播放视频
ffplay test.mp4 -loop 10 # 循环播放10次视频
ffplay test.mp4 -autoexit # 播放完成后自动退出
ffplay test.mp4 -x 320 -y 240 # 以长320x宽240的大小播放
ffplay test.mp4 -window_title testplayer # 将窗口标题设置为testplayer

# ffplay的音画同步的实现方式:以音频为主时间轴、以视频为主时间轴、以外部时钟为主时间轴作为同步源
ffplay test.mp4 -sync audio # 指定使用以音频为基准进行音视频同步的方式播放视频
ffplay test.mp4 -sync video # 指定使用以视频为基准进行音视频同步的方式播放视频
ffplay test.mp4 -sync ext # 指定使用外部时钟为基准进行音视频同步的方式播放视频

2-3 媒体信息

1
2
3
4
5
6
7
8
9
10
11
# -v error:只输出错误级别的日志信息,而不输出其他级别的日志信息,例如警告(warning)、信息(info)等

ffprobe test.mp4 # 查看mp4文件信息

ffprobe test.mp4 -show_format # 输出格式信息
ffprobe test.mp4 -show_frames # 显示帧信息,pict_type=I说明是关键帧
ffprobe test.mp4 -show_frames -v error # key_frame=1是IDR帧,key_frame=0是Non-IDR帧

ffprobe test.mp4 -show_streams # 显示每个流的具体信息
ffprobe test.mp4 -show_packets # 显示包信息
ffprobe test.mp4 -print_format json # 以Json格式显示mp4文件信息

(1) 查看信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# -select_streams v:表示选择所有视频流
# -select_streams v:0:表示选择视频流中的第一个流
# -count_frames:统计视频流中的帧数
# -show_entries stream=nb_frames:显示指定条目
# nb_frames:意味着只显示视频流中的帧数
# bit_rate:只显示视频流的比特率
# nb_read_frames:显示已读取的帧数
# -show_entries frame=pkt_pts_time:获取视频帧的相关信息
# pkt_pts_time:获取视频帧的显示时间戳信息
# pict_type:获取视频帧的图片类型信息
# -of default=nokey=1:noprint_wrappers=1:指定了输出的格式,包括不显示键和不打印包装器
# -of csv=print_section=0:以CSV格式输出数据,但不包括标题行
# -skip_frame nokey:在跳过帧时不显示关键帧信息
# Windows命令:findstr /n "I" | for /f "tokens=1 delims=:" %a in ('findstr /n "I"') do @echo %a
# Linux命令:grep -n I | cut -d ':' -f 1

# 查看视频总帧数
ffprobe test.mp4
-v error -select_streams v:0 -count_frames
-show_entries stream=nb_frames -of default=nokey=1:noprint_wrappers=1

# 查看视频比特率
ffprobe test.mp4
-v error -select_streams v:0
-show_entries stream=bit_rate -of default=noprint_wrappers=1:nokey=1

# 查看key frame帧数
ffprobe test.mp4
-v error -select_streams v:0 -count_frames
-show_entries stream=nb_read_frames -of default=nokey=1:noprint_wrappers=1 -skip_frame nokey

# 查看key frame所在的时间(***Windows下好像显示不出来,Linux下正常)
ffprobe test.mp4
-v error -select_streams v:0 -skip_frame nokey
-show_entries frame=pkt_pts_time
ffprobe test.mp4
-v error -select_streams v:0 -skip_frame nokey
-show_entries frame=pkt_pts_time -of csv=p=0
ffprobe test.mp4
-v error -select_streams v:0 -skip_frame nokey
-show_entries frame=pkt_pts_time -of csv=print_section=0
ffprobe -v error -select_streams v:0 -show_entries frame=pkt_pts_time -of csv test.mp4

# 查看key frame分布的情况,Windows与Linux
ffprobe test.mp4 -v error -show_frames | find "pict_type"
ffprobe test.mp4 -v error -show_frames | grep pict_type

# 查看key frame所在的帧数,Windows与Linux(***显示内容不一样)
ffprobe test.mp4
-v error -select_streams v -show_frames
-show_entries frame=pict_type -of csv | findstr /n "I" |
for /f "tokens=1 delims=:" %a in ('findstr /n "I"') do @echo %a
ffprobe test.mp4
-v error -select_streams v -show_frames
-show_entries frame=pict_type -of csv | grep -n I | cut -d ':' -f 1

# 查看视频中关键帧所在的帧数(***Windows和Linux下显示内容不一样)
ffprobe -v error -select_streams v:0 -show_entries frame=pkt_pts_time,pict_type -of csv test.mp4

(2) 内容解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 查看mp4文件信息
ffprobe test.mp4
...
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'test.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
creation_time : 2023-04-17T08:50:27.000000Z
Hw : 1
:
bitRate : 16000000
:
maxrate : 16000000
:
te_is_reencode : 1
:
encoder : Lavf58.76.100

# 该视频文件的时长是31秒880毫秒,开始播放时间是0,整个文件的比特率是11745Kbit/s
Duration: 00:00:31.88, start: 0.000000, bitrate: 11745 kb/s

# 第一个流是视频流,编码格式是H264格式(封装格式为AVC1)
# 每一帧的数据表示为yuv420p,分辨率为1920x1080,这路流的比特率为11649Kbit/s,帧率为每秒钟30帧
Stream #0:0[0x1](und): Video: h264(Main)(avc1/0x31637661), yuv420p(tv, bt709, progressive),
#1920x1080 [SAR 1:1 DAR 16:9], 11649 kb/s, 30 fps, 30 tbr, 15360 tbn (default)
Metadata:
creation_time : 2023-04-17T08:50:27.000000Z
handler_name : VideoHandler
vendor_id : [0][0][0][0]

# 第二个流是音频流,编码方式是ACC(封装格式为MP4A)
# 采用的Profile是LC规格,采样率44.1KHz,声道立体声,这路流的比特率95Kbit/s
Stream #0:1[0x2](und): Audio: aac(LC)(mp4a/0x6134706D),
#44100 Hz, stereo, fltp, 95 kb/s(default)
Metadata:
creation_time : 2023-04-17T08:50:27.000000Z
handler_name : SoundHandler
vendor_id : [0][0][0][0]

2-4 参数说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
-i                                            # 指定输入流
-y # 若输出流已存在,则覆盖流
-t 60 # 指定时长为60秒
# 输出格式可以包括但不限于mp4、avi、mov、mkv、flv、mpeg、wmv、webm
-f mp4 # 指定输出格式为mp4

-map 0 # 将输入文件的所有流映射到输出文件
-map 0:v # 指定第一个输入文件的视频流
-map 0:a # 指定第一个输入文件的音频流
-map 0:v:0 # 指定视频文件的第一个视频流
-map 0:a:0 # 指定视频文件的第一个音频流
-map [v] -map [a] # 将输入文件中的特定视频流和音频流映射到输出文件中

# 作为推流工具时一定要加上该参数,否则ffmpeg会按最高速率不停地向流媒体发送数据
-re # 以源文件固有帧率发送数据
-ss 00:01:30 # 指定从输入流的00:01:30开始处理

(1) 视频参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
-s 320x240                                    # 指定分辨率为320x240(w*h)
-r 30 # 指定帧速率为30帧每秒
-b 200k # 指定比特率为200kbit/s

-an # 去除音频流
-vn # 去除视频流
-vb 200k # 指定视频比特率为200kbit/s

# ffmpeg -encoders | findstr /i video # Windows下查看系统支持的所有视频编码器
# ffmpeg -encoders | grep -i video # Linux下查看系统支持的所有视频编码器
# ffmpeg -decoders | findstr /i video # Windows下查看系统支持的所有视频解码器
# ffmpeg -decoders | grep -i video # Linux下查看系统支持的所有视频解码器
-c:v libx264 # 指定视频编码器为libx264,解码器同理,新版
-vcodec libxvid # 指定视频编码器为libxvid,解码器同理,旧版

# 质量控制的取值范围在0~51之间,0代表无损,18~28代表合理,数值越大画质会越差
-crf 23 # 用于视频编码中的质量控制

# 视频质量包括:ultrafast、superfast、veryfast、faster、fast、medium、slow、slower、veryslow
# 与veryslow相比,placebo以极高的编码时间为代价,只换取了大概1%的视频质量提升
# 针对特定类型,例如电影、动画等:slow比medium提升5%~10%,slower比slow提升5%,veryslow比slower提升3%
-preset medium # 指定输出的视频质量为medium,会影响文件的生成速度

# 常见比例:4:3(标准屏幕)、21:9(超宽屏)、9:16(竖屏)、2.35:1(电影院标准宽屏)、2.39:1(电影院宽屏)
-aspect 16:9 # 指定视频高宽比为16:9(宽屏高清)

(2) 音频参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 对于MP3格式,常见的比特率有128kbps、192kbps、256kbps和320kbps等,较低比特率会导致音频质量下降
-ab 128k # 设置音频比特率为128kbps,kbit/s与kbps等价
-an # 去除音频流

-ar 8000 # 设置音频采样率为8000Hz
-ac 1 # 设置为单声道,1是单声道,2是立体声
-aq 0 # 设置音频的压缩质量,0为最高质量,9为最低质量

# ffmpeg -encoders | findstr /i audio # Windows下查看系统支持的所有音频编码器
# ffmpeg -encoders | grep -i audio # Linux下查看系统支持的所有音频编码器
# ffmpeg -decoders | findstr /i audio # Windows下查看系统支持的所有音频解码器
# ffmpeg -decoders | grep -i audio # Linux下查看系统支持的所有音频解码器
-c:a acc # 指定音频编码器为acc,解码器同理,新版
-acodec mp3 # 指定音频编码器为mp3,解码器同理,旧版

3 获取信息

1
2
3
4
5
6
7
8
9
10
11
# Windows下查看本地视频信息,而不生成实际的输出文件
ffmpeg -i test.mp4 -f null NULL
# Windows下查看远程视频信息,而不生成实际的输出文件
ffmpeg -i http://220.161.87.62:8800/hls/0/index.m3u8 -f null NULL

# Linux下查看本地视频信息,而不生成实际的输出文件
ffmpeg -i test.mp4 -f null /dev/null
# Linux下查看远程视频信息,而不生成实际的输出文件
ffmpeg -i http://220.161.87.62:8800/hls/0/index.m3u8 -f null /dev/null

# 不加“-f null Null”会在最后显示“At least one output file must be specified”

4 拼接合并

  • 拼接合并
    • 拼接
      • 通常指的是将多个视频文件按顺序连接在一起,形成一个长视频。
      • 在FFmpeg中,可以使用concat协议,或者filter来实现视频的拼接。
    • 合并
      • 指的是将多个视频文件合并成一个画中画或分屏的效果,也可以是将多个音频轨道合并成一个音频文件。
      • FFmpeg中可以使用filter实现视频合并,例如:overlay filter实现画中画效果,amix filter实现音频混合。
    • 拼接更多指的是将视频按顺序连接在一起,而合并更多指的是将视频进行叠加或混合。
    • 拼接或合并前【注意事项】
      • 确保所有视频的参数匹配,包括分辨率、帧率、像素格式等,不匹配时需先使用滤镜对视频进行调整。
      • 要求输入视频使用相同的编解码格式,如果不同,则需要重新编码视频,以确保编解码格式保持一致。
      • 确保视频的时长和帧率匹配,以避免拼接或合并后出现播放速度不一致的问题。
      • 不同的视频格式需使用不同的处理方式,确保输入视频的格式兼容并符合要求。
      • 若视频中包含音频,需确保音频的参数匹配,并在拼接或合并时正确的处理音频。
      • 在拼接或合并时,需要注意保持视频质量,避免出现画面失真或压缩损失等情况。

4-1 视频拼接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# -qscale 4:设置视频质量的参数,数值越小质量越高
# -vbsf h264_mp4toannexb:指定视频比特流过滤器的参数,将H.264编码的视频流转换为Annex B格式
# -absf aac_adtstoasc:指定音频比特流过滤器的参数,将AAC编码的音频流转换为ADTS格式
# -filter_complex:指定复杂滤镜图的参数,允许用户在一个命令中应用多个滤镜,以实现更复杂的视频处理
# [0:0][0:1] [1:0][1:1] [2:0][2:1] concat=n=3:v=1:a=1 [v][a]:将3个视频流连接在一起并保留音频
# [0:0][1:0][2:0][3:0] concat=n=4:v=1 [v]:使用concat滤镜功能,将4个视频流连接在一起

# mp4转mpeg,使用mpeg拼接
ffmpeg -i test1.mp4 -qscale 4 test1.mpg
ffmpeg -i test2.mp4 -qscale 4 test2.mpg
ffmpeg -i "concat:test1.mpg|test2.mpg" -c:v mpeg4 output.mp4

# mp4转ts,使用ts拼接
ffmpeg -i test1.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb test1.ts
ffmpeg -i test2.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb test2.ts
ffmpeg -i "concat:test1.ts|test2.ts" -acodec copy -vcodec copy -absf aac_adtstoasc output.mp4

# 将3个视频拼接成一个很长的视频,有声音(提供的视频文件必须存在音频流,否则报错)
# 报错信息:Stream specifier ':a' in filtergraph description ... [v][a] matches no streams.
ffmpeg -i test1.mp4 -i test2.mp4 -i test3.mp4
-filter_complex '[0:0][0:1] [1:0][1:1] [2:0][2:1] concat=n=3:v=1:a=1 [v][a]'
-map [v] -map [a] output.mp4
# 将4个视频拼接成一个很长的视频,无声音
ffmpeg -i test1.mp4 -i test2.mp4 -i test3.mp4 -i test4.mp4
-filter_complex '[0:0][1:0][2:0][3:0] concat=n=4:v=1 [v]' -map [v] output.mp4

4-2 视频合并

  • 视频合并
    • 当两个视频合并时,各自的音频流处理方式可以分三种情况。
    • 若两个视频的音频流相同,可选择保留其中一个视频的音频流,或将两个音频流混合在一起。
    • 若两个视频的音频流不同,可选择保留其中一个视频的音频流,或将其中一视频的音频静音。
    • 如果想保留两个视频的音频流,可以使用音频混合的方式将其合并,以保留两个视频的声音。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# -lavfi hstack:水平叠加视频
# -lavfi vstack:垂直叠加视频
# [0:a][1:a]amix=inputs=2:duration=longest
# 使用amix滤镜,将两个音频流混合在一起,并指定混合后音频流的持续时间为最长的那个音频流的持续时间
# -strict experimental:某些编码器可能需要此选项来启用实验性功能,新版不再需要此选项
# -filter_complex:指定复杂滤镜图的参数,允许用户在一个命令中应用多个滤镜,以实现更复杂的视频处理
# [0:v]pad=iw*2:ih*1[a];[a][1:v]overlay=w:对第一个视频流进行填充,然后再与第二个视频流进行叠加
# [0:v]pad=iw*3:ih*1[a];[a][1:v]overlay=w[b];[b][2:v]overlay=2.0*w
# 对第一个视频流进行填充,然后与第二个视频流叠加并保存到变量b中,最后b中视频流再与第三个视频流叠加

# 2个视频水平合并,只保留test1.mp4的音频(垂直合并使用vstack参数)
ffmpeg -i test1.mp4 -i test2.mp4 -lavfi hstack hstack.mp4
ffmpeg -i test1.mp4 -i test2.mp4 -filter_complex hstack hstack.mp4
# 保留并合并各自的音频,【首先】需要各自提取视频中的音频
ffmpeg -i test1.mp4 -vn -y -acodec copy audio1.m4a
ffmpeg -i test2.mp4 -vn -y -acodec copy audio2.m4a
# 【然后】合并音频
ffmpeg -i audio1.m4a -i audio2.m4a
-filter_complex "[0:a][1:a]amix=inputs=2:duration=longest" audio3.mp3
# 【最后】将合并音频audio3.mp3再合并回原先已合并的视频hstack.mp4中
ffmpeg -i hstack.mp4 -i audio3.mp3 -c:v copy -c:a aac -strict experimental output.mp4

# 3个视频水平合并,只保留test1.mp4的音频
ffmpeg -i test1.mp4 -i test2.mp4 -i test3.mp4 -lavfi hstack=inputs=3 output.mp4

# 横向合并2个视频
ffmpeg -i test1.mp4 -i test2.mp4
-filter_complex "[0:v]pad=iw*2:ih*1[a];[a][1:v]overlay=w" output.mp4
# 竖向合并2个视频
ffmpeg -i test1.mp4 -i test2.mp4
-filter_complex "[0:v]pad=iw:ih*2[a];[a][1:v]overlay=0:h" output.mp4

# 横向合并3个视频
ffmpeg -i test1.mp4 -i test2.mp4 -i test3.mp4
-filter_complex "[0:v]pad=iw*3:ih*1[a];[a][1:v]overlay=w[b];[b][2:v]overlay=2.0*w" output.mp4
# 竖向合并3个视频
ffmpeg -i test1.mp4 -i test2.mp4 -i test3.mp4
-filter_complex "[0:v]pad=iw:ih*3[a];[a][1:v]overlay=0:h[b];[b][2:v]overlay=0:2.0*h" output.mp4

# 2x2方式排列合并4个视频
ffmpeg -i test1.mp4 -i test2.mp4 -i test3.mp4 -i test4.mp4
-filter_complex "[0:v]pad=iw*2:ih*2[a];
[a][1:v]overlay=w[b];[b][2:v]overlay=0:h[c];[c][3:v]overlay=w:h" output.mp4

4-3 添加水印

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# movie=test.jpg[logo];[in][logo]overlay=10:10:1[out]
# overlay=10:10:1:logo位于左上角处,左距10像素,上距10像素,1表示logo透明度
# [0:v][1:v]overlay=10:10:enable='between(t,0,5)':[1:v]将test.jpg看成一个视频流
# 将第二个视频流叠加到第一个视频流的(10,10)位置上,并且叠加操作发生在视频的0秒到5秒之间
# -ignore_loop 0:指定循环播放
# -filter_complex overlay=0:H-h:叠加到底部并指定位置,0和H-h分别指横纵坐标的起始位置
# drawtext=fontfile=test.ttf:text='添加文字水印':x=100:y=10:fontsize=24:fontcolor=yellow:shadowy=2
# 设置水印的字体样式、文本内容、位置、字体大小、字体颜色和阴影效果

# 添加图片水印,需要提供test.jpg
ffmpeg -i test.mp4 -vf "movie=test.jpg[logo];[in][logo]overlay=10:10:1[out]" output.mp4
# Linux下可能警告:EOF timestamp not reliable
# 这是由于movie滤镜无法准确获取test.jpg的时长信息而引起的
# 可以使用enable选项来手动设置overlay滤镜的生效时间段
ffmpeg -i test.mp4
-i test.jpg -filter_complex "[0:v][1:v]overlay=10:10:enable='between(t,0,5)'" output.mp4
# 添加图片水印,需要提供test.jpg
ffmpeg -i test.mp4 -i test.jpg -filter_complex overlay output.mp4
# 添加图片水印,需要提供test.jpg
ffmpeg -i test.mp4
-vf "movie=test.jpg[logo];[in][logo]overlay=10:10:1[out]" -acodec copy output.mp4

# 添加GIF,需要提供test.gif
ffmpeg -i test.mp4 -ignore_loop 0 -i test.gif -filter_complex overlay=0:H-h output.mp4

# 添加文字水印,需要提供test.ttf
ffmpeg -i test.flv
-vf "drawtext=fontfile=test.ttf:text='添加文字水印':
x=100:y=10:fontsize=24:fontcolor=yellow:shadowy=2" output.mp4

5 画面旋转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# -metadata:s:v rotate="90":表示将视频的旋转属性设置为90度
# -vf "transpose=1":表示使用transpose滤镜将视频顺时针旋转90度
# -vf hflip:表示使用FFmpeg框架中的hflip滤镜将视频进行水平翻转

# 旋转90°
ffmpeg -i test.mp4 -metadata:s:v rotate="90" -codec copy output.mp4

# 顺时针旋转90°
ffmpeg -i test.mp4 -vf "transpose=1" output.mp4
# 逆时针旋转90°
ffmpeg -i test.mp4 -vf "transpose=2" output.mp4

# 水平翻转
ffmpeg -i test.mp4 -vf hflip output.mp4
# 垂直翻转
ffmpeg -i test.mp4 -vf vflip output.mp4

# 顺时针旋转90°后再水平翻转
ffmpeg -i test.mp4 -vf "transpose=3" output.mp4
# 逆时针旋转90°后再水平翻转
ffmpeg -i test.mp4 -vf "transpose=0" output.mp4

6 视频转码

  • 视频转码
    • 转文件格式
      • 通常指的是改变视频文件的容器格式,即改变视频数据的封装方式,但不会改变视频的编码方式。
      • 可能影响视频兼容性和功能,但不改变视频的压缩算法,常见格式包括MP4、AVI、FLV、MKV等。
    • 转编码格式
      • 通常指改变视频文件的编码方式,即改变视频数据的压缩格式以及算法,而不改变视频的容器格式。
      • 可能影响视频质量、大小和兼容性,但不改变文件类型,常见格式有H.264、H.265、MPEG-4等。
    • 转编码格式主要关注视频数据的压缩和编码方式,而转文件格式主要关注视频数据的封装以及存储方式。

6-1 转文件格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# ffmpeg -i [input_file] [output_file]:基本命令,建议带其他参数,如编解码器、视频质量等
# -bsf:v h264_mp4toannexb:定义比特流过滤器,将H.264编码的视频流转换为MP4格式的AnnexB格式
# -loglevel error:用于设置日志级别,控制输出的详细程度
# quiet:最低的日志级别,不输出任何信息
# panic:只输出致命错误信息
# fatal:只输出致命错误信息和错误信息
# error:只输出错误信息
# warning:输出警告信息和错误信息
# info:输出详细信息,包括警告信息、错误信息和一般信息
# verbose:输出更多详细信息
# debug:输出调试信息,最详细的日志级别

# 3gp转avi
ffmpeg -i test.3gp -f avi -vcodec libxvid -acodec mp3 -ar 22050 output.avi
# mkv转avi
ffmpeg -i test.mkv -vcodec copy -acodec copy -bsf:v h264_mp4toannexb output.avi

# h264转ts
ffmpeg -i test.h264 -c:v libx264 -c:a aac output.ts
# wmv转flv
ffmpeg -i test.wmv -c:v flv -c:a libmp3lame output.flv
# avi转mpeg
ffmpeg -i test.avi -aspect 16:9 -maxrate 2M -bufsize 5M output.mpeg

# mp3转pcm
# Linux下可能警告:Estimating duration from bitrate, this may be inaccurate
# 这是由于FFmpeg在处理MP3输入文件时,根据比特率来估算持续时间,但这种估算可能不准确导致
ffmpeg -i test.mp3 -f s16le -acodec pcm_s16le -ar 44100 output.pcm
ffmpeg -i test.mp3 -f s16le -acodec pcm_s16le -ar 44100 -hide_banner -loglevel error output.pcm

# mp3转wav
# Linux下可能警告:Estimating duration from bitrate, this may be inaccurate
ffmpeg -i test.mp3 output.wav
ffmpeg -i test.mp3 -hide_banner -loglevel error output.wav

(1) flv转其他

1
2
3
4
5
6
7
8
9
10
11
12
13
# -b:v 640k:设置视频的比特率为640kbps
# -b:a 128k:设置音频的比特率为128kbps

# flv转mp4
ffmpeg -i test.flv -b:v 640k output.mp4

# flv转mp4
ffmpeg -i test.flv
-b:v 200k -ac 2 -r 25 -vcodec h264 -acodec mp3 -b:a 128k -ar 44100 output.mp4

# flv转3gp
ffmpeg -i test.flv
-b:v 200k -ac 1 -r 25 -vcodec h263 -acodec aac -b:a 128k -ar 8000 -s 176x144 output.3gp

(2) 其他转3gp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# mpeg转3gp
# Linux下可能警告:Past duration 0.748665 too large
# 这是由于视频文件本身的问题,或是在视频处理过程中出现了一些意外情况
# FFmpeg检测到时间戳过大的情况,可能会导致视频处理过程中的一些不确定性和错误
ffmpeg -i test.mpeg
-y -ar 22500 -r 15 -ac 2 -s 176x144 -c:v h263 -b:v 128k -c:a aac -b:a 24k -f 3gp output.3gp

# wmv转3gp
ffmpeg -i test.wmv
-y -ar 08000 -r 15 -ac 1 -s 176x144 -ab 12200 -acodec libamr_nb -b:v 128k output.3gp

# avi转3gp
ffmpeg -i test.avi
-y -ar 08000 -r 25 -ac 1 -s 352x288 -ab 32k
-vcodec h263 -acodec libopencore_amrnb -b:v 128k output.3gp

(3) mp4转其他

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# -c copy:指定复制原始编解码器而不进行重新编码,以避免质量损失或加快转换速度
# -c:v copy -c:a copy:在不重新编码的情况下,直接从源文件中复制视频流和音频流到输出文件中
# -acodec copy -vcodec copy:在不重新编码的情况下,直接从源文件中复制音频流和视频流到输出文件中
# -q:v 2:设置视频的质量,取值范围是0到31,0表示最高质量,31表示最低质量

# mp4转avi
ffmpeg -i test.mp4 output.avi
# mp4转mkv
ffmpeg -i test.mp4 -c copy output.mkv

# mp4转flv
ffmpeg -i test.mp4 -b:v 640k output.flv
# mp4转flv
ffmpeg -i test.mp4 -c:v libx264 -ar 22050 -crf 28 output.flv
# mp4转flv
ffmpeg -i test.mp4 -acodec copy -vcodec copy -f flv output.flv

# mp4转ts
ffmpeg -i test.mp4 -c:v copy -c:a copy output.ts
# mp4转wmv
ffmpeg -i test.mp4 -c:v wmv2 -b:v 1024k -c:a wmav2 -b:a 192k output.wmv
# mp4转h264
ffmpeg -i test.mp4 -c:v libx264 -c:a aac -crf 23 -preset medium -b:v 1M output.h264
# mp4转3gp
ffmpeg -i test.mp4 -s 176x144 -vcodec h263 -r 25 -b:v 12200 -ab 12200 -ac 1 -ar 8000 output.3gp

# mp4转mpeg
ffmpeg -i test.mp4 -c:v mpeg2video -c:a mp2 -q:v 2 output.mpg[mpeg]
# Linux下需正确设置VBV缓冲区大小,否则警告:VBV buffer size not set, using default size of 130KB.
ffmpeg -i test.mp4 -c:v mpeg2video -c:a mp2 -q:v 2 -maxrate 4000k -bufsize 1835k output.mpg

(4) 其他转mp4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# -vf "setpts=PTS-STARTPTS":部分用于设置时间戳,以确保从第一个帧开始计算时间戳
# -bsf:a aac_adtstoasc:将ACC音频流从MPEG-2传输流转换为原始的MPEG-4文件格式
# -movflags +faststart:在输出的MP4文件中启用快速启动,使视频在网络上的播放更加流畅

# avi转mp4
ffmpeg -i test.avi -c copy -map 0 output.mp4
# h264转mp4
ffmpeg -i test.h264 -c:v libx264 -crf 23 -preset medium -vf "setpts=PTS-STARTPTS" output.mp4
# mkv转mp4
ffmpeg -i test.mkv -y -vcodec copy -acodec copy output.mp4
# wmv转mp4
ffmpeg -i test.wmv -c:v libx264 -crf 23 -c:a aac output.mp4

# ts转mp4
ffmpeg -i test.ts -f mp4 -vcodec copy -acodec copy output.mp4
# Linux下可能出现如下警告信息,这是在处理H.264视频流时出现了SPS(序列参数集)引用错误
# 通常是由于输入文件的视频流中缺少SPS,或SPS数据损坏导致的,是输入文件本身的编码问题
# [h264 @ 0x556d2ecaefc0] non-existing SPS 0 referenced in buffering period
# [h264 @ 0x556d2ecaefc0] SPS unavailable in decode_picture_timing
# [h264 @ 0x556d2ecaefc0] non-existing SPS 0 referenced in buffering period
# [h264 @ 0x556d2ecaefc0] SPS unavailable in decode_picture_timing
# 可以控制不输出任何信息来规避,但若希望视频质量得以保证,最好想法设法进行更好地处理
ffmpeg -i test.ts -f mp4 -vcodec copy -acodec copy -loglevel quiet output.mp4

# m3u8转mp4
ffmpeg -i http://220.161.87.62:8800/hls/0/index.m3u8
-c copy -bsf:a aac_adtstoasc -movflags +faststart output.mp4
# Linux下可能出现如下警告信息,这是由于HLS视频流的编码格式不兼容或存在问题
# [NULL @ 0x556bbcc2f4e0] SPS unavailable in decode_picture_timing
# [NULL @ 0x556bbcc2f4e0] non-existing PPS 0 referenced
# [h264 @ 0x556bbcc31220] SPS unavailable in decode_picture_timing
# [h264 @ 0x556bbcc31220] non-existing PPS 0 referenced
# [h264 @ 0x556bbcc31220] decode_slice_header error
# [h264 @ 0x556bbcc31220] no frame!
# [NULL @ 0x556bbcc2f4e0] ...
# [NULL @ 0x556bbcc2f4e0] non-existing SPS 0 referenced in buffering period
# [NULL @ 0x556bbcc2f4e0] SPS unavailable in decode_picture_timing
# [h264 @ 0x556bbcc31220] non-existing SPS 0 referenced in buffering period
# [h264 @ 0x556bbcc31220] SPS unavailable in decode_picture_timing

6-2 转编码格式

1
2
3
4
5
6
7
8
# mpeg4编码转h264编码
ffmpeg -i test.mp4 -vcodec h264 output.mp4

# h264编码转mpeg4编码
ffmpeg -i test.mp4 -vcodec mpeg4 output.mp4

# 当前的编码格式转换为H.265视频编码和AAC音频编码
ffmpeg -i test.mp4 -c:v libx265 -c:a aac output.mp4

7 图像处理

  • 图像处理
    • FFmpeg截取视频帧的两种seeking方式。
    • 在输入文件之前使用-ss参数:影响视频解码的速度,因为FFmpeg会在指定时间点之前进行解码。
    • 在输入文件之后使用-ss参数:会在解码后丢弃指定时间点之前的帧,可能导致一些性能上的差异。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 将视频第5秒的一帧图像截取出来,使用关键帧,速度快,Linux下可能不识别
ffmpeg -ss 00:01:05 -i test.mp4 -frames:v 1 output.jpg

# 将视频第5秒的一帧图像截取出来,逐帧解码,直到05秒才截取,速度慢
# Linux下可能警告:deprecated pixel format used, make sure you did set range correctly
ffmpeg -i test.mp4 -ss 00:00:05 -frames:v 1 output.jpg

# 从视频第8秒的位置截取一张大小为350x240的缩略图
# Linux下可能警告:deprecated pixel format used, make sure you did set range correctly
ffmpeg -i test.mp4 -y -f image2 -ss 8 -t 0.001 -s 350x240 output.jpg

# 提取图片,提取的图像帧率为1帧/秒,输出格式为image2
# Linux下可能警告:deprecated pixel format used, make sure you did set range correctly
# 出现该警告是由于在视频处理过程中,使用了不推荐的过时像素格式,可能会导致颜色范围设置不正确
# 设置像素格式、使用最邻近算法进行缩放、使用-color_range设置颜色范围,可解决警告(***好像无效)
ffmpeg -i test.avi -r 1 -f image2 image-%3d.jpeg
ffmpeg -i test.avi -r 1 -f image2 -pix_fmt yuvj420p image-%3d.jpeg
ffmpeg -i test.avi -r 1 -f image2 -sws_flags neighbor image-%3d.jpeg

# 把视频的前30帧截取转换成一个gif图片
# fps=10,scale=320:-1:flags=lanczos:设置视频帧率为10,尺寸320x240,并使用lanczos算法进行缩放
ffmpeg -i test.mp4 -vf "fps=10,scale=320:-1:flags=lanczos" -t 3 output.gif

7-1 图转视频

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# -framerate 30:设置视频的帧率为30帧每秒
# test%d.jpg:%d表示从0开始依次递增的数字
# -vf "scale=500:424":将视频尺寸缩放为500x424
# -pix_fmt yuv420p:设置视频的像素格式为yuv420p
# -pattern_type glob:使用glob模式来匹配不规则命名的图片文件

# 规则名称的图片转视频,不规则名称可以使用*.jpg
ffmpeg -i test%d.jpg -vf "scale=500:424" -c:v libx264 output.mp4
# 比特率为200k,像素格式为yuv420p
ffmpeg -framerate 30 -i test%d.jpg
-c:v libx264 -r 30 -b:v 200k -pix_fmt yuv420p output.mp4
# 假设视频时长为5秒,总帧数N=30帧/秒×5秒=150帧
ffmpeg -framerate 30 -i test%d.jpg
-c:v libx264 -r 30 -b:v 200k -pix_fmt yuv420p -t 00:00:05 output.mp4

# 不规则名称图片转视频,Linux方法
ffmpeg -framerate 25 -pattern_type glob -i "*.jpg"
-c:v libx264 -r 30 -pix_fmt yuv420p output.mp4
ffmpeg -framerate 10 -pattern_type glob -i "*.jpg" output.mp4
cat *.jpg | ffmpeg -f image2pipe -i - output.mp4

7-2 格式转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# jpg转png
ffmpeg -i test.jpg output.png

# jpg转webp
ffmpeg -i test.jpg -pix_fmt yuv420p output.webp

# png转jpg
# Linux下可能警告:deprecated pixel format used, make sure you did set range correctly
ffmpeg -i test.png -pix_fmt yuvj420p output.jpg

# png转bmp
ffmpeg -i test.png output.bmp

# png转webp
ffmpeg -i test.png -pix_fmt yuv420p output.webp

# png转tiff
ffmpeg -i test.png output.tiff

# png转raw
ffmpeg -i test.png -vcodec png -vcodec rawvideo -f rawvideo -pix_fmt rgb24 output.raw

# webp转jpg
# Linux下可能警告:deprecated pixel format used, make sure you did set range correctly
ffmpeg -i test.webp -pix_fmt yuvj420p output.jpg

# webp转png
ffmpeg -i test.webp output.png

8 其他操作

1
2
3
4
5
6
7
8
9
10
11
12
13
# 音频和视频混合
# Linux下可能警告:Guessed Channel Layout for Input Stream #0.0 : stereo
# 由于FFmpeg猜测输入音频流的通道布局时,无法确定输入音频流的通道布局,因此使用了默认的立体声布局
ffmpeg -i test.wav -i test.avi output.mpg
# 若能确定输入音频流的通道布局,可使用-map选项显式地指定输入流的通道布局,例如立体声(左声道和右声道)
# 0:a:0表示输入文件0(即test.wav)的第一个音频流,1:v:0表示输入文件1(即test.avi)的第一个视频流
ffmpeg -i test.wav -i test.avi -map 0:a:0 -map 1:v:0 -maxrate 3.5M -bufsize 4M output.mpg

# 设置视频屏幕高宽比
ffmpeg -i test.mp4 -aspect 16:9 output.mp4

# 重新设置key frame interval
ffmpeg -i test.mp4 -vcodec libx264 -x264-params keyint=1:scenecut=0 -acodec copy output.mp4

8-1 视频压缩

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# -threads 4:使用4个线程进行处理,有助于加快视频转码的速度
# -vf scale=640:-2:将视频缩放到宽度为640像素,高度按比例自动调整
# 考虑到libx264要求高度是偶数,让软件自动计算得出一个接近等比例的偶数高

ffmpeg -i test.mp4 -vcodec h264 output.mp4
ffmpeg -i test.mp4 -b:v 1000k -b:a 128k output.mp4
ffmpeg -i test.mp4 -vcodec h264 -vf scale=640:-2 -threads 4 output.mp4

ffmpeg -i test.mp4 -vcodec libx264 -crf 28 -acodec aac output.mp4
ffmpeg -i test.flv -vcodec libx264 -crf 28 -acodec aac output.flv
ffmpeg -i test.avi -vcodec libx264 -crf 28 -acodec aac output.avi
ffmpeg -i test.wmv -vcodec libx264 -crf 28 -acodec aac output.wmv
ffmpeg -i test.3gp -vcodec libx264 -crf 28 -acodec aac output.3gp

ffmpeg -i test.mpeg -vcodec libx264 -crf 28 -acodec aac output.mpeg
# Linux下可能警告:VBV buffer size not set, using default size of 130KB
# 由于将MPEG格式的视频文件转换为H.264格式时,检测到源文件中没有设置VBV缓冲区大小导致
# 尝试增加VBV缓冲区大小,让VBV缓冲区足够大,从而消除没有设置VBV缓冲区大小导致的警告
ffmpeg -i test.mpeg
-vcodec libx264 -crf 28 -acodec aac -b:v 5000k -bufsize 10000k output.mpeg
# Linux下可能警告:VBV bufsize set but maxrate unspecified, ignored
# 这个警告是由于设置了VBV缓冲区大小,但没有设置最大比特率(maxrate)而引起的警告
# VBV缓冲区大小和最大比特率是一对相关参数,一起控制视频的比特率和帧率,确保视频能正常播放
# 设置VBV缓冲区大小为10000k,最大比特率为5000k,保证输出视频文件的比特率和帧率控制正确
ffmpeg -i test.mpeg
-vcodec libx264 -crf 28 -acodec aac -b:v 5000k -bufsize 10000k -maxrate 5000k output.mpeg

8-2 视频剪切

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 从视频第3秒开始剪切,持续5秒
ffmpeg -i test.mp4 -ss 3 -t 5 -codec copy output.mp4
# 从视频第3秒开始剪切,持续5秒
ffmpeg -i test.avi -ss 00:00:03 -t 00:00:05 -vcodec copy -acodec copy output.avi

# -ss 00:00:05:指定剪切视频的开始时间为00:00:05
# -to 00:00:10:指定剪切视频的结束时间为00:00:10
ffmpeg -i test.mp4 -ss 00:00:05 -to 00:00:10 -c:v copy -c:a copy output.mp4
ffmpeg -i test.flv -ss 00:00:05 -to 00:00:10 -c:v copy -c:a copy output.flv
ffmpeg -i test.avi -ss 00:00:05 -to 00:00:10 -c:v copy -c:a copy output.avi
ffmpeg -i test.wmv -ss 00:00:05 -to 00:00:10 -c:v copy -c:a copy output.wmv
ffmpeg -i test.3gp -ss 00:00:05 -to 00:00:10 -c:v copy -c:a copy output.3gp

ffmpeg -i test.mpeg -ss 00:00:05 -to 00:00:10 -c:v copy -c:a copy output.mpeg
# Linux下可能警告:VBV buffer size not set, using default size of 130KB
# 下述方法都试过了,均无效,貌似遇到MPEG文件问题,FFmpeg都不好处理
ffmpeg -i test.mpeg
-ss 00:00:05 -to 00:00:10 -c:v libx264 -b:v 2000k -c:a aac -b:a 128k output.mpeg
ffmpeg -i test.mpeg -ss 00:00:05 -to 00:00:10 -c:v mpeg2video -c:a mp2 output.mpeg
ffmpeg -i test.mpeg -ss 00:00:05 -to 00:00:10 -c:v copy -c:a copy -bufsize 2000k output.mpeg

8-3 倒放与加减速

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# [0:v]reverse[v]:将输入的第一个视频流倒转,然后将结果输出为一个新的视频流
# -vf reverse:将视频逆序播放
# -af areverse:将音频逆序播放
# -vf setpts=PTS/2:将视频的播放速度减半
# -af atempo=2:将音频的播放速度加倍
# PTS即Presentation Time Stamp,是视频帧的显示时间戳,调整倍速范围0.25~4倍
# -filter:v "setpts=0.5*PTS":将视频的播放速度减半
# -filter:v "setpts=2.0*PTS":将视频的播放速度加倍
# -filter:a "atempo=0.5":将音频的播放速度减半
# -filter:a "atempo=2.0":将音频的播放速度加倍

# 视频倒放,无音频
ffmpeg -i test.mp4 -filter_complex [0:v]reverse[v] -map [v] -preset superfast output.mp4
# 视频倒放,音频不变
ffmpeg -i test.mp4 -vf reverse output.mp4
# 音频倒放,视频不变
ffmpeg -i test.mp4 -af areverse -map 0 -c:v copy output.mp4
# 音频和视频同时倒放
ffmpeg -i test.mp4 -af areverse -vf reverse -preset superfast output.mp4

# 视频加速播放
ffmpeg -i test.mp4 -af atempo=2 -vf setpts=PTS/2 output.mp4
ffmpeg -i test.mp4 -filter:v "setpts=0.5*PTS" -filter:a "atempo=2.0" output.mp4
# 视频减速播放
ffmpeg -i test.mp4 -an -filter:v setpts=0.5*PTS output.mp4
ffmpeg -i test.mp4 -filter:v "setpts=2.0*PTS" -filter:a "atempo=0.5" output.mp4

8-4 分离音视频流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 分离视频流
ffmpeg -i test.mp4 -vcodec copy -an output.mp4

# 分离音频流
ffmpeg -i test.mp4 -acodec copy -vn output.mp3
# Linux下可能报错:Invalid audio stream. Exactly one MP3 audio stream is required.
# 需要确保只有一个有效的MP3音频流,如果输入文件不包含MP3音频流,则需要将其转码为MP3格式
ffmpeg -i test.mp4 -acodec libmp3lame -vn output.mp3

# 去掉视频中的音频
ffmpeg -i test.mp4 -an output.mp4

# 去掉视频中的音频
ffmpeg -i test.avi -an -vcodec copy output.avi

9 推流拉流

  • 推流拉流
    • 推流:将直播内容推送至服务器的过程。
    • 拉流:服务器已有直播内容,用指定地址将其拉取的过程,VLC媒体播放器官网
    • MediaMTX实时媒体服务器:https://github.com/bluenviron/mediamtx/releases
      • 下载安装版本,Windows:mediamtx_v1.4.0_windows_amd64.zip。
      • 解压后,在本地双击运行“mediamtx.exe”,进行本地推流的模拟。
      • 下载安装版本,Ubuntu:mediamtx_v1.4.0_linux_amd64.tar.gz。
      • 命令解压:tar -zxvf mediamtx_v1.4.0_linux_amd64.tar.gz
      • 在当前解压的目录中执行命令开启本地媒体服务器:./mediamtx
1
2
3
4
5
6
7
8
# MediaMTX支持的推流协议,及对应使用的端口
2024/01/18 15:58:42 INF MediaMTX v1.4.0
2024/01/18 15:58:42 INF configuration loaded from C:\Users\Admin\Downloads\mediamtx.yml
2024/01/18 15:58:42 INF [RTSP] listener opened on :8554 (TCP), :8000 (UDP/RTP), :8001 (UDP/RTCP)
2024/01/18 15:58:42 INF [RTMP] listener opened on :1935
2024/01/18 15:58:42 INF [HLS] listener opened on :8888
2024/01/18 15:58:42 INF [WebRTC] listener opened on :8889 (HTTP), :8189 (ICE/UDP)
2024/01/18 15:58:42 INF [SRT] listener opened on :8890 (UDP)

9-1 推流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# -rtsp_transport tcp:指定RTSP传输协议为TCP
# -stream_loop -1:无限循环播放输入的视频流,-1表示无限循环,注意放在“-i test.mp4”之前
# -auto-alt-ref 0:告诉FFmpeg对视频进行WebM格式编码时不要使用禁止VP8编码中的备用参考帧特性

# 使用RTSP进行推流
ffmpeg -re -i test.mp4 -c copy -f rtsp rtsp://127.0.0.1:8554/stream
ffmpeg -re -i test.mp4 -c copy -f rtsp -rtsp_transport tcp rtsp://127.0.0.1:8554/stream

# 使用RTMP进行推流
ffmpeg -re -i test.mp4 -c copy -f flv rtmp://127.0.0.1:1935/stream
# Linux下可能警告:Failed to update header with correct duration ... correct filesize.
# 报告无法更新头部信息以包含正确的持续时间和文件大小,可以尝试使用特定的编码参数进行转码
ffmpeg -re -i test.mp4 -c:v libx264 -c:a aac -f flv rtmp://127.0.0.1:1935/stream

# 使用HLS进行推流
ffmpeg -re -i test.mp4 -c copy -f hls http://127.0.0.1:8888/stream.m3u8
# Linux下可能警告:No HTTP method set, hls muxer defaulting to method PUT.
# 警告说明在使用HLS(HTTP Live Streaming)复用器时,未设置HTTP方法,默认使用PUT方法
ffmpeg -re -i test.mp4 -c copy -f hls -method POST http://127.0.0.1:8888/stream.m3u8
# Linux下可能警告:Cannot use rename on non file protocol ... temporary partial files

# 使用WebRTC进行推流
ffmpeg -re -i test.mp4 -c copy -f webm http://127.0.0.1:8889/stream
# Linux下可能报错:Only VP8 or VP9 video and Vorbis or Opus ... are supported for WebM.
# WebM仅支持VP8或VP9视频编解码器、Vorbis或Opus音频编解码器和WebVTT字幕,确保使用支持的编解码器
ffmpeg -re -i test.mp4
-c:v libvpx -c:a libvorbis -auto-alt-ref 0 -f webm http://127.0.0.1:8889/stream

# 使用SRT进行推流
ffmpeg -re -i test.mp4 -c copy -f mpegts srt://127.0.0.1:8890
# Linux下可能报错:srt://127.0.0.1:8890: Protocol not found
# 这是由于FFmpeg在Linux下对SRT URL方案的支持不完整
# 尝试使用SRT协议的另一种写法,即通过UDP指定端口进行传输,并添加参数设置数据包大小
ffmpeg -re -i test.mp4 -c copy -f mpegts "srt://127.0.0.1:8890?pkt_size=1316"
# Linux下可能报错:srt://127.0.0.1:8890?pkt_size=1316: Protocol not found
# 尝试使用SRT的传统端口模式,而非URL形式,mode=listener参数告诉FFmpeg在监听模式下等待传入连接
ffmpeg -re -i test.mp4 -c copy -f mpegts "srt://:8890?pkt_size=1316&mode=listener"
# Linux下可能报错:srt://:8890?pkt_size=1316&mode=listener: Protocol not found(***方法都无效)

# 使用RTSP进行循环推流
ffmpeg -re -stream_loop -1 -i test.mp4 -c copy -f rtsp rtsp://127.0.0.1:8554/stream

9-2 拉流

1
2
3
4
5
6
7
8
# RTSP推流
ffmpeg -re -stream_loop -1 -i test.mp4 -c:v copy -c:a aac -f rtsp rtsp://127.0.0.1:8554/stream

# 推流后,可以使用VLC媒体播放器进行拉流播放,或ffplay命令播放
ffplay rtsp://127.0.0.1:8554/stream

# -timeout 30000000:设置超时时间为30秒,单位微秒(us),该选项必须放在“-i”参数之前
ffmpeg -timeout 30000000 -i rtsp://127.0.0.1:8554/stream -c copy output.mp4

FFmpeg 命令详解
https://stitch-top.github.io/2024/01/11/ce-shi-gong-ju/tt07-ffmpeg-de-ying-yong/tt07-01-ffmpeg-ming-ling-xiang-jie/
作者
Dr.626
发布于
2024年1月11日 23:15:13
许可协议