脚本说明与注意事项
- 运行环境 :此脚本需要在能访问到视频文件的服务器(如转码服务器)上运行。
- 对象存储挂载 :
- 如果您的对象存储(MinIO/Ceph)已经挂载为本地目录(例如通过 S3FS 挂载到了
/mnt/video_source),直接配置路径即可。 - 如果是纯API对接,需要配合
mc(MinIO Client) 先下载后上传。本脚本默认采用"本地目录/挂载盘"模式,这是最通用的方式。
- 如果您的对象存储(MinIO/Ceph)已经挂载为本地目录(例如通过 S3FS 挂载到了
- 关键优化 :
- 我主动帮您加上了
-movflags +faststart参数 。虽然您提供的命令里没写,但作为点播系统,必须加这个参数,否则浏览器无法"边下边播"。 - 增加了幂等性检查:如果目标文件已存在且大小正常,会自动跳过,防止重复跑。
- 我主动帮您加上了
脚本内容 (batch_transcode.sh)
您可以直接复制以下内容保存为 batch_transcode.sh。
bash
#!/bin/bash
# ================= 配置区域 =================
# 源视频目录 (对象存储挂载目录或原始文件目录)
SOURCE_DIR="/data/videos/raw"
# 输出视频目录 (转码后的存放目录,建议与源分开,确认无误后再替换)
OUTPUT_DIR="/data/videos/optimized"
# 日志文件路径
LOG_FILE="./transcode_task.log"
# 设置并发数量 (H.265非常消耗CPU,建议设置为 CPU核心数 / 2)
# 如果服务器要同时响应其他请求,请设为 1 保持单线程处理
MAX_JOBS=1
# ===========================================
# 检查 FFmpeg 是否安装
if ! command -v ffmpeg &> /dev/null; then
echo "错误: 未找到 ffmpeg,请先安装。"
exit 1
fi
# 创建输出目录
mkdir -p "$OUTPUT_DIR"
echo "=== 开始批量压缩任务 ===" | tee -a "$LOG_FILE"
echo "源目录: $SOURCE_DIR" | tee -a "$LOG_FILE"
echo "输出目录: $OUTPUT_DIR" | tee -a "$LOG_FILE"
echo "开始时间: $(date)" | tee -a "$LOG_FILE"
# 统计计数器
count_success=0
count_skip=0
count_fail=0
# 递归查找所有 .mp4 文件
# 注意:处理文件名中的空格
find "$SOURCE_DIR" -type f -name "*.mp4" | while read -r input_file; do
# 1. 构建输出文件路径
# 获取相对路径,保持原有的目录结构
relative_path="${input_file#$SOURCE_DIR/}"
output_file="$OUTPUT_DIR/$relative_path"
output_dir_path=$(dirname "$output_file")
# 自动创建子目录
mkdir -p "$output_dir_path"
# 2. 检查是否已处理(防止重复跑)
if [ -f "$output_file" ]; then
# 如果目标文件存在,且大小大于 1KB (防止之前的空文件),则跳过
if [ $(stat -c%s "$output_file") -gt 1024 ]; then
echo "[跳过] 文件已存在: $relative_path" | tee -a "$LOG_FILE"
continue
fi
fi
echo "------------------------------------------------" | tee -a "$LOG_FILE"
echo "[正在处理] $input_file ..." | tee -a "$LOG_FILE"
# 3. 执行 FFmpeg 命令
# -y: 覆盖输出文件
# -nostdin: 防止ffmpeg吞掉while循环的标准输入
# -movflags +faststart: 必须加!确保Web端能秒开播放
ffmpeg -y -nostdin -i "$input_file" \
-c:v libx265 \
-preset medium \
-crf 28 \
-r 15 \
-tag:v hvc1 \
-c:a aac -b:a 64k \
-movflags +faststart \
"$output_file" < /dev/null >> "$LOG_FILE" 2>&1
# 4. 检查转码结果
if [ $? -eq 0 ]; then
# 获取压缩率
orig_size=$(du -h "$input_file" | cut -f1)
new_size=$(du -h "$output_file" | cut -f1)
echo "[成功] $relative_path (原: $orig_size -> 新: $new_size)" | tee -a "$LOG_FILE"
# 可以在这里添加删除源文件的命令,但建议人工确认后再删
# rm "$input_file"
else
echo "[失败] $relative_path - 请查看日志详情" | tee -a "$LOG_FILE"
# 如果生成了错误的空文件,删除它
rm -f "$output_file"
fi
done
echo "================================================" | tee -a "$LOG_FILE"
echo "任务结束时间: $(date)" | tee -a "$LOG_FILE"
echo "日志已保存至: $LOG_FILE"
如何使用
-
保存脚本 :将上述代码保存为
transcode.sh。 -
赋予权限 :
bashchmod +x transcode.sh -
修改路径 :
使用vim transcode.sh修改前几行的配置:SOURCE_DIR: 指向您存放原始大文件的目录。OUTPUT_DIR: 指定您希望存放处理后文件的目录。
-
后台运行 (推荐):
由于视频压缩非常耗时(H.265可能只有 2-5倍 实时速度),建议使用nohup挂在后台运行,防止SSH断开导致任务中断。bashnohup ./transcode.sh > /dev/null 2>&1 & -
查看进度 :
bashtail -f transcode_task.log
特别提醒:关于 H.265 的浏览器兼容性
您既然决定使用 H.265 (HEVC),请务必告知前端开发人员注意以下事项:
- 浏览器支持现状 :
- Safari (iOS/Mac):完美支持(原生硬件解码)。
- Chrome / Edge:104+ 版本才开始较好支持,且通常依赖硬件加速。
- Firefox:支持较差。
- 解决方案 :
您之前提到的 XGPlayer (西瓜播放器) 支持集成 H.265 软解插件。
务必让前端引入xgplayer-h265插件 ,否则部分旧电脑的 Chrome 浏览器可能会出现 "只有声音没画面" 的情况。
如果为了绝对的兼容性而不使用插件,请改回 H.264,但如果能控制前端播放器环境,H.265 是节省带宽的最佳选择。