# FFmpeg

TIP

如果是在 conda 环境中最好提前手动安装

conda install ffmpeg x264

否则安装其它包如 PyTorch 时会自动安装不支持 libx264 的版本

# 拼接多个视频

首先创建一个 mylist.txt 文件,格式如下

# this is a comment
file '/path/to/file1.mp4'
file '/path/to/file2.mp4'
file '/path/to/file3.mp4'

在 Windows Command-Line 中可以使用如下命令快速为当前文件夹生成上述文件

(for %i in (*.mp4) do @echo file '%i') > mylist.txt

进行拼接

ffmpeg -f concat -i mylist.txt -c copy output.mp4

https://trac.ffmpeg.org/wiki/Concatenate (opens new window)

# 格式转换

# MP4

转换 mkvavimp4

ffmpeg -i input.mkv -c copy output.mp4

转换 wmvmp4

ffmpeg -i input.wmv -c:v libx264 -crf 17 output.mp4

https://trac.ffmpeg.org/wiki/Encode/H.264 (opens new window)

# 动图

# GIF

ffmpeg -ss 1 -to 4 -i input.mp4 \
    -vf "fps=10,scale=320:-1:flags=lanczos,split[a][b];[a]palettegen[p];[b][p]paletteuse" \
    output.gif

https://superuser.com/a/556031 (opens new window)

# WebP

ffmpeg -ss 1 -to 4 -i input.mp4 -vcodec libwebp -vf "fps=fps=15,scale=640:360" \
    -lossless 1 -loop 0 -preset default -an -vsync 0 output.webp

https://gist.github.com/witmin/1edf926c2886d5c8d9b264d70baf7379 (opens new window)

需要裁剪的时候在 -vf 中加入 crop=w:h:x:y 即可

# 将图像序列合并为视频

ffmpeg [-framerate 24] -i images/%4d.jpg [-frames:v <num_frames>] [-s 1920x1080] [-crf 18] \
    output.mp4

也可以使用 glob 选择图片 -pattern_type glob -i 'images/*.jpg'(因为 glob pattern 包含星号等特殊符号所以注意使用引号)

# 多个视频 side-by-side

ffmpeg -i left.mp4 -i right.mp4 -filter_complex hstack output.mp4

如果是三个视频则可以使用 hstack=inputs=3

除了 hstackvstack,还可以使用 xstack,其支持参数比如 grid=3x2(3 列 2 行),比较旧的版本可能还不支持(可以从官网提供的这个链接 (opens new window)下载 Linux 下编译好的单文件二进制)

# 裁剪、缩放、填衬视频

  • crop=<w>:<h>:<x>:<y>
  • scale=<w>:<h>
  • pad=<w>:<h>:<x>:<y>[:<color>]

wh 可以只指定一个值,另一个用 -1 由原本的长宽比来确定,-2 则额外要求其是偶数

使用逗号 , 连接,依次应用多个 filter (FilteringGuide (opens new window))

## 将视频缩放为 200x200,然后竖直方向居中填充至 200x400 大小
ffmpeg -i input -vf 'scale=200:200,pad=200:400:0:(oh-ih)/2' output

可以使用 iwowihoh 等变量,以及 /* 等来计算相应参数

https://ffmpeg.org/ffmpeg-filters.html (opens new window)

# 叠加视频

fg.mp4 缩小、变透明,然后叠加在 bg.mp4 左下角

ffmpeg -i bg.mp4 -i fg.mp4 -filter_complex \
'[0:v]null[bg]; \
[1:v]scale=-1:480,format=rgba,colorchannelmixer=aa=0.8[fg]; \
[bg][fg]overlay=0:(main_h-overlay_h)' \
-crf 15 out.mp4

(如果运行有问题可以将 filter 参数写成一行再运行)

# 仅保留视频或音频

-an 去除音频

ffmpeg -i input.mp4 -c copy -an output.mp4

-vn 去除视频

ffmpeg -i input.mp4 -c copy -vn output.aac

# 添加文字

style_str="fontfile=noto-sans.ttf:fontsize=36:fontcolor=white:shadowx=2:shadowy=2:shadowcolor=black"
ffmpeg -i input.mp4 -vf "drawtext=text='hello world':x=60:y=60:$style_str" -crf 16 output.mp4

# GPU

Using FFmpeg with NVIDIA GPU Hardware Acceleration – NVIDIA Docs (opens new window)

ffmpeg -vsync 0 -hwaccel cuvid -c:v h264_cuvid -i input.mp4 -c:a copy -c:v h264_nvenc \
    -b:v 0 -cq 27 output.mp4

where

-b:v 0  overrides the default 2mbps bitrate as noted by Gyan
-cq 1   target quality level (range of 0-51)
        0 means automatic (in my case around 15mbps)
        1 gives about 15mbps, 26 results in around 5mbps, 51 results in 0.5mbps

Configure CQP (CRF) for h264_nvenc – StackExchange (opens new window)

HEVC 编码就用 hevc_nvenc

HWAccelIntro > CUDA (NVENC/NVDEC) – FFmpeg (opens new window)

查看 encoder 帮助

ffmpeg -h encoder=h264_nvenc

其中有 supported pixel formats 信息以及 encoder 设置项

# 编码质量

GPU 最高质量使用 -preset p7-pix_fmt p010le (10 bit depth),-rc-lookahead 20

https://www.reddit.com/r/ffmpeg/comments/ystse6/hevc_nvenc_2pass_question/ (opens new window)

GPU 转码效果为什么不如纯 CPU?– 知乎 (opens new window)


此外,不论是否使用 GPU 编码,关键帧间隔可以使用 -g 参数 (Group of Picture size) 设置,可以理解为两个关键帧之间的帧数。如果希望每 3 秒一个关键帧则可以设置为 3 倍 fps 大小

# 查看帮助

ffmpeg -h filter=xstack
ffmpeg -h encoder=h264_nvenc

# Extra

# 视频下载工具 lux (opens new window)

e.g. Bilibili

## -c 提供 cookie
## -i 查询提供的格式
## -f 下载指定的格式
lux -c "SESSDATA=<cookie_value>" -i "https://www.bilibili.com/video/BVxxxxxxxxxx/"
lux -c "SESSDATA=<cookie_value>" -f 80-7 "https://www.bilibili.com/video/BVxxxxxxxxxx/"
youtube-dl

list available formats

youtube-dl -F <url>

download the selected format

youtube-dl -f <format_code> <url>

others

youtube-dl [--proxy <proxy>] -f 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/bestvideo+bestaudio' --merge-output-format mp4 <url>

# Fix for "Too short!" error on avidemux

# This will recreate timestamps on the stream allowing avidemux to export the file.
# Note that the output has to be a Matroska container (.mkv).
# <https://gist.github.com/dmcallejo/3aef05029222eb38604a61b1623784c8>
ffmpeg -start_at_zero -copyts -i input_file.ts -map 0:v -c copy -map 0:a:0 output_file.mkv
Last updated: 5/4/2024, 3:19:10 PM