#!/bin/bash maxwidth=1280 maxheight=720 bitrate="2M" bufsize="1M" # mp4 is better for streaming, mkv supports all sorts of mixed codecs and subtitles #container="mkv" container="mp4" #encoder="libx264" #libx264 = CPU, better quality and much smaller filesize; h264_amf = AMD GPU; h265_nvenv = Nvidia GPU; h264_qsv = Intel GPU # ffpb is a wrapper for ffmpeg to show a progress bar and the remaining time. # install it using: # pip install ffpb # Check if ffpb is installed, then use it, otherwise use normal ffmpeg builtin type -P "ffpb" &> /dev/null && binary="ffpb" || binary="ffmpeg" # Check if a parameter is provided if [ -z "$1" ]; then echo "Usage: "$(basename $0)" " exit 1 fi for input in "$@"; do if [ -f "$input" ]; then echo "Processing file: $input" output="${input%.*}.convertednew" # Check if mp4 container is desired and if subtitle is ASS format, then convert to srt, otherwise just copy subs subtitles_present=$(ffprobe -v error -select_streams s -show_entries stream=codec_name -of csv=p=0:s=x "$input") if [ "$subtitles_present" == "ass" ] && [ "$container" == "mp4" ]; then subtitle_option="-c:s mov_text -metadata:s:s:0 language=en" else subtitle_option="-scodec copy" fi #check framerate to only ever reduce it and not increase it # ffprobe returns 25/1 or 24000/1001. result needs to be calculated and needs to be an integer, thus the bash $(( )). fps=$(ffprobe -v 0 -of csv=p=0 -select_streams v -show_entries stream=avg_frame_rate "$input" | sed 's#/# / #g') if [ "$fps" == "0 / 0" ]; then # some video files return 0 / 0 for avg_frame_rate, using r_frame_rate instead fps=$(ffprobe -v 0 -of csv=p=0 -select_streams v -show_entries stream=r_frame_rate "$input" | sed 's#/# / #g') fi fps=$(( $fps )) if [ $fps -gt 30 ]; then fps_option="-r 30" else fps_option="" fi #-c:a copy #copies audio as is, but mp4 works best with aac and wma cannot be in mp4 files #$binary -i "$input" -vf scale=-2:$resolution -c:v libx264 -r 30 -crf 28 -c:a aac -scodec copy -b:v $bitrate -maxrate $bitrate -bufsize $bufsize "$output" # using complex filter to prevent upscaling and only ever downscale cmd=$binary' -i "'"$input"'" -filter_complex "scale=ceil(iw*min(1\,min('$maxwidth'/iw\,'$maxheight'/ih))/2)*2:-2" -c:v libx264 '$fps_option' -crf 28 -c:a aac '$subtitle_option' -b:v '$bitrate' -maxrate '$bitrate' -bufsize '$bufsize' -f '$container' "'"$output"'"' $binary -i "$input" -filter_complex "scale=ceil(iw*min(1\,min($maxwidth/iw\,$maxheight/ih))/2)*2:-2" -c:v libx264 $fps_option -crf 28 -c:a aac $subtitle_option -b:v $bitrate -maxrate $bitrate -bufsize $bufsize -f $container "$output" if [ $? -eq 0 ]; then actualheight=$(ffprobe -v error -select_streams v -show_entries stream=height -of csv=p=0:s=x "$output") #output2="${output%.*}."$actualheight"p.$container" output2="${output//.convertednew/.$actualheight""p.}$container" mv "$output" "$output2" echo "Output file: $output2" else echo "An error occured. File not converted properly!" echo "Full ffmpeg command:" echo "${cmd//ffpb/ffmpeg}" fi fi done # When using in Nemo, it's helpful to force a key to be pressed before closing the terminal to see the status or any errors. Uncomment the following line: #echo;read -rsn1 -p "Press any key to continue . . .";echo