1. Windows 增强版脚本 (convert.bat)
代码段
@echo off
:: 开启变量延迟扩展,确保在 for 循环中能动态更新和读取变量(如 !dur! 和 !fade_st!)
setlocal enabledelayedexpansion
:: ================= 配置区 =================
:: ORI_DIR: 存放相机原始大码率素材的路径
set "ORI_DIR=D:\downloads\ffmpeg\video-ori"
:: OUT_DIR: 处理后用于上传 VPS 且符合 YouTube 直播规范的瘦身素材路径
set "OUT_DIR=D:\downloads\ffmpeg\video-out"
:: 如果输出目录不存在,则静默创建
if not exist "%OUT_DIR%" mkdir "%OUT_DIR%"
:: ================= 执行区 =================
:: 遍历指定目录下所有的 mp4 文件
for %%f in ("%ORI_DIR%\*.mp4") do (
echo 正在处理: %%~nxf
:: 使用 ffprobe 获取视频总时长(秒),用于精确计算结尾淡出的时间点
for /f "tokens=*" %%i in ('ffprobe -v error -show_entries format^=duration -of default^=noprint_wrappers^=1:nokey^=1 "%%f"') do set "dur=%%i"
:: 调用 PowerShell 计算淡出起始点(总时长减去 2 秒),并存入变量 !fade_st!
for /f "tokens=*" %%a in ('powershell !dur! - 2') do set "fade_st=%%a"
:: 核心 FFmpeg 转码逻辑
ffmpeg -i "%%f" ^
-s 1920x1080 ^
-r 30 ^
-filter_complex "[0:v]hqdn3d,setparams=color_primaries=bt709:color_trc=bt709:colorspace=bt709,fade=t=in:st=0:d=2,fade=t=out:st=!fade_st!:d=2[v];[0:a]aresample=44100:async=1,afade=t=in:st=0:d=2,afade=t=out:st=!fade_st!:d=2[a]" ^
-map "[v]" ^
-map "[a]" ^
-c:v libx264 ^
-preset slow ^
-crf 18 ^
-pix_fmt yuv420p ^
-g 60 ^
-keyint_min 60 ^
-sc_threshold 0 ^
-vsync cfr ^
-c:a aac ^
-b:a 128k ^
-ar 44100 ^
-f mp4 ^
-y "%OUT_DIR%\%%~nxf"
)
echo 处理完成!所有素材已标准化。
pause
2. Linux 增强版脚本 (convert.sh)
Bash
#!/bin/bash
# ================= 配置区 =================
# 原始大文件目录
ORI_DIR="/opt/ffmpeg/video-ori"
# 处理后用于推流的小文件目录
OUT_DIR="/opt/ffmpeg/video-out"
# 创建输出目录(如果不存在)
mkdir -p "$OUT_DIR"
# ================= 执行区 =================
# 循环处理所有 mp4 文件
for file in "$ORI_DIR"/*.mp4; do
# 容错处理:如果目录下没有 mp4 文件则跳过
[ -e "$file" ] || continue
# 提取纯文件名(不含路径)
filename=$(basename "$file")
echo "Processing: $filename"
# 利用 ffprobe 提取视频时长,确保淡出效果在视频结束前 2 秒准确触发
duration=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$file")
# 计算淡出开始的时间点(利用 bc 进行浮点数运算)
fade_out_start=$(echo "$duration - 2" | bc)
ffmpeg -i "$file" \
-s 1920x1080 \
-r 30 \
-filter_complex \
"[0:v]hqdn3d,setparams=color_primaries=bt709:color_trc=bt709:colorspace=bt709,fade=t=in:st=0:d=2,fade=t=out:st=$fade_out_start:d=2[v]; \
[0:a]aresample=44100:async=1,afade=t=in:st=0:d=2,afade=t=out:st=$fade_out_start:d=2[a]" \
-map "[v]" \
-map "[a]" \
-c:v libx264 \
-preset slow \
-crf 18 \
-pix_fmt yuv420p \
-g 60 \
-keyint_min 60 \
-sc_threshold 0 \
-vsync cfr \
-c:a aac \
-b:a 128k \
-ar 44100 \
-f mp4 \
-y "$OUT_DIR/$filename"
done
echo "Standardization complete."
3. 核心参数注释详解 (Technical Breakdown)
| 参数 | 详细注释 |
-s 1920x1080 | 分辨率标准化。将 4K 等超大画幅降至 1080p,极大减少带宽压力和文件体积。 |
-r 30 | 帧率标准化。统一为 30fps,避免高帧率(60fps)在直播时占用过多计算资源。 |
hqdn3d | 高画质 3D 降噪。平滑画面噪点,不仅让雨景更清爽,且噪点越少,压缩效率越高。 |
setparams=... | 色彩空间重定义。强制声明为 Rec.709 (BT.709),防止在播放平台上出现对比度丢失或颜色发灰的情况。 |
fade / afade | 音视频淡入淡出。实现“黑场入-黑场出”,为循环直播提供丝滑的视觉缓冲。 |
aresample=async=1 | 异步音频重采样。通过微调采样率对齐视频时间戳,是防止直播长时间运行后音画不同步的利器。 |
-g 60 | 强制 GOP 长度。每 2 秒产生一个 I 帧,这是流媒体分片传输(DASH/HLS)的基础要求。 |
-vsync cfr | 恒定帧率模式。将变帧率(VFR)强制拉直为恒定帧率,解决直播流抖动的根本手段。 |
-pix_fmt yuv420p | 像素格式标准化。最通用的 8-bit YUV 4:2:0 格式,确保所有终端设备都能解码。 |
-f mp4 | 封装容器强制定义。明确输出为 MP4 容器格式。 |
给博主的特别建议:
在本地用这套脚本处理出的 video-out 文件,其编码属性已经达到了“直播参考级”。集成了瘦身、降噪、色彩标准化、音画同步、淡入淡出、以及严格的关键帧控制。这套配置生成的 MP4 文件上传到 VPS 后,使用 -c copy 推流将非常丝滑。