第三十讲:综合实战——搭建一个完整的音视频处理流水线

终于到了最后一讲。说实话,写到这里我自己也有点感慨。前面二十九讲,我们从最基础的FFmpeg命令,一路聊到滤镜、编码器、封装格式、硬件加速……今天,我们要把这些零散的知识点串起来,搭一条真正的自动化流水线。

什么叫“流水线”?说白了,就是输入一个原始素材,经过一系列处理步骤,最终输出你想要的结果。整个过程不需要人工干预,全自动跑完。我在项目中遇到过很多次这样的需求:每天凌晨自动转码一批视频、自动提取音频并做降噪、自动生成缩略图……嗯,今天我们就来手写一个这样的脚本。

流水线的整体设计

先画一张图,让你对整个流程有个直观印象。我个人习惯在动手写代码之前,先把流程图画清楚,这样后面不容易乱。

音视频处理流水线架构图 原始输入文件 步骤1:探测文件信息(ffprobe) 步骤2:分离音视频流 步骤3:分别处理(转码/降噪/缩放) 最终输出文件

这张图看起来简单,但每个步骤背后都有不少细节。下面我们一步步展开。

第一步:探测文件信息

拿到一个视频文件,你首先得知道它是什么格式、分辨率多少、编码器是什么、有没有音频流。这些信息,FFmpeg 自带的 ffprobe 工具可以轻松搞定。

我习惯用 JSON 格式输出,方便脚本解析。命令长这样:

ffprobe -v quiet -print_format json -show_format -show_streams input.mp4

返回的 JSON 里,streams 数组包含了所有音视频流的信息。比如 codec_type 字段告诉你这是视频流还是音频流,codec_name 告诉你编码器名字,widthheight 是视频分辨率。

小技巧: 如果你只想快速看一眼关键信息,可以用 ffprobe -v error -show_entries stream=index,codec_type,codec_name -of default=noprint_wrappers=1 input.mp4。输出更简洁,适合人眼阅读。

第二步:分离音视频流

知道了文件结构,接下来就是分离。为什么要分离?因为很多时候,音频和视频的处理参数不一样。比如视频要缩放到 1080p,音频要降噪,这两个操作放在一条命令里也能做,但分开处理更灵活,也更容易排查问题。

分离视频流(不带音频):

ffmpeg -i input.mp4 -an -c:v copy video_only.mp4

分离音频流(不带视频):

ffmpeg -i input.mp4 -vn -c:a copy audio_only.aac

这里用了 -c:v copy-c:a copy,意思是直接复制流,不重新编码。速度快,而且无损。如果你需要重新编码,可以去掉 copy,指定编码器。

注意: 如果输入文件是 MP4 格式,音频流可能是 AAC 编码,直接复制出来后缀名用 .aac 没问题。但如果音频是其他格式(比如 MP3),后缀名要对应改。我曾经遇到过有人把 AAC 文件改成 .mp3 后缀,结果播放器不认,折腾了半天才发现是后缀名搞错了。

第三步:分别处理

分离之后,就可以对视频和音频各自做处理了。这里我给出一个常见的组合:视频缩放 + 音频降噪。

视频缩放:

ffmpeg -i video_only.mp4 -vf "scale=1920:1080" -c:v libx264 -preset medium -crf 23 video_processed.mp4

音频降噪(使用 anlmdn 滤镜):

ffmpeg -i audio_only.aac -af "anlmdn" audio_processed.aac

你可能会问:为什么不一步到位?我的经验是,分开处理更容易调试。如果最终结果有问题,你可以分别检查视频和音频的处理结果,快速定位是哪个环节出了岔子。

第四步:合并输出

处理完的视频和音频,最后要合并成一个文件。这一步用 FFmpeg 的 concat 或者直接重新封装都可以。

ffmpeg -i video_processed.mp4 -i audio_processed.aac -c:v copy -c:a copy -map 0:v:0 -map 1:a:0 final_output.mp4

这里 -map 0:v:0 表示取第一个输入文件的第一个视频流,-map 1:a:0 表示取第二个输入文件的第一个音频流。用 -c:v copy -c:a copy 直接复制,不重新编码,速度飞快。

自动化脚本:把一切串起来

上面这些步骤,手动执行没问题,但我们要的是自动化。下面我写一个完整的 Bash 脚本,把整个流程串起来。你可以在 Linux 或 macOS 上直接运行,Windows 的话用 WSL 或者 Git Bash 也行。

#!/bin/bash

# 音视频处理流水线自动化脚本
# 用法: ./pipeline.sh input.mp4 output.mp4

INPUT=$1
OUTPUT=$2

if [ -z "$INPUT" ] || [ -z "$OUTPUT" ]; then
    echo "用法: $0 <输入文件> <输出文件>"
    exit 1
fi

# 检查输入文件是否存在
if [ ! -f "$INPUT" ]; then
    echo "错误: 输入文件 $INPUT 不存在"
    exit 1
fi

echo "=== 步骤1: 探测文件信息 ==="
ffprobe -v quiet -print_format json -show_format -show_streams "$INPUT" > probe.json

# 检查是否有音频流
AUDIO_STREAM=$(ffprobe -v error -select_streams a -show_entries stream=index -of csv=p=0 "$INPUT")
if [ -z "$AUDIO_STREAM" ]; then
    echo "警告: 输入文件没有音频流,将只处理视频"
    HAS_AUDIO=false
else
    HAS_AUDIO=true
fi

echo "=== 步骤2: 分离音视频流 ==="
ffmpeg -i "$INPUT" -an -c:v copy video_only.mp4 -y
if [ "$HAS_AUDIO" = true ]; then
    ffmpeg -i "$INPUT" -vn -c:a copy audio_only.aac -y
fi

echo "=== 步骤3: 处理视频流(缩放至1080p) ==="
ffmpeg -i video_only.mp4 -vf "scale=1920:1080" -c:v libx264 -preset medium -crf 23 video_processed.mp4 -y

if [ "$HAS_AUDIO" = true ]; then
    echo "=== 步骤3: 处理音频流(降噪) ==="
    ffmpeg -i audio_only.aac -af "anlmdn" audio_processed.aac -y
fi

echo "=== 步骤4: 合并输出 ==="
if [ "$HAS_AUDIO" = true ]; then
    ffmpeg -i video_processed.mp4 -i audio_processed.aac -c:v copy -c:a copy -map 0:v:0 -map 1:a:0 "$OUTPUT" -y
else
    cp video_processed.mp4 "$OUTPUT"
fi

echo "=== 清理临时文件 ==="
rm -f video_only.mp4 audio_only.aac video_processed.mp4 audio_processed.aac probe.json

echo "=== 完成! 输出文件: $OUTPUT ==="
核心要点:
  • 脚本自动检测输入文件是否有音频流,没有的话就只处理视频
  • 每一步都加了日志输出,方便跟踪进度
  • 处理完成后自动清理临时文件,不留下垃圾
  • 所有中间步骤都用了 -y 参数,避免交互式确认

避坑指南

写这种自动化脚本,有几个坑我踩过,分享给你:

  • 路径中有空格: 输入输出文件名最好用引号包起来,否则脚本会报错。我在脚本里用了 "$INPUT""$OUTPUT",就是为了防这个。
  • 磁盘空间不足: 中间文件会占用额外空间。如果原始文件很大(比如 4K 视频),临时文件可能会撑爆磁盘。建议在处理前用 df -h 检查一下剩余空间。
  • 编码器不可用: 脚本里用了 libx264,如果你的 FFmpeg 没有编译这个编码器,会报错。可以用 ffmpeg -encoders | grep x264 检查一下。
  • 音频格式不匹配: 如果原始音频是 AC3 或 DTS,直接复制成 .aac 后缀可能有问题。更稳妥的做法是用 ffprobe 获取实际的编码器名称,然后动态决定后缀名。

扩展思路

这个流水线只是一个基础模板。实际项目中,你可以根据需求随意扩展:

  • 加入硬件加速(比如 -c:v h264_nvenc)提升转码速度
  • 加入字幕流提取和嵌入
  • 加入封面图生成(用 thumbnail 滤镜)
  • 加入多分辨率输出(同时生成 1080p、720p、480p 三个版本)
  • 加入日志记录和错误重试机制

我个人建议,每加一个新功能,先单独测试通过,再集成到流水线里。这样出了问题,你能很快知道是哪个环节的锅。

好了,整个课程到这里就结束了。三十讲,从命令行参数到滤镜语法,从封装格式到硬件加速,从单条命令到完整流水线——你想想看,这些东西串起来,是不是已经能解决工作中大部分音视频处理问题了?

希望这套课程对你有用。以后遇到音视频相关的需求,别忘了打开 FFmpeg,敲几行命令试试。嗯,动手实践永远是最好的学习方式。


公众号:蓝海资料掘金营,微信deep3321