
ストレージスペースがいっぱいになったので、スペースを確保したいと思っています。
すべてのファイルを mkv に変換し、高解像度のファイルを低解像度にダウンスケールすることを考えました。
mp4をmkvに変換するには
ffmpeg -i input.mp4 -vcodec copy -acodec copy output.mkv
そして規模を縮小するには
ffmpeg -i input.mp4 -vf scale=$w:$h <encoding-parameters> output.mp4
しかし、単一の mp4 ファイルではなくすべてのファイルを変換する必要があり、処理が完了したら入力ファイルを削除する必要があり、特定の解像度を超えるファイルに対してのみこれを行う必要があります。また、アスペクト比を維持したいのですが、これがそれを実行しているかどうかはわかりません。
というツールがありますビデオダイエットそれはこれの一部です。
これが私がやりたいことです
Recursively find every file under the current directory
If the file resolution has a height equal or greater to a given height.
Convert the file to mkv if it's in another format avi, mp4, flv, etc
Downscale to a lower resolution height, keeping the aspect ratio.
私もそうすべきかもしれないフレームレートを下げる24 fps までですか?
もっと良い方法があれば、ぜひ聞かせてください。
答え1
始めるためのスクリプトがここにあります。おそらく、これをニーズに合わせて変更し、フレームレートを変更する場合は ffmpeg にオプションを追加するなどしてください。
ファイルがすでに .mkv であるかどうかを確認する条件がありますが、実際にはそれらに対して何か違うことをしているわけではないので、条件は意味がありません。質問から、それらに対して何か違うことをしたいように思われたので、そこに条件があるだけですが、その理由はよくわかりません。FFMPEG は、拡大縮小と変換を同時に行うことができます。
ただし、何か違うことをしたい場合は、条件が true の場合の ffmpeg 行を別のものに変更します。
#!/bin/bash
# set the resolution above which you want to downscale
maxwidth=1920
maxheight=1080
# set the resolution to downscale to; the width will be
# calculated to preserve aspect ratio
targetwidth=1280
# a counter for errors
errors=0
# recursively find video files; add their names to
# an array to process
mapfile -t filenames < <(find $(pwd) -type f -iregex '.*avi$\|.*mp4$\|.*m4v$\|.*flv\|.*mkv\|.*ogv\|.*webm$\|.*mov')
# loop through the array
for filename in "${filenames[@]}" ; do
# get the resolution with ffprobe
res="$(ffprobe -hide_banner -v error -select_streams v:0 -show_entries stream=width,height -print_format csv "$filename")"
# strip "stream" off "res"
res="${res#stream,}"
# parse into width and height
width="${res%,*}"
height="${res#*,}"
# compare to maxwidth/height to see if it should be
# processed
if [[ "$width" -ge "$maxwidth" ]] || [[ "$height" -ge "$maxheight" ]] ; then
# determine the output name
outputname="${filename%.*}-downscaled.mkv"
# check if output already exists; if so, skip it
if [[ -e "$outputname" ]] ; then
continue
fi
# calculate targetheight, divide by 2 multiply by 2
# to ensure it's even
targetheight="$(( ( ( (targetwidth * height) / width) / 2) * 2 ))"
# get file extension
ext="${filename##*.}"
# do something different with mkvs?
# not sure why you would though
if [[ "$ext" =~ '[Mm]{Kk][Vv]' ]] ; then
ffmpeg -i "$filename" -vf scale="$targetwidth:$targetheight" "$outputname"
exitcode="$?"
else
ffmpeg -i "$filename" -vf scale="$targetwidth:$targetheight" "$outputname"
exitcode="$?"
fi
# if conversion was a success, delete original file
if [[ "$exitcode" == 0 ]] && [[ -e "$outputname" ]] ; then
rm "$filename"
else
echo
echo "Error processing $filename" >&2
echo "Not deleted!"
let errors++
echo
fi
fi
done
# report number of errors if there were any
if [[ "$errors" == 0 ]] ; then
exit 0
fi
echo "There were $errors errors!" >&2
exit 1
それはちょっとやりすぎかもしれないし、もっと単純化する方法もあるかもしれないが、私ならそうするだろう。