Рекурсивная обработка видеофайлов для освобождения места

Рекурсивная обработка видеофайлов для освобождения места

Я исчерпал имеющееся у меня место для хранения данных и хотел бы освободить немного места.

Я думал о том, чтобы преобразовать все файлы в 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 кадров в секунду?

Если есть лучший способ, я хотел бы его услышать.

решение1

Вот скрипт, с которого можно начать. Вероятно, вы захотите изменить его в соответствии со своими потребностями, добавить опции в ffmpeg, если хотите изменить частоту кадров и т. д.

Обратите внимание, что там есть условие, проверяющее, является ли файл уже .mkv, но я на самом деле не делаю с ними ничего другого, так что условие бессмысленно. Оно там просто потому, что ваш вопрос звучал так, как будто вы хотите сделать с ними что-то другое, хотя я не уверен, почему. FFMPEG может масштабировать и конвертировать одновременно.

Но если вы хотите сделать что-то другое, измените строку 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

Возможно, это излишне, и, возможно, есть способы упростить это, но я бы сделал именно так.

Связанный контент