Videodateien rekursiv verarbeiten, um Platz zu schaffen

Videodateien rekursiv verarbeiten, um Platz zu schaffen

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.

verwandte Informationen