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

FFmpeg 多媒体处理教程 / 故障排除

故障排除

概述

在使用 FFmpeg 过程中,可能会遇到各种问题。本章介绍常见问题的原因和解决方法,以及调试技巧。

常见错误与解决

编解码器错误

错误:找不到编解码器

Error: encoder 'libx264' not found

原因: FFmpeg 编译时未启用该编解码器。

解决方法:

# 检查可用的编解码器
ffmpeg -encoders | grep x264
ffmpeg -decoders | grep x264

# 如果没有,需要重新编译 FFmpeg 并启用该编解码器
./configure --enable-libx264
make && make install

错误:编解码器不支持

Error: NVENC: Codec not supported

原因: 硬件不支持该编解码器或参数。

解决方法:

# 检查硬件支持
ffmpeg -hwaccels
ffmpeg -encoders | grep nvenc

# 检查 GPU 信息
nvidia-smi

# 使用支持的参数
ffmpeg -i input.mp4 -c:v h264_nvenc -preset p1 output.mp4

错误:参数无效

Error: Invalid value for option crf

原因: 编解码器不支持该参数或参数值超出范围。

解决方法:

# 查看编解码器支持的参数
ffmpeg -h encoder=libx264

# 使用正确的参数范围
# libx264 CRF: 0-51
ffmpeg -i input.mp4 -c:v libx264 -crf 23 output.mp4

格式错误

错误:无法写入输出文件

Error: Could not write header for output file

原因: 输出格式不支持所选编解码器或路径问题。

解决方法:

# 检查输出目录是否存在
mkdir -p /path/to/output

# 检查格式兼容性
ffmpeg -formats | grep mp4

# 使用兼容的编解码器
ffmpeg -i input.mkv -c:v libx264 -c:a aac output.mp4

错误:格式不支持

Error: Unknown input format

原因: FFmpeg 不识别输入文件格式。

解决方法:

# 强制指定格式
ffmpeg -f rawvideo -video_size 1920x1080 -i input.raw output.mp4

# 检查文件信息
ffprobe input.file

# 检查支持的格式
ffmpeg -formats

网络错误

错误:连接超时

Error: Connection timed out

原因: 网络连接问题或服务器不可达。

解决方法:

# 增加超时时间
ffmpeg -timeout 10000000 -i rtsp://server/stream output.mp4

# 使用 TCP 传输
ffmpeg -rtsp_transport tcp -i rtsp://server/stream output.mp4

# 检查网络连接
ping server
curl -I http://server/stream

错误:流断开

Error: Server returned 404 Not Found

原因: 流地址错误或流已结束。

解决方法:

# 检查流地址
ffprobe rtsp://server/stream

# 添加重试机制
while true; do
    ffmpeg -i rtmp://server/live/stream -c copy output.mp4
    sleep 5
done

内存错误

错误:内存不足

Error: Cannot allocate memory

原因: 系统内存不足或 FFmpeg 内存使用过多。

解决方法:

# 限制内存使用
ffmpeg -i input.mp4 -c:v libx264 -preset ultrafast output.mp4

# 分段处理
ffmpeg -i input.mp4 -ss 00:00:00 -t 01:00:00 -c copy part1.mp4
ffmpeg -i input.mp4 -ss 01:00:00 -t 01:00:00 -c copy part2.mp4

# 降低分辨率
ffmpeg -i input.mp4 -vf scale=640:360 -c:v libx264 output.mp4

同步问题

音视频不同步

Audio/Video synchronization issues

原因: 时间戳问题或编解码延迟。

解决方法:

# 使用 -async 选项
ffmpeg -i input.mp4 -c:v libx264 -c:a aac -async 1 output.mp4

# 使用 -copyts 保留时间戳
ffmpeg -i input.mp4 -c copy -copyts output.mp4

# 重置时间戳
ffmpeg -i input.mp4 -c copy -output_ts_offset 0 output.mp4

# 使用 -avoid_negative_ts
ffmpeg -i input.mp4 -c copy -avoid_negative_ts make_zero output.mp4

音频延迟

Audio is ahead/behind video

解决方法:

# 音频延迟
ffmpeg -i input.mp4 -itsoffset 0.5 -i input.mp4 -map 0:v -map 1:a -c copy output.mp4

# 视频延迟
ffmpeg -i input.mp4 -itsoffset -0.5 -i input.mp4 -map 1:v -map 0:a -c copy output.mp4

硬件加速错误

错误:设备不可用

Error: No capable devices found

原因: GPU 驱动问题或设备权限问题。

解决方法:

# 检查设备
ls -la /dev/dri/

# 检查驱动
nvidia-smi  # NVIDIA
vainfo      # Intel/AMD

# 添加用户到 video 组
sudo usermod -aG video $USER

# 检查 NVIDIA 容器工具包
docker run --rm --gpus all nvidia/cuda:12.0.0-base-ubuntu22.04 nvidia-smi

错误:NVENC 会话数限制

Error: Too many concurrent sessions

原因: 消费级 GPU 有编码会话数限制。

解决方法:

# 检查会话数
nvidia-smi -q | grep "Encoder Sessions"

# 减少并发会话数
# 或使用破解驱动解除限制

字幕错误

错误:字幕编码问题

Error: Invalid UTF-8

原因: 字幕文件编码不是 UTF-8。

解决方法:

# 转换编码
iconv -f GBK -t UTF-8 subtitle_gbk.srt > subtitle_utf8.srt

# 指定编码
ffmpeg -charenc GBK -i subtitle.srt -c:s srt output.srt

调试技巧

日志级别

# 静默模式
ffmpeg -v quiet -i input.mp4 output.mp4

# 仅显示错误
ffmpeg -v error -i input.mp4 output.mp4

# 显示警告
ffmpeg -v warning -i input.mp4 output.mp4

# 显示信息(默认)
ffmpeg -v info -i input.mp4 output.mp4

# 显示详细信息
ffmpeg -v verbose -i input.mp4 output.mp4

# 显示调试信息
ffmpeg -v debug -i input.mp4 output.mp4

性能统计

# 显示性能统计
ffmpeg -benchmark -i input.mp4 output.mp4

# 显示编码统计
ffmpeg -i input.mp4 -c:v libx264 -stats output.mp4

格式分析

# 详细文件信息
ffprobe -v verbose input.mp4

# JSON 格式输出
ffprobe -v quiet -print_format json -show_format -show_streams input.mp4

# 显示所有信息
ffprobe -v quiet -show_format -show_streams -show_packets input.mp4

流分析

# 显示流信息
ffprobe -show_streams input.mp4

# 显示特定流
ffprobe -show_entries stream=codec_name,codec_type input.mp4

# 显示视频流详情
ffprobe -show_entries stream=width,height,r_frame_rate,pix_fmt input.mp4

# 显示音频流详情
ffprobe -show_entries stream=sample_rate,channels,channel_layout input.mp4

时间戳分析

# 显示时间戳
ffprobe -show_entries packet=pts_time,dts_time input.mp4

# 显示帧时间戳
ffprobe -show_entries frame=pts_time,pkt_dts_time input.mp4

常见问题排查

问题 1:输出文件为空

症状: 输出文件大小为 0 或很小。

排查步骤:

# 1. 检查输入文件
ffprobe input.mp4

# 2. 检查输出日志
ffmpeg -i input.mp4 output.mp4 2>&1 | tail -20

# 3. 尝试复制流
ffmpeg -i input.mp4 -c copy output.mp4

# 4. 检查磁盘空间
df -h

问题 2:编码速度慢

症状: 编码速度远低于预期。

排查步骤:

# 1. 检查 CPU 使用率
top

# 2. 使用更快的预设
ffmpeg -i input.mp4 -c:v libx264 -preset ultrafast output.mp4

# 3. 降低分辨率
ffmpeg -i input.mp4 -vf scale=640:360 -c:v libx264 output.mp4

# 4. 使用硬件加速
ffmpeg -i input.mp4 -c:v h264_nvenc output.mp4

# 5. 减少线程数(如果是 CPU 密集型)
ffmpeg -threads 2 -i input.mp4 output.mp4

问题 3:画质差

症状: 输出视频画质明显下降。

排查步骤:

# 1. 检查 CRF 值(越小质量越高)
ffmpeg -i input.mp4 -c:v libx264 -crf 18 output.mp4

# 2. 使用更好的预设
ffmpeg -i input.mp4 -c:v libx264 -preset slow -crf 18 output.mp4

# 3. 检查码率
ffprobe -show_entries stream=bit_rate output.mp4

# 4. 使用两遍编码
ffmpeg -i input.mp4 -c:v libx264 -b:v 5M -pass 1 -f null /dev/null
ffmpeg -i input.mp4 -c:v libx264 -b:v 5M -pass 2 output.mp4

问题 4:文件太大

症状: 输出文件大小超出预期。

排查步骤:

# 1. 提高 CRF 值
ffmpeg -i input.mp4 -c:v libx264 -crf 28 output.mp4

# 2. 限制码率
ffmpeg -i input.mp4 -c:v libx264 -b:v 2M -maxrate 2M -bufsize 4M output.mp4

# 3. 降低分辨率
ffmpeg -i input.mp4 -vf scale=640:360 -c:v libx264 output.mp4

# 4. 使用更高效的编解码器
ffmpeg -i input.mp4 -c:v libx265 -crf 28 output.mp4

问题 5:播放器不兼容

症状: 某些播放器无法播放输出文件。

排查步骤:

# 1. 使用兼容的编解码器
ffmpeg -i input.mp4 -c:v libx264 -profile:v baseline -level 3.0 -c:a aac output.mp4

# 2. 使用 MP4 容器
ffmpeg -i input.mkv -c copy output.mp4

# 3. 添加 faststart
ffmpeg -i input.mp4 -c copy -movflags +faststart output.mp4

# 4. 转换像素格式
ffmpeg -i input.mp4 -pix_fmt yuv420p -c:v libx264 output.mp4

高级调试

使用 strace

# 跟踪系统调用
strace -f -o trace.log ffmpeg -i input.mp4 output.mp4

# 分析日志
grep -i error trace.log

使用 GDB

# 调试 FFmpeg
gdb --args ffmpeg -i input.mp4 output.mp4

# 在 GDB 中运行
(gdb) run
(gdb) bt  # 查看堆栈

使用 Valgrind

# 检测内存泄漏
valgrind --leak-check=full --show-leak-kinds=all ffmpeg -i input.mp4 output.mp4

核心转储

# 启用核心转储
ulimit -c unlimited

# 运行 FFmpeg
ffmpeg -i input.mp4 output.mp4

# 分析核心转储
gdb ffmpeg core
(gdb) bt

常见警告处理

警告:非单调时间戳

Non-monotonous DTS in output stream

解决方法:

# 修复时间戳
ffmpeg -i input.mp4 -c copy -avoid_negative_ts make_zero output.mp4

# 使用 genpts
ffmpeg -fflags +genpts -i input.mp4 -c copy output.mp4

警告:过长的帧

Warning: Warning: not compiled with thread support

解决方法:

# 重新编译 FFmpeg 并启用线程支持
./configure --enable-pthreads
make && make install

警告:弃用的像素格式

deprecated pixel format

解决方法:

# 指定像素格式
ffmpeg -i input.mp4 -pix_fmt yuv420p -c:v libx264 output.mp4

问题诊断脚本

诊断脚本

#!/bin/bash
# diagnose.sh

FILE=$1

echo "=== FFmpeg 诊断 ==="
echo ""

echo "1. 文件信息"
ffprobe -v quiet -show_format "$FILE"
echo ""

echo "2. 流信息"
ffprobe -v quiet -show_streams "$FILE"
echo ""

echo "3. 错误检查"
ffmpeg -i "$FILE" -f null - 2>&1 | grep -i error
echo ""

echo "4. 警告检查"
ffmpeg -i "$FILE" -f null - 2>&1 | grep -i warning
echo ""

echo "5. 编码测试"
ffmpeg -v error -i "$FILE" -c:v libx264 -c:a aac -t 5 -f null - 2>&1
if [ $? -eq 0 ]; then
    echo "编码测试: 通过"
else
    echo "编码测试: 失败"
fi

批量诊断

#!/bin/bash
# batch_diagnose.sh

INPUT_DIR=${1:-.}

for file in "$INPUT_DIR"/*.mp4; do
    echo "=== 诊断: $(basename "$file") ==="
    
    # 检查文件大小
    size=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file" 2>/dev/null)
    echo "文件大小: $size 字节"
    
    # 检查时长
    duration=$(ffprobe -v quiet -show_entries format=duration -of csv=p=0 "$file")
    echo "时长: $duration 秒"
    
    # 检查视频流
    video=$(ffprobe -v quiet -select_streams v:0 -show_entries stream=codec_name -of csv=p=0 "$file")
    echo "视频编解码器: $video"
    
    # 检查音频流
    audio=$(ffprobe -v quiet -select_streams a:0 -show_entries stream=codec_name -of csv=p=0 "$file")
    echo "音频编解码器: $audio"
    
    echo ""
done

错误代码参考

FFmpeg 错误代码

代码常量说明
0AVERROR_EOF文件结束
-1AVERROR(EINVAL)无效参数
-2AVERROR(ENOMEM)内存不足
-5AVERROR(EIO)I/O 错误
-11AVERROR(EAGAIN)资源暂时不可用
-12AVERROR(ENOMEM)内存不足
-13AVERROR(EACCES)权限拒绝
-14AVERROR(EFAULT)错误地址
-17AVERROR(EEXIST)文件已存在
-19AVERROR(ENODEV)设备不存在
-20AVERROR(ENOTDIR)不是目录
-21AVERROR(EISDIR)是目录
-22AVERROR(EINVAL)无效参数
-38AVERROR(ENOSYS)函数未实现
-40AVERROR(ERANGE)结果超出范围

HTTP 错误代码

代码说明
400请求错误
401未授权
403禁止访问
404未找到
500服务器内部错误
502网关错误
503服务不可用

性能问题排查

CPU 使用率高

# 检查 CPU 使用率
top -p $(pgrep ffmpeg)

# 使用更快的预设
ffmpeg -i input.mp4 -c:v libx264 -preset ultrafast output.mp4

# 限制线程数
ffmpeg -threads 2 -i input.mp4 output.mp4

内存使用高

# 检查内存使用
ps aux | grep ffmpeg

# 分段处理
ffmpeg -i input.mp4 -ss 00:00:00 -t 01:00:00 -c copy part1.mp4

# 降低分辨率
ffmpeg -i input.mp4 -vf scale=640:360 -c:v libx264 output.mp4

I/O 瓶颈

# 检查 I/O 使用
iostat -x 1

# 使用 SSD
# 使用 tmpfs
mount -t tmpfs -o size=4G tmpfs /tmp/ffmpeg

# 减少 I/O
ffmpeg -i input.mp4 -c copy output.mp4

注意事项

  1. 日志记录:始终记录 FFmpeg 输出日志以便排查
  2. 版本检查:确保使用最新稳定版本的 FFmpeg
  3. 测试优先:在处理重要文件前先用小文件测试
  4. 备份原文件:处理前备份原始文件
  5. 资源监控:监控 CPU、内存、磁盘使用情况

扩展阅读

  1. FFmpeg FAQ
  2. FFmpeg 错误代码
  3. FFmpeg 调试指南
  4. FFmpeg 性能优化

总结

本章介绍了 FFmpeg 的常见问题和故障排除方法,包括:

  • 编解码器错误
  • 格式错误
  • 网络错误
  • 内存错误
  • 同步问题
  • 硬件加速错误

掌握这些调试技巧可以帮助您快速定位和解决问题。