FFmpeg 视频处理速查表
按类别整理的 FFmpeg 命令集合,适用于视频自动化管道。
可将此作为灵感来源,用于调试 FFmpeg 命令,或探索他人正在开发的自动化媒体应用。
如何使用此速查表?
- 使用目录(建议在 GitHub 的 MD 文件完整视图中查看)浏览主要主题。
- 使用 Ctrl + F 查找所需内容。所有命令、滤镜和标志均在文档中详细解释。若未找到特定说明,则表示该内容出现在文档的其他位置,可通过搜索查找(若仍未找到,请提交问题,我会处理)。
- 所有示例命令均可直接在本地机器上运行,因为它们使用存储在网上的示例文件,而 FFmpeg 能够将这些文件下载到本地。
- 我已为每个命令、过滤器、标志、关键词及解释附上了原始参考资料。您可以利用这些资料深入研究 FFmpeg,以及视频格式相关知识。其中部分发现为本人原创,因此未指定具体参考来源。
- 为了节省空间,使用了下拉箭头。您可以点击它们以获取更详细的信息。浏览器能够搜索这些隐藏部分中的文本,并在需要时显示它们。
- 要充分利用这份速查表,最好将其与您喜欢的LLM(或MCP服务器或AI代理)结合使用。以下是一些实现方式:
- 直接将全文复制到LLM中,让LLM索引此处所有信息。为获得最佳效果,请确保复制MD文件的原始版本。
- 您也可以直接将此文件的URL提供给LLM,让其进行索引。
- 若对特定命令感兴趣,可将其复制到LLM中,并与LLM对话以根据需求调整该命令。
- 您可以在本文件及其提供的参考资料中找到所有命令的详细说明。不过,您仍可将命令复制到聊天界面,让LLM进一步解释。
正如某位Reddit用户所言:
“我知道每次向GPT提问都会消耗资源,但这总比在Stack Exchange上翻阅十年前的答案要好”
关于LLM和FFmpeg
我尽可能多地使用LLM来简化本文件的工作流程,但所有命令和解释均已由我手动测试和审核。其中许多命令我在GPT时代之前就已使用过——这暗示着我已经不年轻了(🙈)
LLMs在处理FFmpeg时存在局限性,因为它有时需要精准度和对细节的关注,而这些在线上很难找到,尤其是在处理复杂滤镜时。我喜欢将其作为一个高级搜索和摘要引擎使用——指出特定细节和关键词,然后我再在线上进行验证。
🛠️ – 标记为🛠️的标题是那些使用LLM难以找到正确解决方案或解释的内容,或是信息过于重要而无法完全依赖LLM,因此我进行了手动研究和反复试验。
常用标志滤镜词汇表
对于希望优化现有FFmpeg命令的用户,可跳转至命令设置部分
-vf
(也可用-filter:v
)视频滤镜-af
(也支持-filter:a
)音频滤镜filter_complex
复杂滤镜图 – 用于通用滤镜处理,可控制所有流中的音频和视频
常见滤镜关键字(可通过修改数字指定所需索引):
[0]
选择第一个输入的所有流(基于 0 的索引)[0:v]
选择第一个输入的视频流[1:a]
选择第二个输入的音频流0:v:0
来自第一个输入的第一个视频流(基于 0 的索引)0:a:1
来自第一个输入的第二个音频流(基于 0 的索引)[name]
选择一个命名流,通常与-filter_complex
一起使用
-map [name] 选择输出流
表达式评估 if
, lte
, gte
等
-y
自动覆盖现有输出文件。在每个 FFmpeg 命令开头添加此标志以避免提示确认覆盖
简单编辑
格式转换
将MP4转换为MKV:
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4 -c copy big_buck_bunny_720p_16sec.mkv
-c copy
– 阅读下方
MKV 和 MP4:两者均为视频容器格式,可存储 H264 和 H265 编码的视频以及 AAC 和 MP3 编码的音频。视频质量本身并不由容器格式决定,而是由用于压缩视频数据的视频编解码器决定。
MKV 可以包含多个视频流,而 MP4 在不同平台和设备上具有更广泛的兼容性。
将 MP4 重新封装为 MOV:
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4 -c copy big_buck_bunny_720p_16sec.mov
将 MP4 编码为 AVI:
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4 big_buck_bunny_720p_16sec.avi
调整尺寸和添加边框
🛠️ 将视频放大至1080×1920,保持原始宽高比,并根据需要添加黑色边框填充空白:
ffmpeg -i https://storage.rendi. dev/sample/popeye_talking.mp4 -vf "scale=w=1080:h=1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2:color=black,setsar=1:1" output_resized_pad.mp4
缩放详细信息
scale=w=1080:h=1920:force_original_aspect_ratio=decrease 将视频缩放以适应 1080×1920 尺寸,会自动降低输出尺寸以等于或低于指定的宽度和高度,同时保持输入的原始宽高比。在此情况下,将先将输入视频缩放至1080×810,再添加填充。
若不确定保持原始宽高比所需的高度(或宽度),可指定scale=w=1080:h=-1
,让FFmpeg自动选择合适的高度,同时确保保持原始宽高比且最大宽度不超过1080。
指定 -2 scale=w=1080:h=-2
强制使用可被 2 整除的尺寸
注意:这里不能使用 scale=w=-1:1920
,因为这会导致 FFmpeg 选择大于 1080 的宽度,与我们期望的 1080 输出宽度冲突,从而引发错误。
͏ 可通过 “force_original_aspect_ratio” 实现。共有 3 个可能的值: ͏ |0| “禁用”(默认) ͏ |1| “缩小”: 根据需要自动缩小输出尺寸。͏ |2| “增加”: 根据需要自动增加输出尺寸。
填充详细信息
pad=1080:1920:(ow-iw)/2:(oh-ih)/2:color=black 将缩放后的视频居中,并用黑色填充剩余部分。值格式为 宽度:高度:x:y
,其中 x:y 表示左上角坐标。负值同样可将图像居中,因此可使用 pad=1080:1920:-1:-1:color=black
实现类似效果。
setsar=1:1 采样宽高比 – 确保输出像素以 1:1 的比例缩放。也可设置为 1
或 1/1
– 这些均等效。在某些情况下,FFmpeg 可能会自动设置采样宽高比以补偿比例变化。明确指定 SAR 1:1 以确保按预期工作。
使用一个 FFmpeg 命令从同一输入视频创建两个缩放视频 – 一个水平方向,另一个垂直方向。在垂直视频顶部添加一个叠加层徽标:
ffmpeg -i https://storage.rendi.dev/sample/popeye_talking.mp4 -i https://storage.rendi.dev/sample/rendi_banner_white.png -filter_complex "[0:v]split=2[s0][s1];[s0]scale=w=1920: h=1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2:color=black,setsar=1:1[out1];[s1]scale=w=720:h=1280: 强制原始宽高比=缩小,填充=720:1280:(ow-iw)/2:(oh-ih)/2:颜色=黑色,设置宽高比=1:1[s2];[s2][1]叠加=(主宽-叠加宽)/2:(主宽-叠加宽)/5[out2]" -map [输出1] -map 0:a 输出YouTube.mp4 -map [输出2] -map 0:a 输出短视频.mp4
我经常使用的两个Stack Overflow信息来源 链接1 ; 链接 2
按时间裁剪
ffmpeg -i https://storage.rendi.dev/sample/popeye_talking.mp4 -ss 00:00:10 -to 00:00:25 output_trimmed.mp4
虽然存在更快速的裁剪方法,但它们可能不够精准或会生成黑屏帧。
音频处理
替换视频中的音频
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4 -i https://storage.rendi.dev/sample/Neon_Lights_5sec.mp3 -map 0:v -map 1:a -shortest -c:v copy -c:a aac output_replace_audio.mp4
将视频中的音频替换为新的音频文件
-shortest 将视频的结尾裁剪至与音频长度相同。若需保留视频时长,可移除此参数(输出视频将在5秒后静音)
注意:上述命令中包含
c:v copy
,这意味着它会在非关键帧位置进行裁剪而无需重新编码,因此我原本预计会出现黑屏。但输出视频看起来完美无缺。此外,当尝试显式使用-c:v libx264
重新编码时,输出视频长度为 7 秒,比最短的 5 秒音频更长。在线搜索后,我未能找到这两种情况的解释。
从视频中提取音频
将 MP4 编码为 MP3:
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4 big_buck_bunny_720p_16sec.mp3
从MP4视频中提取音频,将其采样率降至16,000 Hz,转换为单声道MP3,同时提取视频(静音):
ffmpeg -i https://storage.rendi.dev/sample/popeye_talking.mp4 -ar 16000 -ab 48k -codec:a libmp3lame -ac 1 output_extracted_audio.mp3 -map 0:v -c:v copy -an out_video_only.mp4
-ar
采样率 16KHz – 每秒数字音频波形样本的数量-b:a 48k
(与-ab
相同)比特率 48KBit/s – 每秒存储的数据量 Stackoverflow 参考-ac 1
音频通道 – 1(单声道)
从 MP4 中提取 AAC 音频而无需编码:
ffmpeg -i https://storage.rendi.dev/sample/popeye_talking.mp4 -map 0:a:0 -acodec copy output.aac
在视频中混合音频
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4 -i https://storage.rendi. dev/sample/Neon_Lights_5sec.mp3 -filter_complex "[1:a]volume=0.2[a1];[0:a][a1]amix=inputs=2:duration=shortest" -shortest -map 0:v -c:v copy -c:a aac output_mix_audio.mp4
将视频中的音频与新音频文件混合并降低其音量:
[1:a]volume=0.2[a1] 降低音频文件的音量,以便我们也能听到视频文件的音频,[1:a]
表示来自文件1的音频,采用0基索引。[a1]
标记音量已调整的音频,以便与视频音频混合。
[0:a][a1]amix=inputs=2 提取第一个流(视频)的音频和音量调整后的音频,并将它们混合在一起
更多细节
如果你不想更改音量,可以直接使用这个滤镜:-filter_complex "[0:a][1:a]amix=inputs=2:duration=shortest"
:duration=shortest
使新音频与最短音频等长,但仍需添加 -shortest
标志,因为它控制最终输出视频的长度(而不仅仅是音频)
相关讨论 涉及视频长度与音频长度不一致时,如何调整输出视频长度以保持一致
与该主题相关的已知问题 使用 duration:shortest
和 -shortest
可避免该问题的影響。
合并两个 MP3 音轨
ffmpeg -i https://storage.rendi.dev/sample/Neon_Lights_5sec.mp3 -i https://storage.rendi.dev/sample/Neon%20Lights.mp3 -filter_complex "[0:a]afade=t=out: st=2:d=3[a0];[1:a]afade=t=in:st=0:d=3[a1];[a0][a1]concat=n=2:v=0:a=1" -c:a libmp3lame -q:a 2 output_gapless_fade.mp3
[0:a]afade=t=out:st=2:d=3…[1:a]afade=t=in:st=0:d=3 淡出第一个音频并淡入第二个音频:
- 第一段输入音频
[0:a]
3 秒d=3
淡出t=out
,从其第 2 秒开始st=2
- 第二段音频
[1:a]
3 秒d=3
淡入t=in
,从音频开始处st=0
[a0][a1]concat=n=2:v=0:a=1 将两个淡入淡出的音频流重新连接,生成一个输出音频流,无视频(v=0
)。
-q:a 2 – 高质量音频输出,平均立体声比特率为170-210 KBit/s
交叉淡入淡出
ffmpeg -i https://storage.rendi. dev/sample/Neon_Lights_5sec.mp3 -i https://storage.rendi.dev/sample/Neon%20Lights.mp3 -filter_complex "[0:0][1:0]acrossfade=d=3:c1=exp:c2=qsin" -c:a libmp3lame -q:a 2 output.mp3
acrossfade=d=3:c1=exp:c2=qsin 3秒音频淡入淡出效果,其中第一首曲目快速淡出,第二首曲目缓慢淡入
更改音频格式
MP3 转换为 WAV pcm_s32le(无符号 32 位小端字节序)格式,单声道且采样频率为 48KHz:
ffmpeg -i https://storage.rendi.dev/sample/Neon%20Lights.mp3 -acodec pcm_s32le -ac 1 -ar 48000 output.wav
将两个MP4文件的音频合并,以相同比例混合为单声道,标准化音量,降采样至16 kHz,以64 KBits/s编码为MP3:
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4 -i https://storage.rendi. dev/sample/popeye_talking.mp4 -filter_complex "[0:a][1:a]amix=inputs=2:duration=longest,pan=mono|c0=.5*c0+.5*c1,dynaudnorm" -ar 16000 -c:a libmp3lame -b:a 64k merged_audio.mp3
pan=mono|c0=.5*c0+.5*c1
输出声道(c0)由左声道输入(c0
)的50%和右声道输入(c1
)的50%混合而成。
dynaudnorm
应用动态音频标准化(平滑处理大声/小声部分)
高级编辑
更改播放速度,不失真音频
ffmpeg -i https://storage.rendi.dev/sample/popeye_talking.mp4 -filter_complex "[0:v]setpts=PTS/1.5[v];[0:a]atempo=1.5[a]" -map "[v]" -map "[a]" output_sped_up.mp4
setpts=PTS/1.5 将视频速度加快 1.5 倍。atempo=1.5
加快音频播放速度的同时保持音调不变
更改视频帧率而不改变音频速度
ffmpeg -i https://storage.rendi.dev/sample/popeye_talking.mp4 -filter:v fps=60 popeye_fps.mp4
跳切
ffmpeg -i https://storage.rendi.dev/sample/popeye_talking.mp4 -vf "select='between(t,0.0,5.7)+between(t,11.0,18.0)+between(t,19.0,20.0)',setpts=N/FRAME_RATE/TB" -af "aselect='between(t,0.0,5.7)+between(t,11.0,18.0)+between(t,19.0,20.0)',asetpts=N/SR/TB" popeye_jumpcuts.mp4
用于缩短片段、去除静音、去除过渡效果等。
setpts=N/FRAME_RATE/TB…asetpts=N/SR/TB 根据请求的剪辑重置视频和音频呈现时间戳
N
已消耗的帧数音频样本数,不包括当前帧(音频),从0开始计数FRAME_RATE
SR
视频帧率和音频采样率TB
输入时间戳的时间基准
🛠️ 社交媒体视频裁剪
将 1080×720 视频裁剪为 720×1080,通过将视频片段裁剪为 480×720 并在特定时间帧以 1.5 倍放大,以创建垂直社交媒体视频:
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4 -vf "split=3[1][2][3];[1]trim=0.0:4. 5,setpts=PTS-STARTPTS,crop=min(in_w-300,480):min(in_h-0,720):300:0,scale=720:1080,setsar=1:1[1];[2]trim=4.5:8. 5,setpts=PTS-STARTPTS,crop=min(in_w-500,480):min(in_h-0,720):500:0,scale=720:1080,setsar=1:1[2];[3]trim=8. 5,setpts=PTS-STARTPTS,crop=min(in_w-400,480):min(in_h-0,720):400:0,scale=720:1080,setsar=1:1[3];[1][2][3]concat=n=3:v=1" -c:v libx264 -c:a copy output_cropped.mp4
split=3[1][2][3] 将输入视频分割为3个片段并命名为[1]
[2]
[3]
trim=0.0:4.5 每个裁剪片段都是从起始时间开始到结束时间结束的临时新视频 [3]trim=8.5
未指定结束时间,因此将与视频结束同步
使用 setpts=PTS-STARTPTS 重置时间戳是必要的,当使用 trim 和 concat 时,以确保 concat 在看似独立的视频流(已裁剪的流)上正确工作
crop=min(in_w-300,480):min(in_h-0,720):300:0 参数值为 宽度:高度:x:y
,其中 x,y 表示左上角坐标。最小尺寸确保FFmpeg在缩放前不会裁剪超出输出帧指定尺寸的区域。在此场景下最小值计算并非必要,它们仅作为占位符,以防后续需要调整尺寸或x,y位置。
若裁剪超出帧边界,裁剪操作将导致视频失真。为解决此问题,可使用黑色填充来填补空白区域:
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4 -vf "split=3[1][2][3];[1]trim=0.0:4.5,setpts=PTS-STARTPTS,crop=min(in_w-1200,480): min(in_h-0,720):1200:0,pad=480:720:(ow-iw)/2:(oh-ih)/2:color=black,scale=720:1080,setsar=1:1[1];[2]trim=4.5:8. 5,setpts=PTS-STARTPTS,crop=min(in_w-500,480):min(in_h-0,720):500:0,pad=480:720:(ow-iw)/2:(oh-ih)/2:color=black,scale=720: 1080,setsar=1:1[2];[3]trim=8.5,setpts=PTS-STARTPTS,crop=min(in_w-400,480):min(in_h-0,720):400:0,pad=480:720: (ow-iw)/2:(oh-ih)/2:color=black,scale=720:1080,setsar=1:1[3];[1][2][3]concat=n=3:v=1" -c:v libx264 -c:a copy output_cropped.mp4
在视频上叠加文本
在视频上叠加三条不同的文本消息,每条消息在特定时间出现,带有淡入透明度效果和半透明背景框。:
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec. mp4 -vf "drawtext=text='准备好':x=50:y=100:fontsize=80:fontcolor=black:alpha='if(gte(t,1)*lte(t,3),(t-1)/2,1)':box=1:boxcolor=#6bb666@0. 6:boxborderw=7:enable='gte(t,1)', drawtext=text='Set':x=50:y=200:fontsize=80:fontcolor=black:alpha='if(gte(t,6)*lte(t,10),(t-6)/4,1)':box=1:boxcolor=#6bb666@0. 6:框边框宽度=7:启用='gte(t,6)', 绘制文本=文本='BOOM!':x=50:y=300:字体大小=80:字体颜色=黑色:透明度='if(gte(t,10)*lte(t,15),(t-10)/5,1)':框=1:框颜色=#6bb666@0. 6:boxborderw=7:enable='gte(t,10)'" -c:v libx264 output_text_overlay.mp4
如果您有本地存储的字体文件,可以使用以下方式指定: fontfile=<文件路径>
,例如:drawtext=text='准备就绪':x=50:y=100:fontsize=80:fontcolor=black:fontfile=arial.ttf
drawtext详细信息
“准备就绪”叠加层的解释 drawtext=text='准备就绪':x=50:y=100:fontsize=80:fontcolor=black:alpha='if(gte(t,1)*lte(t,3),(t-1)/2,1)':box=1:boxcolor=#6bb666@0. 6:boxborderw=7:enable='gte(t,1)'
:
- enable=’gte(t,1)’ 控制叠加层何时可见 – 大于或等于 1 秒。
*
是与运算符,从 t = 1 秒开始显示 alpha='if(gte(t,1)*lte(t,3),(t-1)/2,1)'
在 t=1 到 t=3 之间渐隐,其他时间均为 1(完全不透明)box=1
在文本后绘制背景,并设置 7px 填充boxborderw=7
- boxcolor=#6bb666@0.6 — 绿色背景 #6bb666,不透明度 60%。
x=50:y=100
框的左上角位置
从文本文件和字体文件向视频添加文本叠加层:
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4 -vf "drawtext=textfile=sample_text. txt:fontfile=Poppins-Regular.ttf:x=50:y=100:fontsize=40:fontcolor=black:alpha='if(gte(t,1)*lte(t,5),t-1,1)':box=1:boxcolor=#6bb666@0.6:boxborderw=7:enable='gte(t,1)'" -c:v libx264 output_text_font_file.mp4
FFmpeg 不会自动下载 textfile=
和 fontfile=
中的文件, 因此您需要手动从 https://storage.rendi.dev/sample/sample_text.txt 和 https://storage.rendi.dev/sample/Poppins-Regular.ttf 下载文件
建议使用 textfile 而不是在 FFmpeg 命令中直接指定文本,以避免特殊字符干扰命令行语法的问题。
🛠️ 为视频添加字幕
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p.mp4 -ss 00:00 -to 00:40 -vf "subtitles=sample_subtitles. srt:fontsdir=.:force_style='FontName=Poppins,FontSize=24,PrimaryColour=&HFFFFFF,OutlineColour=&H4066B66B,Outline=1,BorderStyle=3'" -c:v libx264 -c:a copy output_subtitles.mp4
此命令使用自定义字体 Poppins
烧录字幕,并应用自定义字幕样式。请注意使用 FontName
(而非文件名)——您可以在打开字体文件时找到该名称。此外,需指定包含字体文件的 fontsdir
路径。
您可以从 https://storage.rendi.dev/sample/Poppins-Regular.ttf 下载 Poppins 字体文件
字幕详细信息
颜色可以是 &HBBGGRR
– 蓝色、绿色、红色,或者 &HAABBGGRR
,如果你想添加 alpha 通道(透明度),其中 FF 表示 100% 透明,00 表示无透明度。
PrimaryColour
是字体颜色
🛠️ OutlineColour=&H4066B66B,Outline=1,BorderStyle=3
配置绿色背景(HEXA 中的 40/FF 表示 25% 不透明度)和 RGB 中的 #6bb666 颜色。要使背景显示,必须设置 Outline=1,BorderStyle=3
。背景样式化有点复杂,这个 Reddit 帖子 提供了有用信息。
官方FFmpeg文档:如何将字幕烧录到视频中;字幕滤镜
如果您希望对字幕的外观进行深度自定义,最佳选择是使用ASS字幕格式。我经常使用的优质信息来源。
若需实现像素级精准的字幕烧录效果,并添加特殊效果或独特外观,建议在任何字幕格式之外创建不透明图像,并使用FFmpeg将图像烧录到视频中。
向视频添加默认字幕SRT轨道并存储于MKV容器中,无需重新编码视频,编码格式仍保持H264:
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4 -i sample_subtitles.srt -c copy -c:s srt -disposition:s:0 default big_buck_bunny_720p_16sec.mkv
-c:s srt
字幕格式为 srt
-disposition:s:0 默认设置为默认字幕轨道
从 mkv 文件中提取字幕:
ffmpeg -i big_buck_bunny_720p_16sec.mkv -map 0:s:0 subs.srt
从 MKV 文件中提取字幕
组合媒体资源
在视频上叠加图像 – 为视频添加徽标/水印:
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4 -i https://storage.rendi. dev/sample/rendi_banner_white_transparent.png -filter_complex "overlay=x=(main_w-overlay_w)/8:y=(main_h-overlay_h)/8:enable='gte(t,1)*lte(t,7)'" -c:v libx264 -c:a output_logo.mp4
上述命令在视频上叠加一个透明背景的叠加层
x=(main_w-overlay_w)/8:y=(main_h-overlay_h)/8
将叠加层的左上角水平定位在从左侧和顶部剩余空间的1/8处
main_wmain_h
是主视频的宽度和高度overlay_woverlay_h
是叠加层图像的宽度和高度
enable='gte(t,1)*lte(t,7)'
控制叠加层的可见时间 – 大于等于 1 秒且小于等于 7 秒,*
是与运算符
🛠 若需让 FFmpeg 控制叠加层的透明度,可使用以下命令:
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4 -i https://storage.rendi.dev/sample/rendi_banner_white. png -filter_complex "[1:v]format=argb,geq='p(X,Y)':a='0.5*alpha(X,Y)'[v1];[0:v][v1]overlay=x=(main_w-overlay_w)/8:y=(main_h-overlay_h)/8:enable='gte(t,1)*lte(t,7)'" -c:v libx264 -c:a copy output_faded_logo.mp4
[1:v]format=argb,geq=r='r(X,Y)':a='0.5*alpha(X,Y)'[v1]
创建透明标志
详细信息
[1:v]
选择第二个输入(标志)的视频流format=argb
将图像转换为ARGB格式,以便与没有Alpha通道的叠加图像兼容- geq=’p(X,Y)’ 定义徽标在点X,Y处的像素颜色为原始图像中的颜色。这是为了精确控制像素的透明度
a='0.5*alpha(X,Y)'
通过将 alpha 通道乘以 0.5,使徽标透明度为 50%[v1]
将此处理后的徽标标记为新的视频流
将视频叠加在背景图像上 – 以新的分辨率和宽高比创建视频:
ffmpeg -i https://storage.rendi.dev/sample/popeye_talking.mp4 -i https://storage.rendi.dev/sample/evil-frank.png -filter_complex "[1:v][0:v]overlay=(W-w)/2:(H-h)/2" -c:v libx264 -c:a copy output_bg.mp4
[1:v][0:v]
首先放置图像(背景),然后在顶部放置视频。
(W-w)/2:(H-h)/2
通过选择视频的左上角,将视频水平和垂直居中放置在背景图像上。WH 表示背景的宽度和高度,wh 表示视频的宽度和高度,大写字母属于第一个指定的流 [1:v]
,小写字母属于第二个指定的流 [0:v]
。请注意,顺序基于 [1:v][0:v]
,而非输入文件的顺序。
将片头、片中和片尾合并为一个视频,并混入背景音乐:
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_5sec_intro.mp4 -i https://storage.rendi.dev/sample/popeye_talking.mp4 -i https://storage.rendi.dev/sample/big_buck_bunny_720p_5sec_outro. mp4 -i https://storage.rendi.dev/sample/Neon%20Lights.mp3 -filter_complex "[0:v]fps=30,format=yuv420p,setsar=1[intro_v];[1:v]scale=-2:720:force_original_aspect_ratio=decrease,pad=1280: 720:(ow-iw)/2:(oh-ih)/2:black,fps=30,format=yuv420p,setsar=1[main_v];[2:v]fps=30,format=yuv420p,setsar=1[outro_v];[0:a]aformat=sample_fmts=fltp: 声道布局=立体声[intro_a];[1:a]a格式=采样格式=fltp:声道布局=立体声[main_a];[2:a]a格式=采样格式=fltp: 声道布局=立体声[结尾_a];[开头_v][开头_a][主_v][主_a][结尾_v][结尾_a]合并=n=3:v=1:a=1[合并视频][合并音频];[3:a]音量=0.1,音频格式=采样格式=fltp,音频淡入=t=in: ss=0:d=1.5,afade=t=out:st=20:d=2[bgm_faded];[combined_audio][bgm_faded]amix=inputs=2:duration=first:dropout_transition=2[final_audio]" -map "[combined_video]" -map "[final_audio]" -c:v libx264 -c:a aac -shortest intro_main_outro.mp4
duration=first
输出音频流的时长应与输入流(合并后的音频)一致,dropout_transition=2
为较短的音频创建淡出效果,以避免突然中断
aformat=sample_fmts=fltp 将音频格式转换为32位浮点平面格式(FFmpeg中常见的格式),网上找不到好的简单资料
🛠️ 垂直叠加两个视频并保留第二个视频的音频:
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4 -i https://storage.rendi.dev/sample/popeye_talking.mp4 -filter_complex "[0:v]scale=720:-2:force_original_aspect_ratio=decrease,pad=720: 640:(ow-iw)/2:(oh-ih)/2:black[top];[1:v]scale=720:-2:force_original_aspect_ratio=decrease,pad=720:640:(ow-iw)/2:(oh-ih)/2:black[bottom];[top][bottom]vstack=inputs=2:shortest=1[v]" -映射 "[v]" -映射 1:a -c:v libx264 -c:a aac -最短 输出堆叠.mp4
shortest=1 在两个视频流中,我们选择最短的进行垂直堆叠。-shortest
在输出视频和第二个输入视频的音频之间,我们选择最短的。
资产生成
图片转视频
从循环输入图片和音频文件创建一个10秒的视频,图片淡入显示:
ffmpeg -loop 1 -t 10 -i https://storage.rendi.dev/sample/bbb-splash.png -i https://storage.rendi.dev/sample/Neon%20Lights.mp3 -vf "scale=1280:720:force_original_aspect_ratio=decrease,pad=1280: 720:-1:-1:color=black,setsar=1,fade=t=in:st=0:d=1,format=yuv420p" -c:v libx264 -c:a aac -shortest output_loop.mp4
上述命令运行缓慢,因为它为每个视频帧下载图像帧。要加快运行速度,请将PNG文件本地下载,然后使用本地文件运行命令。
-loop 1
无限循环输入图像。-t 10
输入循环的持续时间为10秒,因此即使我们无限循环输入图像,也会在10秒后停止。
关于循环的优秀 StackOverflow 参考资料 – 必读
fade=t=in:st=0:d=1 视频开始时(st=0
)进行1秒(d=1
)的淡入(t=in
)
🛠️ 创建一个每张输入图像持续5秒的幻灯片视频,并带有背景音频,在图像之间进行淡入淡出:
ffmpeg -loop 1 -t 5 -i https://storage.rendi.dev/sample/rodents.png -loop 1 -t 5 -i https://storage.rendi.dev/sample/evil-frank.png -i https://storage.rendi. dev/sample/Neon%20Lights.mp3 -filter_complex "[0:v]format=yuv420p,fade=t=in:st=0:d=0.5,setpts=PTS-STARTPTS[v0];[1:v]format=yuv420p,fade=t=out:st=4. 5:d=0.5,setpts=PTS-STARTPTS[v1];[v0][v1]xfade=transition=fade:duration=0.5:offset=4.5,format=yuv420p[v]" -map "[v]" -map 2:a -c:v libx264 -c:a aac -shortest slideshow_with_fade.mp4
生成的视频时长为9.5秒,因为从第一帧过渡到第二帧时存在0.5秒的重叠。第一帧以淡入方式显示,最后一帧以淡出方式显示。
[0:v]... [v0];[1:v]...[v1];[v0][v1]...[v]
首个输入视频流 [0:v]
经过淡入滤镜处理,其结果标记为 v0
,随后第二个输入视频流经过滤镜处理,其结果标记为 v1
,然后两者通过 xfade 滤镜拼接,输出视频结果标记为 v
xfade=transition=fade:duration=0.5:offset=4.5 从第一张图像的 4.5 秒处开始淡出过渡,持续 0.5 秒,同时在过渡过程中添加第二张图像。
🛠️ 从图像创建 Ken Burns 风格的视频:
ffmpeg -loop 1 -i https://storage.rendi.dev/sample/rodents.png -loop 1 -i https://storage.rendi.dev/sample/evil-frank.png -i https://storage.rendi. dev/sample/Neon%20Lights.mp3 -filter_complex "[0:v]scale=8000:-1,zoompan=z='zoom+0.005':x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)':d=100:s=1920x1080: fps=25,trim=duration=4,format=yuv420p,setpts=PTS-STARTPTS[v0];[1:v]scale=8000:-1,zoompan=z='if(lte(zoom,1.0),1.5,max(zoom-0.005,1.005))': x=0:y='ih/2-(ih/zoom/2)':d=100:s=1920x1080:fps=25,trim=duration=4,format=yuv420p,setpts=PTS-STARTPTS[v1];[v0][v1]xfade=transition=fade: 持续时间=1:偏移=3,格式=yuv420p[v]" -map "[v]" -map 2:a -c:v libx264 -c:a aac -shortest 输出_肯伯恩斯.mp4
该命令从两个输入图像和背景音频创建视频。对第一个图像的中心进行放大,播放4秒后淡入淡出过渡到下一个图像。第二个图像从其左侧开始缩小,同时播放4秒。输出时长为7秒,因为两个图像片段之间有1秒的淡入淡出过渡,且命令会将音频缩短以匹配视频
z='zoom+0.005'
每个新生成帧相较前一帧增加0.005倍缩放,即前一帧缩放1.005倍
x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)'
水平平移至画面中心
d=100:s=1920x1080:fps=25
指定效果将生成 100 帧(d
),输出分辨率为 s=1920x1080
,每秒 25 帧 fps
,即 4 秒效果(100 帧除以 25 fps)
scale=8000:-1
用于先对帧进行放大,然后再进行缩放,这可以避免使用缩放平移滤镜时出现的 抖动 bug,但会增加放大操作的计算时间。-1
表示调整高度以保持宽高比,根据 8000 像素的宽度进行调整。推荐阅读:https://superuser.com/a/1112680/431710 ,https://superuser. com/questions/1112617/ffmpeg-smooth-zoompan-with-no-jiggle
zoompan=z=’if(lte(zoom,1.0),1.5,max(zoom-0.005,1.005))’ 这部分是从放大的起始帧开始缩小。如果缩放因子小于 1.0,则将其设置为 1.5——这对应于起始帧。然后命令以每帧 0.005 的幅度缩小,直到缩放因子达到 1.005,从而实现缩小效果,之后停止更改缩放因子——以防止缩小效果被重置。
trim=duration=4
在输入文件前无法指定 -t=4
并保持此图像片段为 4 秒(如上所述,从循环输入图像创建视频)。尝试这样做时,第一个片段由于 xfade
效果在 4 秒内长度正确,但第二个片段会被重复,以便总输出视频与音频长度匹配。我尝试了多种解决方法,但均未奏效。这可能与 zoompan 滤镜有关,该滤镜通过指定帧率和帧数(而非设置硬性最大限制)本质上消除了 -t
参数的意义。唯一有效的方法是在 zoompan 之后指定裁剪时长。
创建GIF
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4 -vf "select='gt(trunc(t/2),trunc(prev_t/2))',setpts='PTS*0.1',scale=trunc(oh*a/2)*2:320: force_original_aspect_ratio=decrease,pad=trunc(oh*a/2)*2:320:-1:-1" -loop 0 -an output.gif
从视频中创建一个循环GIF,自动缩放至320像素宽度,每隔一帧(lte(n,1)+gt(trunc(t/2),trunc(prev_t/2))
)并加速播放速度10倍(setpts='PTS*0.1'
)
-loop 0
是默认设置,实际上可以省略,表示循环为无限次。若仅循环一次,请使用 -loop 1
将视频帧转换为视频合集
基于单个输入视频创建视频合集,将视频分割为多个部分并添加淡入淡出效果:
ffmpeg -i https://storage.rendi.dev/sample/BigBuckBunny_320x180.mp4 -filter_complex "[0:v]trim=start=11:end=15,setpts=PTS-STARTPTS,fade=t=in:st=0:d=0.5,fade=t=out: st=3.5:d=0.5[v1];[0:a]atrim=start=11:end=15,asetpts=PTS-STARTPTS,afade=t=in:st=0:d=0.5,afade=t=out: st=3.5:d=0.5[a1];[0:v]trim=start=21:end=25,setpts=PTS-STARTPTS,fade=t=in:st=0:d=0.5,fade=t=out: st=3.5:d=0.5[v2];[0:a]atrim=start=21:end=25,asetpts=PTS-STARTPTS,afade=t=in:st=0:d=0.5,afade=t=out: st=3.5:d=0.5[a2];[v1][a1][v2][a2]concat=n=2:v=1:a=1[outv][outa]" -map "[outv]" -map "[outa]" -c:v libx264 -c:a aac output_fade_in_out.mp4
该命令从输入视频中提取两个片段(11-15秒和21-25秒),对每个片段应用淡入/淡出效果,并将其连接在一起。
trim=start=X:end=Y
将视频裁剪为指定的时间范围,atrim
– 对应于音频
setpts=PTS-STARTPTS
将时间戳重置为从0开始
fade=t=in:st=0:d=0.5...fade=t=out:st=3.5:d=0.5
参见上文关于创建幻灯片的内容
afade
参见上文关于音频处理的内容
concat=n=2:v=1:a=1
将两个包含视频和音频的片段合并
从视频创建缩略图
从第 7 秒的帧创建缩略图:
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4 -ss 00:00:07 -frames:v 1 output_thumbnail.png
要控制输出图像质量,请使用 -q:v
:
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4 -ss 00:00:07 -frames:v 1 -q:v 2 output_thumbnail.jpg
值范围为2到31,2为最佳,31为最差。参考资料:Stackoverflow 1 Stackoverflow 2
创建两个缩略图——一个来自第5秒后的第一个帧,另一个来自第15秒后的第一个帧:
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4 -filter_complex "[0:v]split=2[first][second];[first]select='gte(t,5)'[thumb1];[second]select='gte(t,15)'[thumb2]" -map [thumb1] -frames:v 1 output_thumbnail_1.png -map [thumb2] -frames:v 1 output_thumbnail_2.png
-frames:v 1
仅输出1帧视频
从场景变化的第一帧创建缩略图:
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4 -vf "select='gt(scene,0.4)'" -frames:v 1 -q:v 2 thumbnail_scene.jpg
gt(scene,0.4) 参数用于确定 FFmpeg 对帧变化的敏感度,从而识别场景变化。该值范围为 0 到 1,数值越低表示 FFmpeg 对场景变化的敏感度越高,识别出的场景变化越多。推荐值范围为0.3至0.5
关于使用FFmpeg检测场景的良好Stack Overflow讨论
从输入图像创建图像缩略图
ffmpeg -i https://storage.rendi.dev/sample/bbb-splash.png -i https://storage.rendi.dev/sample/rodents.png -i https://storage.rendi.dev/sample/evil-frank.png -filter_complex "[1]scale=640:360,pad=648:368: 4:4:black[overlay1];[2]scale=640:360,pad=648:368:4:4:black[overlay2];[0][overlay1]overlay=0:main_h-overlay_h[tmp1];[tmp1][overlay2]overlay=main_w-overlay_w: main_h-overlay_h" -frames:v 1 thumbnail_overlayed.png
从视频创建故事板
以下所有命令均从视频中提取帧以创建不同故事板
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4 -vf "select='gt(scene,0.4)',scale=640:480,tile=2X2" -frames:v 1 scene_storyboard.jpg
🛠️ 使用 tile=2X2
从视频中的场景创建 2X2 分镜脚本。 示例来自 FFmpeg 文档
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4 -vf "select='gt(scene,0.4)'" -vsync 0 scene_storyboard_%03d.jpg
创建相同的分镜图,但每个场景使用单独的图像文件
🛠️ -vsync 0 会丢弃属于同一场景的帧,以避免重复。此参数使用较为复杂,详细说明
vsync 参数可正常使用,但在 ffmpeg 新版本中已废弃,应改用
-fps_mode
参数 参考 FFmpeg 文档
ffmpeg -skip_frame nokey -i https://storage.rendi.dev/sample/big_buck_bunny_720p.mp4 -vf 'scale=640:480,tile=4x4' -an -vsync 0 keyframes%03d.png
使用多个文件创建故事板,这些文件以平铺方式排列,基于视频的关键帧而非场景来确定帧。示例来自FFmpeg的文档
-skip_frame nokey
如文本所示,跳过非关键帧。
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4 -vf "select=not(mod(n,10)),scale=640:480,tile=4x2" -vsync 0 tile_4_2_frames_10_%03d.png
从视频的每第10帧创建4×2拼接文件。若仅需按帧创建图像,可移除,tile4x2
部分
命令设置
通用、简单且优化的 FFmpeg 命令,适用于日常使用
ffmpeg -i https://storage.rendi.dev/sample/popeye_talking.mp4 -vf "scale=w=1080:h=1920:force_original_aspect_ratio=decrease,pad=1080:1920: (ow-iw)/2:(oh-ih)/2:color=black,setsar=1:1" -crf 18 -preset veryslow -threads 0 -tune fastdecode -movflags +faststart output_scaled_optimized.mp4
此命令会重新调整输入视频的尺寸,适用于存档、流媒体(非实时)以及在多种边缘设备上播放。您通常可以将此命令中的参数用于所有 FFmpeg 命令,除非有特殊原因不使用。
此命令中的参数具有不同的配置选项。请务必查阅它们的 FFmpeg 参考文档。如果您希望我在此详细说明这些参数,请告诉我。
-tune fastdecode 编码后的输出文件解码所需的计算资源更少,适合在多种边缘设备上查看。您可以使用 zerolatency 进行优化,以实现快速编码和低延迟流媒体
-preset veryslow 编码速度较慢,但输出更压缩且保持高质量——适用于优化网络观看(VOD、存档、非直播流媒体)。若需极快编码速度(以牺牲输出文件大小为代价),请使用 ultrafast
。
-threads 0
指定使用多少系统线程。最佳值为 0(默认值),通常建议不使用此参数,让 FFmpeg 自动优化。 但有时需要根据系统和命令行环境进行调整
🛠️ 视频/音频编码、编解码器和比特率
-c:v
指定视频编码器,-c:a
指定音频编码器。
-c:a aac
AAC编码的音频。这也是FFmpeg的默认设置,建议明确指定。
-c:a libmp3lame MP3编码库
-an
禁用输出音频
-c:v libx264 – H264 (AVC)
通常FFmpeg在生成MP4输出时会默认使用H264,除非您使用的FFmpeg构建版本未包含libx264库。建议始终明确指定编码器。
libx265 – H265(HEVC),这种较新的编解码器在行为和控制方面与 H264 非常相似。H264 仍然是最常用的编解码器。
Apple 设备有时会出现 FFmpeg 生成的 H265 视频问题(例如在 iOS AirDrop 中),使用
-vtag hvc1
解决此问题。感谢! 相关链接
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4 -c:v libx265 -vtag hvc1 -c:a copy output_265.mp4
format=yuv420p H264 YUV 平面颜色格式,用于确保在大多数播放器中的播放兼容性。在将图像转换为视频时使用此标志,以及在输出视频出现播放问题时使用,除非你有特定的理由不使用它。
为了使输出在 QuickTime 和大多数其他播放器中正常工作,您可能需要使用 -vf format=yuv420p(或别名 -pix_fmt yuv420p)。这些播放器仅支持 H.264 视频的 YUV 平面颜色空间,且色度采样为 4:2:0。否则,根据您的源文件,FFmpeg 可能会输出一种与这些播放器不兼容的像素格式。
关于 YUV420P 的更多信息,请参阅 此 Reddit 帖子
-crf
恒定速率因子 (CRF) – 这是 libx264 和 libx265 的默认比特率控制选项:
如果您希望保持最佳质量且不太在意文件大小,请使用此速率控制模式。这是大多数情况下推荐的速率控制模式。
此方法允许编码器在文件大小不重要时,尝试为整个文件实现特定的输出质量。这在单次编码通过中提供最大的压缩效率。通过调整每个帧的量化器,它会获得所需的比特率以保持请求的质量级别。缺点是无法指定特定的文件大小或不超過特定大小或比特率,这意味着此方法不推荐用于编码流媒体视频。
CRF 刻度范围为 0–51,其中 0 表示无损(仅适用于 8 位,10 位时使用 -qp 0),23 为默认值,51 表示最差质量。较低的值通常会带来更高的质量,而主观上合理的范围是17–28。将17或18视为视觉上无损或几乎无损;它应与输入看起来相同或几乎相同,但从技术上讲并非无损。该范围是指数级的,因此将CRF值增加+6会导致比特率/文件大小大约减半,而-6则会导致比特率大约翻倍。
常见建议是使用 -crf 18
获得非常高质量的 H264 输出,但我发现使用 -crf 10
能够获得更好的视频质量。
使用 -movflags +faststart 可使视频在线播放速度更快,优化网页观看体验,通过将元数据移至容器开头:
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4 -c copy -movflags +faststart big_buck_bunny_720p_16sec_faststart.mp4
YouTube 建议 上传带有 faststart 的 MP4 文件到 YouTube。他们随后会将这些文件重新编码为 VP9。
快速启动功能支持 MP4、M4A 和 MOV 格式,处理过程可能需要几秒钟我未能找到官方文档明确说明快速启动功能与 libx265 兼容,但以下命令表明该功能确实有效:
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4 -c:v libx265 -c:a copy -movflags +faststart big_buck_bunny_720p_16sec_h265_faststart.mp4
为了确保 big_buck_bunny_720p_16sec_h265_faststart.mp4
确实使用了 moov faststart 进行编码,请运行
ffprobe -v trace -i your_video.mp4
并检查开头是否有一行类似于 [mov,mp4,m4a,3gp,3g2,mj2 @ 0x...] type:'moov' size:... pos:...
libvpx-vp9
它是 WebM 格式(一种开放、免版税的媒体文件格式)的 VP9 视频编码器。VP9 由谷歌拥有,YouTube 上大多数视频均采用该编码器进行编码。它是一种专为静态网页托管视频设计的编码方案。libvpx-vp9
与默认的 H264 编码器 libx264
相比,可节省约 20–50% 的比特率,同时保持相同的视觉质量。
libvpx-vp9
中的恒定质量 -crf
编码——与 libx264
中的恒定速率因子类似:
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4 -c:v libvpx-vp9 -crf 15 -b:v 0 -c:a libopus big_buck_bunny_720p_16sec.webm
要启用此模式,必须同时使用
-crf
和-b:v 0
。请注意,-b:v
必须设置为 0。将其设置为更高值或完全省略将触发受限质量模式。CRF 值范围为 0–63。较低值表示更高质量。推荐值范围为 15–35,其中 31 适用于 1080p 高清视频。
-c:a libopus
WebM 的默认音频编码器为 libopus,上述命令将 MP4 中的 AAC 音频重新编码为 WebM 中的 Opus 音频。
VP9、libx264 和 libx265 支持 1 遍和 2 遍编码(您可以在各自的参考资料中阅读相关内容)。slhck 总结得很好::
总结如下,根据您的使用场景,您应选择以下比特率编码配置:
- 存档 — 使用 CRF 实现您所需的质量。
- 流媒体 — 两次通过 CRF 或 ABR,搭配 VBV 限制的比特率。
- 直播流媒体 — 单次通过 CRF 或带 VBV 限制比特率的 ABR,或 CBR(如果可以浪费比特)。
- 设备编码 — 通常使用两次通过 ABR。
slhck可能指的是VP9中的两遍CRF用于流媒体——第一遍让libvpx-vp9计算所需的指标,以便在第二遍以更高的压缩率编码,从而减小文件大小同时保持质量。这种方法更适合网络托管的视频。
良好参考:
- slhck关于CRF的另一篇优秀参考文章
- Stackoverflow关于FFmpeg中CRF的讨论
- Reddit关于CRF的讨论
- Reddit关于CRF与CQP与CBR及GPU编码的讨论
- Reddit关于CBR和CQP的讨论
- Reddit 关于 CRF 和 2-pass 的讨论
🛠️ -c copy
尽可能使用 -c copy
,它会重新封装视频和音频,而不是重新编码(尤其是视频重新编码,这非常耗费计算资源)。-c:v copy
专门复制视频而不重新编码,而 -c:a copy
则对音频做同样的事情(与 -acodec copy
相同)。
重新封装是指将流重新包装到新容器中而不改变其内容,与转码不同,转码会改变压缩方式和质量。例如,MP4 可以重新封装为 MKV 和 MOV,因为它们都是 H264 编解码器的容器。
何时不应使用 -c copy
?
- 应用视频滤镜(缩放、叠加、字幕、裁剪、淡入淡出)或混合/修改音频(amix、atempo、音量)时,这些操作需要重新编码
- 进行精确裁剪(帧级精度)时,
-c copy
只能在关键帧处裁剪,导致粗糙/不准确的编辑。 - 将字幕烧录到视频中需要重新编码
- 在不同编解码器之间转码需要重新编码
- 如果想压缩媒体
🛠️ 输入/输出定位
输入定位(-ss
在输入前):
ffmpeg -ss 00:00:03 -i "https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4" -frames:v 1 "input_seeking.jpg"
通过关键帧解析视频,速度非常快,但准确性较低(在H.264格式且帧率为25fps的情况下,每10秒有一个关键帧)。
如果使用输入定位功能裁剪视频,视频的时间戳将重置为裁剪后的版本,因此在使用滤镜时,需要确保遵循裁剪后的视频时间。
ffmpeg -i "https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4" -ss 00:00:03 -frames:v 1 "input_seeking.jpg"
输出定位(-ss
在输入后)”解码但丢弃输入直到时间戳达到指定位置” – 它具有帧级精度,但处理时间可能更长,因为需要解码。
🛠️ 在裁剪时,建议使用输出定位并禁用 -c:v copy
,重新编码输出视频。
原因如下:
- 使用输入定位和
-c:v copy
进行裁剪存在已知问题 Stackoverflow 讨论 – FFmpeg 仓库问题报告 。因此,建议使用输出定位进行裁剪(无论是否使用-c:v copy
)。 - 当使用输出寻址并启用
-c:v copy
进行裁剪时,输出视频中可能会出现黑色帧。这是因为c:v copy
仅复制了关键帧之后开始的帧,而未复制关键帧本身,导致缺少生成帧所需的数据。更多详情请参阅 FFmpeg 的 Trac 文档
以下是FFmpeg文档中的摘录,概括了相关内容:
当作为输入选项使用时,会在该输入文件中跳转至指定位置。需注意,在大多数格式中无法精确跳转,因此FFmpeg会跳转至距离指定位置最近的可跳转点。在转码时启用-accurate_seek选项(默认启用),该跳转点与指定位置之间的额外片段将被解码并丢弃。在进行流复制或使用-noaccurate_seek选项时,该片段将被保留。
关于此问题的详细解答请参阅 Stackoverflow
重新编码后的输出视频可能采用不同码率,因此可能需要相应调整输出码率(详见下方)。
🛠️ 使用GPU进行加速
使用Nvidia GPU将AVI视频转码为H264(AVC):
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_stereo.avi -c:v h264_nvenc output_gpu_264.mp4
使用Nvidia GPU将AVI视频转码为H265(HEVC):
ffmpeg -i https://storage.rendi.dev/sample/big_buck_bunny_720p_stereo.avi -c:v hevc_nvenc output_gpu_265.mp4
使用Intel GPU进行转码 – Quick Sync Video (QSV)编码器:
ffmpeg -init_hw_device qsv=hw -filter_hw_device hw -i https://storage.rendi.dev/sample/big_buck_bunny_720p_stereo.avi -c:v h264_qsv output_gpu_qsv.mp4
更复杂且支持较少的编码方式:通过 AMD GPU 及 Mesa VAAPI 驱动 进行编码
杂项
FFmpeg 安装
列出 FFmpeg 构建支持的格式:
ffmpeg -formats
列出 FFmpeg 构建支持的编解码器:
ffmpeg -codecs
FFprobe
它提供关于媒体文件的结构化元数据。显示视频文件的详细流信息:
ffprobe -show_streams -i https://storage.rendi.dev/sample/big_buck_bunny_720p_16sec.mp4
致谢
- www.bigbuckbunny.org 提供视频和图像文件。
- 音乐致谢:https://www.fiftysounds.com/music/neon-lights.mp3
- 美国国会图书馆和派拉蒙影业公司提供《大力水手》https://www.loc.gov/item/2023602008/
未来可能添加到 cheat sheet 的主题
-
- 帧率配置
- 详细说明视频比特率设置
- 详细说明音频比特率设置
- 解释1次编码和2次编码
- 概述音调、预设和配置文件选项
- ASS字幕格式
- 详细说明如何创建网络优化媒体
- 讨论使用FFmpeg进行在线视频流媒体传输
- 使用FFmpeg去除静音
- 使用FFmpeg进行批量处理
结语
如有任何问题、反馈或其他希望添加的命令,请在 Issues 部分中写下。
我将根据您的反馈和请求更新此文档。