强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

FFmpeg 多媒体处理教程 / 转码技术

转码技术

概述

转码(Transcoding)是 FFmpeg 最核心的功能之一,指将视频或音频从一种编码格式转换为另一种编码格式的过程。本章详细介绍编解码器选择、质量控制、码率设置等转码技术。

转码基础

转码流程

输入文件 → 解封装 → 解码 → 处理 → 编码 → 封装 → 输出文件
   │         │       │      │      │      │        │
   │         │       │      │      │      │        │
   ▼         ▼       ▼      ▼      ▼      ▼        ▼
 MP4      Demuxer  Decoder Filter Encoder Muxer   MKV

复制 vs 转码

方式 命令 优点 缺点
复制 -c copy 速度快、无质量损失 不能改变编解码参数
转码 -c:v libx264 可调整参数 速度慢、有质量损失
# 复制流(不重新编码)
ffmpeg -i input.mp4 -c copy output.mkv

# 转码(重新编码)
ffmpeg -i input.mp4 -c:v libx264 -c:a aac output.mkv

编解码器选择

视频编解码器对比

编解码器 类型 压缩率 速度 兼容性 适用场景
libx264 H.264 极好 通用视频
libx265 H.265 极高 4K/8K 视频
libvpx-vp9 VP9 Web 视频
libaom-av1 AV1 极高 极慢 未来格式
libsvtav1 SVT-AV1 极高 批量 AV1
h264_nvenc H.264 极快 极好 实时处理
hevc_nvenc H.265 极快 GPU 加速
# 使用 H.264
ffmpeg -i input.mp4 -c:v libx264 -preset medium -crf 23 output.mp4

# 使用 H.265
ffmpeg -i input.mp4 -c:v libx265 -preset medium -crf 28 output.mp4

# 使用 VP9
ffmpeg -i input.mp4 -c:v libvpx-vp9 -crf 30 -b:v 0 output.webm

# 使用 AV1
ffmpeg -i input.mp4 -c:v libaom-av1 -crf 30 -b:v 0 -cpu-used 4 output.mkv

音频编解码器对比

编解码器 类型 质量 速度 兼容性 适用场景
aac AAC 极好 通用音频
libfdk-aac AAC 极高 极好 高质量音频
libmp3lame MP3 极好 兼容性需求
libopus Opus 极高 低延迟音频
libvorbis Vorbis 开源格式
flac FLAC 无损 无损音频
# 使用 AAC
ffmpeg -i input.wav -c:a aac -b:a 192k output.m4a

# 使用 libfdk-aac(更高质量)
ffmpeg -i input.wav -c:a libfdk-aac -b:a 192k output.m4a

# 使用 MP3
ffmpeg -i input.wav -c:a libmp3lame -q:a 2 output.mp3

# 使用 Opus
ffmpeg -i input.wav -c:a libopus -b:a 128k output.opus

# 使用 FLAC(无损)
ffmpeg -i input.wav -c:a flac output.flac

质量控制

CRF(恒定质量因子)

CRF(Constant Rate Factor)是最推荐的质量控制方式,它在保证视觉质量的同时最小化文件大小。

CRF 值范围:

编解码器 范围 推荐值 说明
libx264 0-51 18-23 值越小质量越高
libx265 0-51 22-28 值越小质量越高
libvpx-vp9 0-63 30-35 值越小质量越高
libaom-av1 0-63 25-35 值越小质量越高
# 高质量(大文件)
ffmpeg -i input.mp4 -c:v libx264 -crf 18 output.mp4

# 标准质量(推荐)
ffmpeg -i input.mp4 -c:v libx264 -crf 23 output.mp4

# 低质量(小文件)
ffmpeg -i input.mp4 -c:v libx264 -crf 28 output.mp4

# H.265 CRF(推荐值略高于 H.264)
ffmpeg -i input.mp4 -c:v libx265 -crf 28 output.mp4

CRF 与视觉质量对应:

CRF 范围 视觉质量 适用场景
0-17 无损/近无损 存档、后期制作
18-22 高质量 高清视频、蓝光
23-27 标准质量 网络视频、日常使用
28-32 中等质量 移动设备、带宽受限
33-51 低质量 预览、草稿

预设(Preset)

预设控制编码速度和压缩效率的平衡:

预设 速度 压缩效率 适用场景
ultrafast 最快 最低 实时编码
superfast 很快 很低 快速预览
veryfast 日常使用
faster 较快 较低 快速编码
fast 一般用途
medium 默认设置
slow 高质量
slower 很慢 很高 存档
veryslow 最慢 最高 最高质量
# 使用 ultrafast 预设
ffmpeg -i input.mp4 -c:v libx264 -preset ultrafast output.mp4

# 使用 medium 预设(默认)
ffmpeg -i input.mp4 -c:v libx264 -preset medium output.mp4

# 使用 slow 预设
ffmpeg -i input.mp4 -c:v libx264 -preset slow output.mp4

Tune 参数

Tune 参数用于针对特定内容优化:

Tune 说明 适用场景
film 电影内容 电影、电视剧
animation 动画内容 动画片、卡通
grain 胶片颗粒 老电影、胶片
stillimage 静态图像 幻灯片
fastdecode 快速解码 低端设备
zerolatency 零延迟 直播、实时
# 电影优化
ffmpeg -i input.mp4 -c:v libx264 -preset slow -tune film output.mp4

# 动画优化
ffmpeg -i input.mp4 -c:v libx264 -preset slow -tune animation output.mp4

# 零延迟(直播)
ffmpeg -i input.mp4 -c:v libx264 -preset ultrafast -tune zerolatency output.mp4

Profile 和 Level

Profile 定义编码特性集合,Level 定义性能限制:

H.264 Profile:

Profile 特性 兼容性 适用场景
baseline 基础特性 最好 移动设备
main 主要特性 标清视频
high 高级特性 高清视频

H.264 Level:

Level 最大分辨率 最大帧率 最大码率
3.0 720×480 30fps 10Mbps
3.1 1280×720 30fps 14Mbps
4.0 1920×1080 30fps 20Mbps
4.1 1920×1080 30fps 50Mbps
5.0 1920×1080 60fps 25Mbps
5.1 1920×1080 60fps 50Mbps
# 基线配置(移动设备)
ffmpeg -i input.mp4 -c:v libx264 -profile:v baseline -level 3.0 output.mp4

# 主配置(标清)
ffmpeg -i input.mp4 -c:v libx264 -profile:v main -level 3.1 output.mp4

# 高配置(高清)
ffmpeg -i input.mp4 -c:v libx264 -profile:v high -level 4.1 output.mp4

码率控制

固定码率(CBR)

# 固定视频码率
ffmpeg -i input.mp4 -c:v libx264 -b:v 2M output.mp4

# 固定音频码率
ffmpeg -i input.mp4 -c:a aac -b:a 128k output.mp4

# 固定总码率
ffmpeg -i input.mp4 -c:v libx264 -b:v 2M -c:a aac -b:a 128k output.mp4

可变码率(VBR)

# 使用 CRF 模式(推荐)
ffmpeg -i input.mp4 -c:v libx264 -crf 23 output.mp4

# 使用 CQ 模式(硬件编码器)
ffmpeg -i input.mp4 -c:v h264_nvenc -cq 23 output.mp4

# 使用 QP 模式
ffmpeg -i input.mp4 -c:v libx264 -qp 23 output.mp4

码率限制

# 设置最大码率
ffmpeg -i input.mp4 -c:v libx264 -b:v 2M -maxrate 2.5M -bufsize 5M output.mp4

# 使用 VBV 模型(流媒体推荐)
ffmpeg -i input.mp4 -c:v libx264 -b:v 2M -maxrate 2M -bufsize 4M output.mp4

码率推荐

按分辨率推荐码率:

分辨率 H.264 码率 H.265 码率 VP9 码率
480p 1-2 Mbps 0.5-1 Mbps 0.5-1 Mbps
720p 2-4 Mbps 1-2 Mbps 1-2 Mbps
1080p 4-8 Mbps 2-4 Mbps 2-4 Mbps
1440p 8-12 Mbps 4-8 Mbps 4-8 Mbps
4K 15-30 Mbps 8-15 Mbps 8-15 Mbps

两遍编码

原理

两遍编码(Two-Pass Encoding)通过两次扫描视频来优化码率分配:

  1. 第一遍:分析视频内容,生成统计信息
  2. 第二遍:根据统计信息分配码率

使用方法

# 两遍编码(第一遍)
ffmpeg -i input.mp4 -c:v libx264 -b:v 2M -pass 1 -an -f null /dev/null

# 两遍编码(第二遍)
ffmpeg -i input.mp4 -c:v libx264 -b:v 2M -pass 2 -c:a aac -b:a 128k output.mp4

完整两遍编码脚本

#!/bin/bash
# two_pass_encode.sh

INPUT=$1
OUTPUT=$2
VIDEO_BITRATE=${3:-2M}
AUDIO_BITRATE=${4:-128k}

# 第一遍
ffmpeg -y -i "$INPUT" \
    -c:v libx264 \
    -b:v "$VIDEO_BITRATE" \
    -pass 1 \
    -an \
    -f null /dev/null

# 第二遍
ffmpeg -y -i "$INPUT" \
    -c:v libx264 \
    -b:v "$VIDEO_BITRATE" \
    -pass 2 \
    -c:a aac \
    -b:a "$AUDIO_BITRATE" \
    "$OUTPUT"

# 清理临时文件
rm -f ffmpeg2pass-0.log ffmpeg2pass-0.log.mbtree

echo "编码完成: $OUTPUT"

两遍编码 vs CRF

方面 两遍编码 CRF
码率控制 精确控制目标码率 无法精确控制
质量 均匀质量分布 可能不均匀
速度 两倍时间 单次处理
适用场景 带宽限制严格 质量优先

高级转码技巧

分辨率调整

# 缩放到 720p
ffmpeg -i input.mp4 -vf scale=1280:720 -c:v libx264 -c:a copy output.mp4

# 保持宽高比
ffmpeg -i input.mp4 -vf "scale=1280:720:force_original_aspect_ratio=decrease" -c:v libx264 output.mp4

# 填充黑边
ffmpeg -i input.mp4 -vf "scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2" -c:v libx264 output.mp4

帧率调整

# 降低帧率
ffmpeg -i input.mp4 -vf fps=24 -c:v libx264 output.mp4

# 提高帧率(不推荐)
ffmpeg -i input.mp4 -vf fps=60 -c:v libx264 output.mp4

# 去除重复帧
ffmpeg -i input.mp4 -vf "fps=fps=source_fps:round=near" -c:v libx264 output.mp4

像素格式转换

# 转换为 yuv420p(兼容性最好)
ffmpeg -i input.mp4 -pix_fmt yuv420p -c:v libx264 output.mp4

# 转换为 yuv422p10le(10bit)
ffmpeg -i input.mp4 -pix_fmt yuv422p10le -c:v libx265 -profile:v main10 output.mp4

HDR 到 SDR 转换

# HDR 到 SDR 色调映射
ffmpeg -i input_hdr.mp4 -vf "zscale=t=linear:npl=100,format=gbrpf32le,zscale=p=bt709,tonemap=tonemap=hable:desat=0,zscale=t=bt709:m=bt709:r=tv,format=yuv420p" -c:v libx264 output_sdr.mp4

质量对比脚本

#!/bin/bash
# compare_quality.sh

INPUT=$1

# 不同 CRF 值编码
for crf in 18 20 22 24 26 28 30; do
    ffmpeg -y -i "$INPUT" -c:v libx264 -crf "$crf" -preset slow "output_crf${crf}.mp4"
    
    # 计算 PSNR
    ffmpeg -i "$INPUT" -i "output_crf${crf}.mp4" -lavfi psnr -f null - 2>&1 | grep PSNR
    
    # 显示文件大小
    ls -lh "output_crf${crf}.mp4" | awk '{print $5}'
done

批量转码

批量转码脚本

#!/bin/bash
# batch_transcode.sh

INPUT_DIR=${1:-.}
OUTPUT_DIR=${2:-output}
CODEC=${3:-libx264}
CRF=${4:-23}

mkdir -p "$OUTPUT_DIR"

for file in "$INPUT_DIR"/*.mp4; do
    filename=$(basename "$file")
    output="$OUTPUT_DIR/${filename%.mp4}_transcoded.mp4"
    
    echo "转码: $file -> $output"
    ffmpeg -y -i "$file" -c:v "$CODEC" -crf "$CRF" -c:a aac -b:a 128k "$output"
done

echo "批量转码完成"

并行转码

#!/bin/bash
# parallel_transcode.sh

INPUT_DIR=${1:-.}
OUTPUT_DIR=${2:-output}
MAX_JOBS=${3:-4}

mkdir -p "$OUTPUT_DIR"

transcode() {
    local file=$1
    local filename=$(basename "$file")
    local output="$OUTPUT_DIR/${filename%.mp4}_transcoded.mp4"
    
    ffmpeg -y -i "$file" -c:v libx264 -crf 23 -c:a aac -b:a 128k "$output"
    echo "完成: $filename"
}

export -f transcode
export OUTPUT_DIR

find "$INPUT_DIR" -name "*.mp4" -print0 | xargs -0 -P "$MAX_JOBS" -I {} bash -c 'transcode "$@"' _ {}

echo "并行转码完成"

常见转码场景

场景 1:Web 视频优化

# 为 Web 播放优化
ffmpeg -i input.mp4 \
    -c:v libx264 \
    -preset slow \
    -crf 23 \
    -profile:v high \
    -level 4.1 \
    -movflags +faststart \
    -c:a aac \
    -b:a 128k \
    output_web.mp4

场景 2:移动设备兼容

# 移动设备兼容格式
ffmpeg -i input.mp4 \
    -c:v libx264 \
    -profile:v baseline \
    -level 3.0 \
    -vf scale=640:480 \
    -c:a aac \
    -b:a 96k \
    -ar 44100 \
    -ac 2 \
    output_mobile.mp4

场景 3:4K 视频压缩

# 4K 视频压缩
ffmpeg -i input_4k.mp4 \
    -c:v libx265 \
    -preset slow \
    -crf 26 \
    -tag:v hvc1 \
    -c:a aac \
    -b:a 192k \
    output_4k_compressed.mp4

场景 4:直播转码

# 低延迟直播转码
ffmpeg -re -i input.mp4 \
    -c:v libx264 \
    -preset ultrafast \
    -tune zerolatency \
    -b:v 2M \
    -maxrate 2M \
    -bufsize 4M \
    -c:a aac \
    -b:a 128k \
    -f flv rtmp://server/live/stream

场景 5:存档级转码

# 高质量存档
ffmpeg -i input.mp4 \
    -c:v libx264 \
    -preset veryslow \
    -crf 18 \
    -profile:v high \
    -c:a flac \
    output_archive.mkv

注意事项

  1. 编解码器选择:H.264 兼容性最好,H.265 压缩率更高但兼容性稍差
  2. CRF 值选择:不同编解码器的 CRF 值不能直接对比
  3. 预设选择:预设越慢质量越好,但编码时间越长
  4. 两遍编码:需要精确码率控制时使用两遍编码
  5. 硬件加速:GPU 编码速度快但质量略低于 CPU 编码

扩展阅读

  1. FFmpeg H.264 编码指南
  2. FFmpeg H.265 编码指南
  3. FFmpeg VP9 编码指南
  4. FFmpeg AV1 编码指南
  5. Video Encoding Settings for Top UGC Platforms

总结

本章介绍了 FFmpeg 的转码技术,包括:

  • 编解码器选择
  • 质量控制(CRF、预设、Tune)
  • 码率控制(CBR、VBR)
  • 两遍编码
  • 高级转码技巧
  • 批量转码方法

掌握这些技术可以帮助您在不同场景下选择合适的转码策略。