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

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

编解码器选择

视频编解码器对比

编解码器类型压缩率速度兼容性适用场景
libx264H.264极好通用视频
libx265H.265极高4K/8K 视频
libvpx-vp9VP9Web 视频
libaom-av1AV1极高极慢未来格式
libsvtav1SVT-AV1极高批量 AV1
h264_nvencH.264极快极好实时处理
hevc_nvencH.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

音频编解码器对比

编解码器类型质量速度兼容性适用场景
aacAAC极好通用音频
libfdk-aacAAC极高极好高质量音频
libmp3lameMP3极好兼容性需求
libopusOpus极高低延迟音频
libvorbisVorbis开源格式
flacFLAC无损无损音频
# 使用 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 值范围:

编解码器范围推荐值说明
libx2640-5118-23值越小质量越高
libx2650-5122-28值越小质量越高
libvpx-vp90-6330-35值越小质量越高
libaom-av10-6325-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.0720×48030fps10Mbps
3.11280×72030fps14Mbps
4.01920×108030fps20Mbps
4.11920×108030fps50Mbps
5.01920×108060fps25Mbps
5.11920×108060fps50Mbps
# 基线配置(移动设备)
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 码率
480p1-2 Mbps0.5-1 Mbps0.5-1 Mbps
720p2-4 Mbps1-2 Mbps1-2 Mbps
1080p4-8 Mbps2-4 Mbps2-4 Mbps
1440p8-12 Mbps4-8 Mbps4-8 Mbps
4K15-30 Mbps8-15 Mbps8-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)
  • 两遍编码
  • 高级转码技巧
  • 批量转码方法

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