如何正确修改bash脚本使用for循环实现ffmpeg批量视频转码
批量ffmpeg视频转码脚本修复方案
核心故障点
- 语法错误:外层
for f in *.mp4循环体内存在孤立的do关键字,同时嵌套了多余的for i in *.mp4循环,会导致同批次文件被重复处理,逻辑完全混乱 - 元数据读取错误:处理单个文件时不需要给filebot加
-r递归参数,且年份提取字段{media.Recorded_Date}不适用于电影元数据,绝大多数场景下会返回空值 - 变量未定义:字幕拷贝逻辑使用的
LBSDFPATH、LRSDFPATH等变量未提前声明,实际定义的字幕路径变量为LBSFPATH、LRSFPATH,导致字幕拷贝完全不生效 - 路径遍历范围错误:原脚本仅能遍历当前工作目录下的mp4文件,无法匹配基目录下所有子目录的电影文件
- 变量定义冗余:全局根路径参数
LROOTPATH、CROOTPATH放在循环体内,每次循环重复赋值,无意义消耗性能 - 转码日志冲突:双路转码的pass日志文件没有按文件区分,多文件同时处理时日志会互相覆盖,导致转码失败
修正后可运行脚本
#!/bin/bash ## 全局路径配置 移到循环外仅赋值1次 LROOTPATH="/mnt/e/tmp" CROOTPATH="/mnt/g/Shared drives/flix" ## 开启globstar支持 遍历所有子目录的mp4文件 shopt -s globstar nullglob for f in **/*.mp4; do ## 获取元数据 去掉多余的-r递归参数,修正年份提取字段 TITLE="$(filebot -mediainfo "$f" --format "{media.Title}")" YEAR="$(filebot -mediainfo "$f" --format "{y}")" BMDIR="$(filebot -mediainfo "$f" --format "{folder.name}")" BMFILE="${TITLE}" ## 交互输入海报文件名 echo "Enter file name for ${TITLE} (${YEAR}) movie poster from themoviedb.org:" && read CFILE BCFILE="${CFILE}" BSFILE="${TITLE}.eng.srt" RMDIR="${TITLE} (${YEAR})" RMFILE="${TITLE} (${YEAR})" RCFILE="cover" RTFILE="thumb" RSFILE="${RMFILE}.eng.default" ## 路径拼接 LBPATH="${LROOTPATH}/backup/movies/downloaded/${BMDIR}" LBFPATH="${LBPATH}" LBMFPATH="${LBFPATH}/${BMFILE}.mp4" LBSFPATH="${LBFPATH}/${BSFILE}.srt" LRPATH="${LROOTPATH}/remux/movies/$(filebot -mediainfo "${LBMFPATH}" --format "{HD.lower()}")" LRFPATH="${LRPATH}/${RMDIR}" LRMFPATH="${LRFPATH}/${RMFILE}.mp4" LRCFPATH="${LRFPATH}/${RCFILE}.jpg" LRTFPATH="${LRFPATH}/${RTFILE}.jpg" LRSFPATH="${LRFPATH}/${RSFILE}.srt" CBPATH="${CROOTPATH}/backup/movies" CBFPATH="${CBPATH}" CBMFPATH="${CBFPATH}/${BMFILE}.mp4" TMDB="https://www.themoviedb.org/t/p/original/${CFILE}.jpg" ## 创建输出目录 mkdir -v "${LRFPATH}" ## 下载海报 wget -O "${LRCFPATH}" "https://www.themoviedb.org/t/p/original/${BCFILE}.jpg" ## 拷贝字幕 修正未定义的变量 if [ -f "${LBSFPATH}" ]; then cp -v "${LBSFPATH}" "${LRSFPATH}" fi ## 提取缩略图 去掉多余的for循环,直接用当前遍历的$f ffmpeg -y -hide_banner \ -ss 00:10:00 \ -i "$f" \ -vframes 1 \ -q:v 3 \ -an \ -metadata:s:t:0 mimetype=image/jpeg \ -metadata:s:t:0 title="thumb" \ -threads 16 \ "${LRTFPATH}" ## 双路x265转码 去掉多余的for循环,日志文件按当前文件命名避免冲突 ffmpeg -y -hide_banner \ -i "$f" \ -pix_fmt yuv420p \ -c:v libx265 \ -pass 1 \ -an \ -x265-params crf=28 \ -passlogfile "${LBFPATH}/ffmpeg2pass-${f//\//_}" \ -f null \ -threads 16 \ /dev/null && \ ffmpeg -y -hide_banner \ -i "$f" \ -pix_fmt yuv420p \ -c:v libx265 \ -map 0:v:0 \ -map 0:a:0 \ -c:a copy \ -x265-params crf=28 \ -pass 2 \ -passlogfile "${LBFPATH}/ffmpeg2pass-${f//\//_}" \ -threads 16 \ "${LRMFPATH}" ## 清理原文件 rm -Rv "${LBFPATH}" #mv -v "${LBFPATH}" "${CBFPATH}" done
内容的提问来源于stack exchange,提问作者Schmitty
相关产品推荐
相关产品推荐

