批量降级视频码率的脚本

wen 实用脚本 3

从入门到精通的完整指南(附Python与FFmpeg实战代码)

目录导读

  1. 为什么需要批量降级视频码率? —— 存储成本、流媒体适配与合规需求
  2. 核心工具选型 —— FFmpeg、Python多进程、硬件加速对比
  3. 脚本设计架构 —— 递归扫描、动态码率计算、容错与日志
  4. 五大实战脚本模板 —— 覆盖单视频、批量文件夹、HDR转SDR、音轨处理
  5. 性能优化技巧 —— 多线程/进程、GPU转码、避免CPU瓶颈
  6. 常见问题与排查 —— 黑屏、音画不同步、文件损坏的解决方案
  7. 问答专区 —— 高频疑惑一网打尽

为什么需要批量降级视频码率?

日常工作中,你可能会遇到这些场景:

批量降级视频码率的脚本

  • 存储空间告急:一个4K电影动辄50GB,批量压缩到1080p可节省70%空间
  • 平台上传限制:微信、邮件附件限制200MB,短视频平台要求码率≤5Mbps
  • 多设备兼容:老平板/电视盒子不支持高码率HEVC,需转为低码率H.264

手动用格式工厂逐条处理?100个视频要耗费一下午。脚本化批量降级不仅能释放人力,还能通过统一参数确保输出质量稳定。


核心工具选型:为什么FFmpeg是首选?

工具 优点 缺点
FFmpeg 命令行万能、支持所有格式、自带硬件加速 语法复杂需学习
HandBrakeCLI 参数友好、内置预设 定制性稍弱
Python+OpenCV 便于集成算法 转码速度慢,仅适合图像序列

最佳实践:用Python调用FFmpeg子进程,既保留强大的转码能力,又能实现批量逻辑与错误恢复。

官方文档提示:FFmpeg 5.0+ 支持 -b:v (总码率) 与 -maxrate (峰值码率) 分离控制,避免画质波动。


脚本设计架构(3层核心)

graph LR
A[扫描目录] --> B[解析文件信息]
B --> C[动态计算码率]
C --> D[执行转码]
D --> E{成功?}
E -->|是| F[原文件移到备份库]
E -->|否| G[记录错误日志]
G --> H[邮件/钉钉通知]
关键设计点:
  1. 递归扫描os.walk 匹配 .mp4/.mov/.mkv,用 fnmatch 过滤
  2. 动态码率规则:根据分辨率自动设定——
    • 4K → 8000kbps
    • 1080p → 4000kbps
    • 720p → 2000kbps
  3. 保留元数据-map_metadata 0 确保时间戳、旋转信息不丢失

五大实战脚本模板(可直接复制)

模板1:单视频降级(含画质校验)
ffmpeg -i input.mp4 -c:v libx265 -b:v 3000k -c:a aac -b:a 128k \
-twopass 1 -passlogfile /tmp/fflog -vf scale=-2:1080 output.mp4

两遍编码可提升10%压缩率,但耗时翻倍。

模板2:批量文件夹遍历(Python核心)
import subprocess, os, logging
from pathlib import Path
SRC_DIR = "/data/videos"
DST_DIR = "/data/compressed"
def compress_video(in_path: Path, out_path: Path):
    cmd = [
        "ffmpeg", "-y",
        "-i", str(in_path),
        "-c:v", "libx264", "-crf", "26",
        "-preset", "fast",
        "-maxrate", "2500k", "-bufsize", "5000k",
        "-c:a", "aac", "-b:a", "96k",
        "-movflags", "+faststart",
        str(out_path)
    ]
    return subprocess.run(cmd, capture_output=True)
for root, dirs, files in os.walk(SRC_DIR):
    for f in files:
        if f.endswith(('.mp4', '.mkv')):
            src = Path(root) / f
            rel = src.relative_to(SRC_DIR)
            dst = DST_DIR / rel
            dst.parent.mkdir(parents=True, exist_ok=True)
            if compress_video(src, dst).returncode == 0:
                logging.info(f"成功: {f}")
            else:
                logging.error(f"失败: {f}")
模板3:硬件加速(NVIDIA GPU)
ffmpeg -hwaccel cuda -hwaccel_device 0 -i input.mp4 \
-c:v h264_nvenc -b:v 2500k -c:a copy output.mp4

比CPU快3-5倍,但画质略降(适合超大批量)。

模板4:Web端自适应(HLS流差异化)
# 生成多码率版本
for bitrate in ['2000k', '1200k', '600k']:
    subprocess.run(... -b:v {bitrate} -s 1280x720 {bitrate}.ts)
模板5:附带音频降噪(可选)
ffmpeg -i in.mp4 -af "highpass=f=200,lowpass=f=3000" \
-c:v libx264 -b:v 2000k -c:a libopus -b:a 64k out.mkv

性能优化五大技巧

  1. 多进程并行Python multiprocessing.Pool(4) 控制同时转码数量,避免内存爆仓
  2. 超低延迟预设-tune zerolatency 减少缓冲,适合直播流
  3. 分片处理-ss 截取片头片尾,分段并行转码再拼接(需要精确切割点)
  4. IO瓶颈规避:SSD临时盘 + -threads 8 调高编码线程
  5. 安全中断恢复:用 -progress pipe:1 实时输出百分比,中断后跳过已处理文件

常见问题与排查

错误现象 原因定位 解决方案
输出黑屏但有声音 视频流编码损坏 -vsync vfr 并重试
音画不同步 时间戳偏移 -fflags +genpts 重新生成
编码中途退出 源文件损坏 先用 ffmpeg -v error -i file -f null /dev/null 验证
文件大小不降反增 用了无损参数 检查 -crf 值是否>28,或-b:v单位是否错误

问答专区(高频疑惑)

Q1:如何保证批量转换后字幕不被烧录?

-c:s mov_text 保持原字幕轨,而非 -vf subtitles 硬编码。

Q2:脚本运行到一半中断,如何断点续传?

在Python中维护completed.txt,每次成功后写入文件名,启动时读取跳过。

Q3:为什么CRF 23输出的文件比原始文件还大?

源文件可能本身是低码率(如录屏),此时改用 -b:v 800k 强制降码率。

Q4:在Mac M1上如何启用硬件加速?

安装video_toolbox + FFmpeg 6.0,命令添加-c:v h264_videotoolbox

Q5:批量处理会改变视频的播放方向吗?

若源文件带旋转元数据,必须加-display_rotation并配合 -metadata:s:v rotate=0


通过脚本批量降级视频码率,不仅解放重复劳动力,更是实现自动化媒体管道的基础,建议先用5-10个样本验证参数,再大规模跑批,若涉及商业保密视频,请务必加密传输并对SD卡做清理。

立即行动

复制模板2,修改SRC_DIR路径,运行:

pip install click tqdm   # 可选依赖
python batch_compress.py

延伸思考:如果视频码率降到极低出现色块,试一下-crf 28 + -preset slow;如果是风景场面临时起雾,添加-vf unsharp=5:5:1.0增强锐度,有任何参数调整疑问,欢迎在评论区留言交流!

抱歉,评论功能暂时关闭!