不要な言語の大容量オーディオと字幕ストリームを含むビデオファイル(500以上)がたくさんありますが、保存スペースを節約するために削除したいと思います。
ファイルの処理後にストリームを変更しましたが、ffmpeg
結果は次のようになります。非常に時間がかかります。ビデオファイルには異なる順序の異なるストリームが含まれているため、インデックスを介した削除が困難でエラーが発生しやすく、スクリプトには運がありません。
より高速で多様なストリームを含むファイルに対して機能するソリューションが必要です。そうですか?どんな助けでも大変感謝します。
答え1
次のffmpeg
コマンドラインを使用できます。
ffmpeg -i video.mkv -map 0:v -map 0:m:language:eng -codec copy video_2.mkv
説明する:
-i video.mkv input file (identified as '0:' in mappings below)
-map 0:v map video streams from input to output file
-map 0:m:language:eng map streams for language 'eng' from input to output file
(may be specified multiple times for multiple languages)
-codec copy copy streams without reencoding
video_2.mkv output file
結果ファイルには英語のストリームのみが保持されます(コピーされたビデオストリームを除く)。
実際、私はしばらく前にスクリプトを作成しました(GitHub Gist:不要な言語を削除する):
#!/usr/bin/env bash
# -------------------------------------------------------------------------
# -
# Remove unneeded language(s) from video file -
# -
# Created by Fonic <https://github.com/fonic> -
# Date: 04/14/22 - 08/26/22 -
# -
# Based on: -
# https://www.reddit.com/r/ffmpeg/comments/r3dccd/how_to_use_ffmpeg_to_ -
# detect_and_delete_all_non/ -
# -
# -------------------------------------------------------------------------
# Print normal/hilite/good/warn/error message [$*: message]
function printn() { echo -e "$*"; }
function printh() { echo -e "\e[1m$*\e[0m"; }
function printg() { echo -e "\e[1;32m$*\e[0m"; }
function printw() { echo -e "\e[1;33m$*\e[0m" >&2; }
function printe() { echo -e "\e[1;31m$*\e[0m" >&2; }
# Set up error handling
set -ue; trap "printe \"Error: an unhandled error occurred on line \${LINENO}, aborting.\"; exit 1" ERR
# Process command line
if (( $# != 3 )); then
printn "\e[1mUsage:\e[0m ${0##*/} LANGUAGES INFILE OUTFILE"
printn "\e[1mExample:\e[0m ${0##*/} eng,spa video.mkv video_2.mkv"
printn "\e[1mExample:\e[0m for file in *.mkv; do ${0##*/} eng,spa \"\${file}\" \"out/\${file}\"; done"
printn "\e[1mNote:\e[0m LANGUAGES specifies language(s) to KEEP (comma-separated list)"
exit 2
fi
IFS="," read -a langs -r <<< "$1"
infile="$2"
outfile="$3"
# Sanity checks
[[ -f "${infile}" ]] || { printe "Error: input file '${infile}' does not exist, aborting."; exit 1; }
command -v "ffmpeg" >/dev/null || { printe "Error: required command 'ffmpeg' is not available, aborting."; exit 1; }
# Run ffmpeg
printh "Processing file '${infile}'..."
lang_maps=(); for lang in "${langs[@]}"; do lang_maps+=("-map" "0:m:language:${lang}"); done
ffmpeg -i "${infile}" -map 0:v "${lang_maps[@]}" -codec copy -loglevel warning "${outfile}" || exit $?
exit 0
次のように使用します(例:すべての.mkv
ファイルを処理し、英語とスペイン語のストリームのみを保持)。
mkdir out; for file in *.mkv; do remove-unneeded-languages.sh eng,spa "${file}" "out/${file}"; done