#!/bin/bash for f in *.mkv do ## Detect what audio codec is being used: audio=$(ffprobe "$f" 2>&1 | sed -n '/Audio:/s/.*: \([a-zA-Z0-9]*\).*/\1/p' | sed 1q) ## Detect video codec: video=$(ffprobe "$f" 2>&1 | sed -n '/Video:/s/.*: \([a-zA-Z0-9]*\).*/\1/p' | sed 1q) ## Set default audio settings (you may need to use a different encoder, ## since libfdk_aac is not re-distributable) aopts="-c:a libfdk_aac -vbr 3" ## Set default video settings: vopts="-c:v libx264 -crf 22 -preset veryfast" case "$audio" in aac|alac|mp3|mp2|ac3 ) ## If the audio is one of the MP4-supported codecs, ## copy the stream instead of transcoding aopts="-c:a copy" ;; "" ) ## If there is no audio stream, don't bother with audio aopts="-an" ;; * ) ;; esac case "$video" in ## If the video stream is one of the MP4-compatible formats, ## copy the stream h264|mpeg4|mpeg2video|mpeg1video ) vopts="-c:v copy" ;; "" ) ## If no video stream is detected, don't bother with video vopts="-vn" ;; * ) ;; esac ## This will tell you what is going on; that is, ## it will echo a line that will make the terminal output ## easier to follow: echo -e "\n \E[1;30mffmpeg -i $f -map 0 $vopts $aopts ${f/%mkv/mp4}\E[0m" ## And now, to the meat of the thing. ## Normally you should ALWAYS quote your variables ## so that spaces in filenames etc will be preserved. ## But in this case, doing so for $vopts and $aopts ## would break the ffmpeg command ## because we WANT the spaces to break up the strings: ffmpeg -y -i "$f" -map 0 $vopts $aopts "${f/%mkv/mp4}" done exit 0