メモ:ffmpeg (mp4→mp4)ストリームをそのままコピーするシェルスクリプト

この記事は

ffmpegを使用して、映像/音声/字幕だけをコピーする作業が必要だったので色々勉強しているうちに辿り着いた解答を残すためのものです。
その時々で仕様等が変更されるでしょうから、この記事を確認された時点では少しの改良が必要かも知れません。
MEPG2-TSの場合、ffmpegコマンドでの出力が変わってくるので、cutコマンド・trコマンドをいじる必要があります。
もしかしたら、libassオプションを追加しないと動かないかも知れません・・・

前提条件

・FreeBSD 12.1-RELEASE/amd64
・ffmpeg 4.2.2 (multimedia/ffmpeg)

コードと解説

#!/bin/sh
: 一応使用方法ですが、コマンドに対してmp4ファイルへの引数が必要です。
:
:
: とりあえず、ディレクトリとファイル名(拡張子なし)、拡張子を分離。
: コピー先のファイルパスを生成するため。(ffmpegコマンドでエンコード時に指定する)
FILE_DIR=$( cd `dirname ${1}`; pwd )
FILE_TITLE=$( basename ${1%.*} )
FILE_EXT="${1##*.}"
:
:
: 映像のマッピング。
ENCODE_OPTION_VIDEO=""
for map in $( ffmpeg -i ${FILE_DIR}/${FILE_TITLE}.${FILE_EXT} 2>&1 | grep "Stream" | grep "Video" | cut -f1 -d '(' | cut -f2 -d "#" )
do
    ENCODE_OPTION_VIDEO="${ENCODE_OPTION_VIDEO} -map ${map} -c:v copy"
done
:
:
:
: 音声のマッピング。
ENCODE_OPTION_AUDIO=""
for map in $( ffmpeg -i ${FILE_DIR}/${FILE_TITLE}.${FILE_EXT} 2>&1 | grep "Stream" | grep "Audio" | cut -f1 -d '(' | cut -f2 -d "#" )
do
    ENCODE_OPTION_AUDIO="${ENCODE_OPTION_AUDIO} -map ${map} -c:a copy"
done
:
:
:
: 字幕のマッピング
:  字幕だけはcopyとはいかない謎。
ENCODE_OPTION_SUBTITLE=""
for map in $( ffmpeg -i ${FILE_DIR}/${FILE_TITLE}.${FILE_EXT} 2>&1 | grep "Stream" | grep "Subtitle" | cut -f1 -d '(' | cut -f2 -d "#" )
do
    ENCODE_OPTION_SUBTITLE="${ENCODE_OPTION_SUBTITLE} -map ${map} -c:s mov_text"
done
:
:
:
: 実際にエンコードする。
ffmpeg -y -i ${FILE_DIR}/${FILE_TITLE}.${FILE_EXT} ${ENCODE_OPTION_VIDEO} ${ENCODE_OPTION_AUDIO} ${ENCODE_OPTION_SUBTITLE} -f mp4 ${FILE_DIR}/${FILE_TITLE}.${FILE_EXT}
: コピペするのはここまで。

あとがき

何もないところからこれを完成させるだけに1年と2ヶ月はかかった。
解説の文は :コマンドにより、何もしないため特にshコマンドにおけるxオプションを使用しなければ実行時にも表示されない。

更新

2023/01/09 全体的な校正
2020/05/11 作成

コメント