
He maximizado el espacio de almacenamiento que tengo y me gustaría hacer algo de espacio.
He pensado en convertir todos los archivos a mkv y reducir los archivos de alta resolución a una resolución más baja.
Entonces, para convertir mp4 a mkv hay
ffmpeg -i input.mp4 -vcodec copy -acodec copy output.mkv
Y para reducir la escala hay
ffmpeg -i input.mp4 -vf scale=$w:$h <encoding-parameters> output.mp4
pero necesito convertir todos los archivos, no uno solo mp4, necesito eliminar el archivo de entrada después de terminar de procesarlo y tengo que hacer esto solo para archivos por encima de una resolución determinada. También me gustaría mantener la relación de aspecto y no sé si esto lo logra.
Hay una herramienta llamadavideo-dietaeso hace parte de esto.
Esto es lo que me gustaría hacer
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.
Tal vez yo también deberíabajar la velocidad de fotogramasa 24 fps?
Si hay una manera mejor, me gustaría escucharla.
Respuesta1
Aquí tienes un guión para empezar. Probablemente querrás modificar esto para adaptarlo a tus necesidades, agregar opciones a ffmpeg si deseas cambiar la velocidad de fotogramas, etc.
Tenga en cuenta que hay un condicional allí que verifica si el archivo ya es .mkv, pero en realidad no estoy haciendo nada diferente con ellos, por lo que el condicional no tiene sentido. Simplemente está ahí porque tu pregunta hizo que pareciera que querías hacer algo diferente con ellos, aunque no estoy seguro de por qué. FFMPEG puede escalar y convertir al mismo tiempo.
Pero si desea hacer algo diferente, cambie la línea ffmpeg para cuando el condicional sea verdadero por algo diferente.
#!/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
Puede que sea un poco excesivo y puede que haya formas de simplificarlo, pero eso es lo que yo haría.