
Ich habe meinen Speicherplatz voll ausgeschöpft und möchte Platz schaffen.
Ich habe darüber nachgedacht, alle Dateien in MKV zu konvertieren und hochauflösende Dateien auf eine niedrigere Auflösung herunterzuskalieren.
Um MP4 in MKV zu konvertieren, gibt es
ffmpeg -i input.mp4 -vcodec copy -acodec copy output.mkv
Und um es herunterzustufen, gibt es
ffmpeg -i input.mp4 -vf scale=$w:$h <encoding-parameters> output.mp4
aber ich muss alle Dateien konvertieren, nicht eine einzige MP4-Datei. Ich muss die Eingabedatei nach der Verarbeitung entfernen und das darf ich nur für Dateien über einer bestimmten Auflösung tun. Außerdem möchte ich das Seitenverhältnis beibehalten und ich weiß nicht, ob das funktioniert.
Es gibt ein Tool namensVideo-Diätdas trägt teilweise dazu bei.
Das ist, was ich gerne tun würde
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.
Vielleicht sollte ich auchVerringern Sie die Bildratebis zu 24 fps?
Wenn es einen besseren Weg gibt, würde ich ihn gerne hören.
Antwort1
Hier ist ein Skript, das Ihnen den Einstieg erleichtert. Sie werden es wahrscheinlich Ihren Bedürfnissen entsprechend modifizieren wollen, Optionen zu ffmpeg hinzufügen wollen, wenn Sie die Framerate ändern wollen, usw.
Beachten Sie, dass es dort eine Bedingung gibt, die prüft, ob die Datei bereits eine MKV-Datei ist, aber ich mache eigentlich nichts anderes damit, also ist die Bedingung irgendwie sinnlos. Sie ist nur da, weil Ihre Frage den Eindruck erweckte, als wollten Sie etwas anderes damit machen, obwohl ich nicht sicher bin, warum. FFMPEG kann gleichzeitig skalieren und konvertieren.
Wenn Sie jedoch etwas anderes tun möchten, ändern Sie die ffmpeg-Zeile für den Fall, dass die Bedingung erfüllt ist, in etwas anderes.
#!/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
Das ist vielleicht etwas übertrieben, und es gibt vielleicht Möglichkeiten, es zu vereinfachen, aber das ist, was ich tun würde.