ffprobe
ビデオフォルダを読み取り、処理するビデオファイルのリストを作成して、コーデックを識別するスクリプトを作成しようとしています。特定のコーデック(この場合はHEVC)で処理されていない動画は、さらなる処理のために新しいリストに追加する必要がありますffmpeg
。
ffprobe_input
非常に基本的なスクリプトを作成しましたが、次の入力に渡される変数を変更する必要があるという問題に固執しましたffprobe
。
また、スクリプトのこの部分が正しく機能していても、処理後にフィルタリングされたファイルのリストを生成する方法も混乱しています。ffprobe
唯一の出力はhevc
次のような単語だからですx264
。
以下には、もう少し説明が豊富な私のメモと、私が仕事をしようとしたいくつかの方法で実際のスクリプトがあります。
これはスクリプトの目的の目的です。./script.sh -p /path\ to\ videos
#!/bin/bash
#Read path (-p) input and exit on error.
while getopts p: flag
do
case "${flag}" in
p) vpath=${OPTARG};;
*) echo "usage: $0 [-p]" >&2
exit 1 ;;
esac
done
#Now we echo the path for neatness
echo -e "Selected root video path: $vpath";
#Check if the path is valid. The path must be escaped. Cd into the folder and execute: printf "%q\n" "$(pwd)"
[ -d "$vpath" ] && echo "Directory $vpath exists." || echo "Error: Directory $vpath does not exist. Tip: make sure the spaces are escaped in folder names, ex: ===video\ folder===."
#Prepare a list of video files with full escaped paths,ready for ffprobe/ffmpeg input.
find "$vpath" -type f \( -iname "*.mkv" -o -iname "*.mp4" -o -iname "*.avi" \) | sed 's/ /\\ /g' >> full_list.txt
#read the total number of lines from full_list.txt
nrl_total="$(wc -l full_list.txt | grep -Eo "[0-9]{0,7}")"
echo -e "There are a total of $nrl_total videos for further processing."
#read line number and pass to $ffprobe_input
# nrl=($(seq 1 "$nrl_total"))
# nrl={1..$nrl_total..1}
# for $nlr in {1..$nrl_total..1}; do
# nrl=({1..$nrl_total..1})
filename='full_list.txt'
nrl=1
while read line; do
echo "$nrl"
nrl=$((n+1))
#done < $filename
#ffprobe_input="$(sed -n 1p full_list.txt)" Use line number in "p" attribute, ex: 1p.
# ffprobe_input="$(sed -n 1p full_list.txt)"
ffprobe_input="$(sed -n "$nrl"p full_list.txt)"
#Now pass the input to ffprobe to determine if the videos are HEVC or not. Output is single word, ex: hevc or x264.
eval ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 -i "$ffprobe_input"
done < $filename
rm full_list.txt
答え1
ファイル名に改行文字が含まれていないと仮定すると、何らかの方法でファイル名を破損する必要はありません。出力はfilenameごとに1行なfile
ので、保存して結果ファイルを繰り返すだけです。
> non-hevc.txt # clear the output list
find "$vpath" -type f \( -iname "*.mkv" -o -iname "*.mp4" -o -iname "*.avi" \) \
> full_list.txt
while IFS= read -r file; do
result=$(ffprobe -v error -select_streams v:0 -show_entries \
stream=codec_name -of default=noprint_wrappers=1:nokey=1 -i "$file")
if [ "$result" != hevc ]; then
echo "$file" >> non-hevc.txt
fi
done < full_list.txt
rm -f full_list.txt
ffprobe
ここでキャプチャされた出力は、コマンドを使用して置き換えられ、保存されて$(...)
からresult
それを表示します。
同じ行がすでに読み込まれているので、sed -n "$nrl"p
ループ内でファイル名のリストを読む理由はありません。read
しかし、私たちは入力を必要とし、破壊しませんIFS=
。-r
バックスラッシュがあるスペースを抜ける理由もありません。先頭拡張は"$file"
変数の内容をそのままコマンドに渡します。脱出をキャンセルすることも難しく、使用するとeval
他のことも多く処理し、括弧などで吐き出す。
find
すでに含まれている項目に出力を追加するのかfull_list.txt
、リストを再生成するのかはわかりません。リストはすぐに処理されるので、古いコンテンツは無視する方がより合理的だと思います。
terdonコメントと同様に、ファイル名のリストを保存するために中間ファイルが必ずしも必要ではありません。find ... | while IFS= read file, do ...
Bash / ksh / zshで置換を実行または処理できますwhile IFS= read file, do ... done < <(find ...)
。 whileループ内に変数を設定するには、2つの違いが重要です。以下を参照してください。私の変数が1つの「読み込み中」ループではローカルですが、一見似ている他のループではローカルではないのはなぜですか?