我正在编写一个脚本,该脚本循环遍历媒体文件列表,然后使用 FFmpeg 重新编码它们。我的问题是我需要删除 MKV 容器不支持的任何字幕。使用负映射应该很简单,但是,每个文件的流号都会有所不同。这是我当前的命令:
ffmpeg -y -i "path/to/file.ext" -map 0 -c:v libx264 -crf 20 -level 4.1 -profile:v high -c:a copy -q:a 100 -preset faster -strict -2 -movflags faststart -threads 2 -nostdin -stats "file.mkv"
答案1
我不相信 FFmpeg 本身支持这一点。我设法编写了一个允许单次或多次发生的脚本:
stream_count=$(/usr/bin/ffprobe -select_streams s -show_entries stream=index,codec_name -of csv=p=0 "path/to/file.ext" |& grep -cE 'Subtitle: dvd_subtitle|Subtitle: hdmv_pgs' || :)
if [ "$stream_count" -gt 0 ]
then
stream_id=$(/usr/bin/ffprobe -select_streams s -show_entries stream=index,codec_name -of csv=p=0 "path/to/file.ext" |& grep -E 'Subtitle: dvd_subtitle|Subtitle: hdmv_pgs' || :)
if [ "$stream_count" = 1 ]
then
exclude_stream=$(echo "$stream_id" | grep -oP '0:[0-9]{1,3}')
exclude_stream="-map -$exclude_stream"
else
counter=0
until [ "$counter" = "$stream_count" ]
do
counter=$((counter+1))
excluded_stream="$(echo "$stream_id" |& grep -oP '0:[0-9]{1,3}' |& sed -n "${counter}"p)"
if [ ! -z "$excluded_stream" ]
then
if [ "$exclude_stream" = "*$excluded_stream*" ] #If ffprobe returns encode errors within the streams, double results may be returned for the problematic stream which this circumvents
then
counter="$stream_count"
else
exclude_stream="$exclude_stream -map -$excluded_stream"
fi
fi
excluded_stream=""
done
fi
fi
ffmpeg -y -i "path/to/file.ext" -map 0 $exclude -c:v libx264 -crf 20 -level 4.1 -profile:v high -c:a copy -q:a 100 -preset faster -strict -2 -movflags faststart -threads 2 -nostdin -stats "file.mkv" #exclude isn't wrapped as it invalidates the opening hyphen
如果有人对进一步改进此脚本有任何建议,我很乐意听取。
感谢@LordNeckbeard 对 ffprobe 命令提出的修改建议。