ffmpeg를 사용하여 비디오 파일에서 원치 않는 언어를 제거하는 방법은 무엇입니까?

ffmpeg를 사용하여 비디오 파일에서 원치 않는 언어를 제거하는 방법은 무엇입니까?

필요하지 않은 언어로 된 대용량 오디오 및 자막 스트림이 포함된 비디오 파일(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:불필요한 언어 삭제.sh):

#!/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

관련 정보