Skip to content

高级技巧

本文档介绍 FFMPEG 的高级使用技巧,包括视频速度调整、合并、滤镜、水印、字幕处理等。

视频速度调整

调整播放速度(音调不变)

bash
# 2 倍速
ffmpeg -i input.mp4 -filter:v "setpts=0.5*PTS" -filter:a "atempo=2.0" output.mp4

# 0.5 倍速(慢动作)
ffmpeg -i input.mp4 -filter:v "setpts=2.0*PTS" -filter:a "atempo=0.5" output.mp4

# 1.5 倍速
ffmpeg -i input.mp4 -filter:v "setpts=0.666*PTS" -filter:a "atempo=1.5" output.mp4

参数说明

  • setpts: 视频时间戳调整(PTS = Presentation Time Stamp)
  • atempo: 音频速度调整(范围:0.5 - 2.0)
  • 超过 2 倍速需要多次应用 atempo

变速示例

bash
# 4 倍速(需要两次 atempo)
ffmpeg -i input.mp4 \
  -filter:v "setpts=0.25*PTS" \
  -filter:a "atempo=2.0,atempo=2.0" \
  output.mp4

视频合并

合并多个视频文件

方法一:使用 concat demuxer(推荐)

bash
# 创建文件列表
echo "file 'video1.mp4'" > filelist.txt
echo "file 'video2.mp4'" >> filelist.txt
echo "file 'video3.mp4'" >> filelist.txt

# 合并(不重新编码,速度快)
ffmpeg -f concat -safe 0 -i filelist.txt -c copy output.mp4

方法二:使用 concat filter(需要重新编码)

bash
ffmpeg -i video1.mp4 -i video2.mp4 -i video3.mp4 \
  -filter_complex "[0:v][0:a][1:v][1:a][2:v][2:a]concat=n=3:v=1:a=1[outv][outa]" \
  -map "[outv]" -map "[outa]" output.mp4

合并不同格式的视频

bash
# 先统一格式,再合并
ffmpeg -i video1.mov -i video2.avi \
  -c:v libx264 -c:a aac \
  -f concat -safe 0 -i filelist.txt \
  output.mp4

视频水印

添加图片水印

bash
# 左上角
ffmpeg -i input.mp4 -i watermark.png \
  -filter_complex "[0:v][1:v]overlay=10:10" \
  output.mp4

# 右下角
ffmpeg -i input.mp4 -i watermark.png \
  -filter_complex "[0:v][1:v]overlay=W-w-10:H-h-10" \
  output.mp4

# 居中
ffmpeg -i input.mp4 -i watermark.png \
  -filter_complex "[0:v][1:v]overlay=(W-w)/2:(H-h)/2" \
  output.mp4

添加文字水印

bash
# 使用 drawtext 滤镜
ffmpeg -i input.mp4 \
  -vf "drawtext=text='Watermark Text':fontfile=/path/to/font.ttf:fontsize=24:fontcolor=white:x=10:y=10" \
  output.mp4

半透明水印

bash
# 调整水印透明度
ffmpeg -i input.mp4 -i watermark.png \
  -filter_complex "[1:v]format=rgba,colorchannelmixer=aa=0.5[watermark];[0:v][watermark]overlay=10:10" \
  output.mp4

字幕处理

添加字幕文件

bash
# 硬编码字幕(字幕成为视频的一部分)
ffmpeg -i input.mp4 -vf "subtitles=subtitle.srt" output.mp4

# 软字幕(字幕作为独立轨道)
ffmpeg -i input.mp4 -i subtitle.srt \
  -c:v copy -c:a copy \
  -c:s mov_text \
  -metadata:s:s:0 language=chi \
  output.mp4

提取字幕

bash
# 从视频中提取字幕
ffmpeg -i input.mp4 -map 0:s:0 subtitle.srt

字幕格式转换

bash
# ASS 转 SRT
ffmpeg -i subtitle.ass subtitle.srt

视频滤镜

亮度调整

bash
# 增加亮度
ffmpeg -i input.mp4 -vf "eq=brightness=0.1" output.mp4

# 减少亮度
ffmpeg -i input.mp4 -vf "eq=brightness=-0.1" output.mp4

对比度调整

bash
# 增加对比度
ffmpeg -i input.mp4 -vf "eq=contrast=1.2" output.mp4

饱和度调整

bash
# 增加饱和度
ffmpeg -i input.mp4 -vf "eq=saturation=1.5" output.mp4

旋转视频

bash
# 顺时针旋转 90 度
ffmpeg -i input.mp4 -vf "transpose=1" output.mp4

# 逆时针旋转 90 度
ffmpeg -i input.mp4 -vf "transpose=2" output.mp4

# 180 度旋转
ffmpeg -i input.mp4 -vf "transpose=1,transpose=1" output.mp4

镜像翻转

bash
# 水平翻转
ffmpeg -i input.mp4 -vf "hflip" output.mp4

# 垂直翻转
ffmpeg -i input.mp4 -vf "vflip" output.mp4

画中画效果

添加小窗口视频

bash
# 在右下角添加小窗口
ffmpeg -i main_video.mp4 -i small_video.mp4 \
  -filter_complex "[1:v]scale=320:240[small];[0:v][small]overlay=W-w-10:H-h-10" \
  output.mp4

分屏显示

bash
# 左右分屏
ffmpeg -i left.mp4 -i right.mp4 \
  -filter_complex "[0:v]scale=960:540[left];[1:v]scale=960:540[right];[left][right]hstack" \
  output.mp4

# 上下分屏
ffmpeg -i top.mp4 -i bottom.mp4 \
  -filter_complex "[0:v]scale=1920:540[top];[1:v]scale=1920:540[bottom];[top][bottom]vstack" \
  output.mp4

批量处理脚本

批量转码脚本

bash
#!/bin/bash
# 批量转码脚本

INPUT_DIR="./videos"
OUTPUT_DIR="./output"
CRF=23
PRESET="slow"

mkdir -p "$OUTPUT_DIR"

for file in "$INPUT_DIR"/*.mp4; do
    if [ -f "$file" ]; then
        filename=$(basename "$file")
        output="$OUTPUT_DIR/${filename%.mp4}_compressed.mp4"
        
        echo "处理: $filename"
        ffmpeg -i "$file" \
            -vcodec libx264 \
            -crf "$CRF" \
            -preset "$PRESET" \
            -acodec aac \
            -b:a 128k \
            "$output" 2>&1 | grep -E "(error|Error|ERROR)" && echo "错误: $filename" || echo "完成: $output"
    fi
done

批量添加水印

bash
#!/bin/bash
# 批量添加水印

INPUT_DIR="./videos"
OUTPUT_DIR="./output"
WATERMARK="./watermark.png"

mkdir -p "$OUTPUT_DIR"

for file in "$INPUT_DIR"/*.mp4; do
    filename=$(basename "$file")
    output="$OUTPUT_DIR/${filename%.mp4}_watermarked.mp4"
    
    echo "添加水印: $filename"
    ffmpeg -i "$file" -i "$WATERMARK" \
        -filter_complex "[0:v][1:v]overlay=W-w-10:H-h-10" \
        -c:a copy \
        "$output"
done

批量提取帧

bash
#!/bin/bash
# 批量提取帧

INPUT_DIR="./videos"
OUTPUT_BASE="./frames"

for file in "$INPUT_DIR"/*.mp4; do
    filename=$(basename "$file")
    output_dir="$OUTPUT_BASE/${filename%.mp4}"
    
    mkdir -p "$output_dir"
    echo "提取帧: $filename"
    ffmpeg -i "$file" -vf fps=1 "$output_dir/%08d.png"
done

性能优化技巧

多线程处理

bash
# 使用多线程编码
ffmpeg -i input.mp4 -threads 4 -c:v libx264 output.mp4

硬件加速

bash
# NVIDIA GPU 加速
ffmpeg -hwaccel cuda -i input.mp4 -c:v h264_nvenc output.mp4

# Intel Quick Sync
ffmpeg -hwaccel qsv -i input.mp4 -c:v h264_qsv output.mp4

内存优化

bash
# 限制内存使用
ffmpeg -i input.mp4 -threads 2 -c:v libx264 output.mp4

常见问题解决

1. 视频无法播放

问题:转码后的视频在某些设备上无法播放

解决方案

  • 使用 -profile:v high-level 4.0
  • 确保像素格式为 yuv420p
  • 使用 H.264 编码

2. 处理速度慢

问题:转码速度太慢

解决方案

  • 使用硬件加速
  • 调整 preset 为 faster
  • 使用多线程
  • 考虑使用 -c copy 避免重新编码

3. 文件过大

问题:输出文件太大

解决方案

  • 调整 CRF 值(增大)
  • 降低分辨率
  • 降低音频比特率
  • 使用更高效的编码格式(如 H.265)

返回FFMPEG 专题首页