ビデオファイルを識別し、いくつかの規則に基づいてFFmpegを使用してトランスコードする汎用シェルスクリプトを作成する方法は?

ビデオファイルを識別し、いくつかの規則に基づいてFFmpegを使用してトランスコードする汎用シェルスクリプトを作成する方法は?

ffmpegビデオファイルのサブフォルダを含むフォルダを読み、HEVCでエンコードされていないファイルを選択して渡し、入力ファイルと出力ファイルを比較する単純な(いくつかのコマンドのみ実行)スクリプトを取得しようとしています。出力サイズが大きい場合は次のファイルに移動し、サイズが小さい場合は元のファイルを置き換えます。

私のロジックはこれです。

  1. 純粋なtxtリストを準備します。

    find /folder -type f \( -iname "*.mkv" -o -iname "*.mp4" -o -iname "*.avi" \) > log.txt
    
  2. txtを次に渡します。ffprobe

    ffprobe "log.txt" -v error -select_streams v:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1
    

ここffprobeでは、行1、2、3などをから受け取る必要がありますが、単一の入力のみが許可されるため、log.txtこれを行う方法がわかりません。ffprobe

  1. ffprobeリストを実行し、HEVC以外の結果を出力する必要があります。log1.txt

  2. トランスコーディングのためにシステムフォルダを転送するlog1.txt必要がある場所。作業コマンドがありますが、ここの構文は単一のファイルに問題ではありません。ffmpeg/tmpffmpeg

  3. 入力と出力を比較します。入力が出力より大きい場合は交換します。出力が入力より大きい場合、それを破棄して次に進みます。

私が経験している問題は、主に変数の伝達(2.を参照)と明示的な伝達(5.)に関連しています。解決策ではなく、上記の問題を処理する方法に関するいくつかのガイドラインが必要です。

読んでくれてありがとう。

答え1

ファイルリストを生成するために find を使用しないでください。find出力を解析するのは危険なので避けてください。- 特にスペースを含むファイル名の場合。ほとんどのタスクを実行するスクリプトを準備し、findのexec引数を介して実行することをお勧めします(保護されたセミコロンが必要で、bashがfindの代わりにワイルドカードを拡張するのを防ぐために単一引用符も使用します)。

find /folder -type f \( -iname '*.mkv' -o -iname '*.mp4' -o -iname '*.avi' \) -exec transcode.sh {} \;

ファイルから直接ffprobeを呼び出し、出力をgrepにパイプしてコーデック名を確認できます(必要なコーデックの実際の名前がわからないため、調整してください)。

if ffprobe "$1" -hide_banner -loglevel panic -select_streams v:0 -show_entries stream=codec_name | grep -q 'hvec'
then
  # TODO: do transcoding
fi

トランスコーディング後、次のことができます。ファイルサイズの比較それに応じて行動します(次にスクリプトを実行するときにファイルを再トランスコードするのに時間と労力を無駄にしないように、意図的にファイルスタブを残しました)。

if [[ $(stat -c%s "$f") -gt $(stat -c%s "$fhvec") ]]
then
  mv "$fhvec" "$f"
else
  truncate -s 0 "$fhvec"
fi

より一般的な警告:重要でないデータ(プレビュー、サムネイル、プロキシ)に対してのみこれを実行してください。 HVECは強力なエンコーダですが、2つの異なるエンコーダの圧縮アーティファクトを含むビデオが表示されることがあります。彼らは小さいかもしれませんが、見た目も悪く見えます。

関連情報