#!/bin/bash ############################################################################### # By SlainVeteran (with a few pointers by Shelf) # Inspired by work of Shiny, ADO and Shelf # Released under the LGPLv3 licence. # http://www.opensource.org/licenses/lgpl-3.0.html ############################################################################### # This script was built with the Hi Def scene standard in mind, but I could # only test it on DVDs because didn't have a HD-DVD or Bluray drive or discs. # This should work with non-ArCCoS DVDs, but I have no guarantees for HD-DVD # or Bluray sources. If it doesn't work, fix it yourself. ############################################################################### # TODO: # find some boogs # maybe add support for more than 2 audio languages # maybe add support for mutli-angle DVDs # an idea of a deinterlacer: -vf yadif=3:1,mcdeint=1:1:10 ############################################################################### # You need: mencoder/mplayer, ffmpeg, mkvmerge, x264 # on Gentoo, these can be found in the following packages: # media-video/mplayer # media-video/ffmpeg # media-video/mkvtoolnix # media-video/x264-encoder ############################################################################### FIRSTPASS="/dev/null" ALANG="" AID=0 VBR=0 ABR=0 DEVICE="/dev/dvd" FILTERS="pullup,softskip,harddup" FPS="" HELP=0 ITU=0 CROP=1 PASSES=2 SIZE=0 SLANG="en" TITLE="" TRACK=0 DONOTHING=0 while [ $# -gt 0 ]; do case "$1" in -1 | --first-pass ) FIRSTPASS="video_first.264" shift ;; -a | --alang ) ALANG="$2" shift 2 ;; --aid ) AID="$2" shift 2 ;; -b | --audio-bitrate ) ABR="$2" shift 2 ;; -B | --video-bitrate ) VBR="$2" shift 2 ;; -d | --device ) DEVICE="$2" shift 2 ;; -f | --filters ) FILTERS="$2" shift 2 ;; -F | --fps ) FPS="$2" shift 2 ;; -h | --help ) HELP=1 break ;; -i | --itu | --ITU ) ITU=1 shift ;; -n | --no-crop ) CROP=0 shift ;; -p | --passes ) PASSES="$2" shift 2 ;; -S | --size ) SIZE="$2" shift 2 ;; -s | --slang ) SLANG="$(echo "$2" | sed 's/,/ /g')" shift 2 ;; -t | --title ) TITLE="$2" shift 2 ;; -T | --track ) TRACK="$2" shift 2 ;; -z | --do-nothing ) DONOTHING=1 shift ;; * ) echo "Unknown option: $1" HELP=1 break ;; esac done if [ $HELP -gt 0 ]; then # echo "12345678901234567890123456789012345678901234567890123456789012345678901234567890" echo "Scene-compatible DVD Ripper by SlainVeteran" echo "Usage: rip-dvd.sh [options]" if [ "$1" != "-h" ] && [ "$1" != "--help" ]; then exit 1 fi echo "" echo "WARNING: This script is an expert system and WILL let you input stupid values" echo "and does possess the capability to fill your hard drive 6 times over." echo "" echo "Mandantory parameters:" echo "" echo "Optional parameters:" echo " -1, --first-pass" echo " Save the output from the first pass of a mutli-pass encode. This" echo " can be used as a preview but will not be representative of the" echo " quality of the final encode." echo " Default: Not set." echo "" echo " -a, --alang" echo " The primary audio language of the DVD in ISO639-1 format. This" echo " should only be specified for non-English DVDs. If there is also an" echo " English language audio track on the DVD, this will be ripped too," echo " with the language specified as the primary language. The audio" echo " track ID can be specified by adding it after a colon e.g. fr:130" echo " Default: Not set." echo "" echo " --aid" echo " The audio track ID for the English language audio. This should be" echo " used when the audio tracks are not labelled with language" echo " information or mplayer picks the wrong audio track." echo " Default: Not set." echo "" echo " -b, --audio-bitrate" echo " The bitrate of the audio to encode at. This will be ignored if the" echo " audio stream is being copied verbatim from the source (AC-3)." echo " This should be specified in bits per second, not kbits per second." echo " Default: The same bitrate as the source." echo "" echo " -B, --video-bitrate" echo " The bitrate of the video to encode at. This is an average bitrate." echo " This should be specified in bits per second, not kbits per second." echo " Default: Calculated for the target size." echo "" echo " -d, --device" echo " The DVD Device to use. Default: /dev/dvd" echo "" echo " -f, --filters" echo " The -vf command to pass to mencoder during encoding. format=i420" echo " will be automatically added to make sure that the video can be" echo " passed to the x264 encoder. crop=w:h:x:y will be automatically" echo " added unless --no-crop is specified. harddup is recommended." echo "" echo " -F, --fps" echo " The output FPS. This is useful for NTSC movies where the input and" echo " output FPS is different. This can be specified as a float (29.97)" echo " or as a fraction (30000/1001). Default: same as the input FPS." echo "" echo " -h, --help" echo " This help information." echo "" echo " -i, --itu, --ITU" echo " Tell the script to use ITU SARs. Default: Non-ITU." echo "" echo " -n, --no-crop" echo " Do not perform any cropping of the video to remove black borders." echo "" echo " -p, --passes" echo " The number of passes to use with the x264 encoder. Default: 2" echo "" echo " -S, --size" echo " A target filesize (in MiB) to aim for. This will aim to be at most" echo " 40 MiB undersized from the target and not oversized. This option" echo " is overridden by the --video-bitrate option." echo " Default: An appropriate scene-compatible size for the source." echo "" echo " -s, --slang" echo " A comma-seperated list of the subtitle languages to rip in" echo " ISO639-1 format. Subtitle track IDs can be specified by adding" echo " them after a colon e.g. en,fr:1. The subtitle tracks will be" echo " renumbered. Default: en" echo "" echo " -t, --title" echo " The title of the DVD being ripped. This will be inserted into the" echo " Matroska container and is used for the output filename." echo " Default: The name stored on the DVD." echo "" echo " -T, --track" echo " The track of the DVD to rip. Default: the longest track." echo "" echo " -z, --do-nothing" echo " Do not do any ripping. Just work out the details and write the" echo " commands which would be performed to rip.txt and chapters.txt." exit 0 fi # Work out the longest track if one was not specified if [ ${TRACK} -eq 0 ]; then echo -n "Searching for the longest track... " LENGTHS=$(mplayer -nocache -dvd-device ${DEVICE} dvd:// -identify -frames 0 2> /dev/null | grep -e '[0-9]\+_LENGTH') MAXLENGTH=0 for LENGTH in ${LENGTHS}; do TRLENGTH=$(echo ${LENGTH} | sed 's/.*=\([0-9]\+\)\.\([0-9]\+\)/\1\2/') if [ ${TRLENGTH} -gt ${MAXLENGTH} ]; then TRACK=$(echo ${LENGTH} | sed 's/.*_\([0-9]\+\)_.*/\1/') MAXLENGTH=${TRLENGTH} fi done echo "${TRACK}" fi # Grab the identify string echo -n "Grabbing the information for the source content... " if [ ${AID} -gt 0 ]; then IDENTIFY=$(mplayer -nocache -dvd-device ${DEVICE} dvd://${TRACK} -identify -frames 0 2> /dev/null) else IDENTIFY=$(mplayer -nocache -dvd-device ${DEVICE} dvd://${TRACK} -identify -frames 0 2> /dev/null) fi echo "Done." # normalise the audio languages to lang:id if [ ${AID} -eq 0 ]; then ALANGS="en ${ALANG}" else ALANGS="${ALANG}" fi AUDLANGS="" for AUD_LANG in ${ALANGS}; do name=$(echo "${AUD_LANG}" | cut -d ':' -f 1) aid=$(echo "${AUD_LANG}" | cut -d ':' -f 2) if [ -z "${name}" ]; then echo -n "Searching for language of audio language ID ${aid}... " name=$(echo "${IDENTIFY}" | grep -e "ID_AID_${aid}_LANG=.." | head -n 1 | sed "s/ID_AID_${aid}_LANG=\(..\)/\1/") if [ -z "${name}" ]; then echo "Not found, skipping." else AUDLANGS=$(echo -n "${AUDLANGS}${name}:${aid} ") echo "${name}" fi elif [ "${aid}" == "${name}" ]; then echo -n "Searching for ${name} audio language ID... " aid=$(echo "${IDENTIFY}" | grep -e "ID_AID_[0-9]\+_LANG=${name}" | head -n 1 | sed "s/ID_AID_\([0-9]\+\)_LANG=${name}/\1/") if [ -z "${aid}" ]; then echo "Not found, skipping." else AUDLANGS=$(echo -n "${AUDLANGS}${name}:${aid} ") echo "${aid}" fi else echo -n "Checking audio language ID ${aid} exists... " if [ $(echo "${IDENTIFY}" | grep -e "ID_AID_${aid}_LANG=.." | head -n 1 | wc -l) -eq 1 ]; then AUDLANGS=$(echo -n "${AUDLANGS}${name}:${aid} ") echo "Found." else echo "Not found, skipping." fi fi done if [ ${AID} -eq 0 ]; then AID=$(echo "${AUDLANGS}" | cut -d ' ' -f 1 | cut -d ':' -f 2) ALANG=$(echo "${AUDLANGS}" | cut -d ' ' -f 2) else ALANG="${AUDLANGS}" fi # Grab the identify string for an english audio track (and replace the earlier # grabbed identify string which was associated with a specific audio track) echo -n "Grabbing the information for the en audio language... " IDENTIFY=$(mplayer -nocache -dvd-device ${DEVICE} dvd://${TRACK} -identify -frames 0 -aid ${AID} 2> /dev/null) echo "Done." # Grab the identify string for a non-english audio track IDENTIFY_ALANG="" if [ -n "${ALANG}" ]; then ALANG_LAN=$(echo "${ALANG}" | cut -d ':' -f 1) ALANG_AID=$(echo "${ALANG}" | cut -d ':' -f 2) echo -n "Grabbing the information for the ${ALANG_LAN} audio language... " IDENTIFY_ALANG=$(mplayer -nocache -dvd-device ${DEVICE} dvd://${TRACK} -identify -frames 0 -aid ${ALANG_AID} 2> /dev/null) echo "Done." fi # Work out the source details if [ -z "${TITLE}" ]; then TITLE=$(echo "${IDENTIFY}" | grep 'ID_DVD_VOLUME_ID' | cut -d '=' -f 2) fi SRC_LENGTH=$(echo "${IDENTIFY}" | grep 'ID_LENGTH' | cut -d '=' -f 2 | cut -d '.' -f 1) if [ -z "${FPS}" ]; then SRC_FPS=$(echo "${IDENTIFY}" | grep 'VIDEO:' | cut -d ' ' -f 10) else SRC_FPS="${FPS}" fi SRC_BITRATE_VIDEO=$(echo "${IDENTIFY}" | grep 'ID_VIDEO_BITRATE' | cut -d '=' -f 2) SRC_BITRATE_AUDIO=$(echo "${IDENTIFY}" | grep 'ID_AUDIO_BITRATE' | cut -d '=' -f 2 | tail -n 1) SRC_CODEC_AUDIO=$(echo "${IDENTIFY}" | grep 'ID_AUDIO_FORMAT' | cut -d '=' -f 2) SRC_CHANNELS_AUDIO_PRETTY=$(echo "${IDENTIFY}" | grep 'audio stream:' | grep "aid: ${AID}" | cut -d ' ' -f 6 | sed 's/(\(.*\))/\1/') SRC_BITRATE_AUDIO_ALANG=0 SRC_CODEC_AUDIO_ALANG=0 SRC_CHANNELS_AUDIO_ALANG_PRETTY=0 if [ -n "${IDENTIFY_ALANG}" ]; then SRC_BITRATE_AUDIO_ALANG=$(echo "${IDENTIFY_ALANG}" | grep 'ID_AUDIO_BITRATE' | cut -d '=' -f 2 | tail -n 1) SRC_CODEC_AUDIO_ALANG=$(echo "${IDENTIFY_ALANG}" | grep 'ID_AUDIO_FORMAT' | cut -d '=' -f 2) SRC_CHANNELS_AUDIO_ALANG_PRETTY=$(echo "${IDENTIFY}" | grep 'audio stream:' | grep "aid: ${ALANG_AID}" | cut -d ' ' -f 6 | sed 's/(\(.*\))/\1/') fi # Munge the chapter information into an mkvmerge compatible format CHAPTERS=$(echo "${IDENTIFY}" | grep '^CHAPTERS' | sed 's/^CHAPTERS: //g') CHAPTERS=$(echo "${CHAPTERS}" | awk -F, '{for(i = 1; i != NF; i++) { if(i < 10) { print "CHAPTER0" i "=" $i ".000"; print "CHAPTER0" i "NAME=Chapter " i; } else { print "CHAPTER" i "=" $i ".000"; print "CHAPTER" i "NAME=Chapter " i; } }}') # normalise the subtitles so they all have subtitle IDs SUBLANGS="" for SUB_LANG in ${SLANG}; do name=$(echo "${SUB_LANG}" | cut -d ':' -f 1) sid=$(echo "${SUB_LANG}" | cut -d ':' -f 2) if [ -z "${name}" ]; then echo -n "Searching for language of subtitle language ID ${sid}... " name=$(echo "${IDENTIFY}" | grep -e "ID_SID_${sid}_LANG=.." | head -n 1 | sed "s/ID_SID_${sid}_LANG=\(..\)/\1/") if [ -z "${name}" ]; then echo "Not found, skipping." else SUBLANGS=$(echo -n "${SUBLANGS}${name}:${sid} ") echo "${name}" fi elif [ "${sid}" == "${name}" ]; then echo -n "Searching for ${name} subtitle language ID... " sid=$(echo "${IDENTIFY}" | grep -e "ID_SID_[0-9]\+_LANG=${name}" | head -n 1 | sed "s/ID_SID_\([0-9]\+\)_LANG=${name}/\1/") if [ -z "${sid}" ]; then echo "Not found, skipping." else SUBLANGS=$(echo -n "${SUBLANGS}${name}:${sid} ") echo "${sid}" fi else echo -n "Checking subtitle language ID ${sid} exists... " if [ $(echo "${IDENTIFY}" | grep -e "ID_SID_${aid}_LANG=.." | head -n 1 | wc -l) -eq 1 ]; then SUBLANGS=$(echo -n "${SUBLANGS}${name}:${sid} ") echo "Found." else echo "Not found, skipping." fi fi done SLANG="${SUBLANGS}" # work out cropping by taking samples through the film and using the largest. SRC_VIDEO_WIDTH=$(echo "${IDENTIFY}" | grep 'ID_VIDEO_WIDTH' | cut -d '=' -f 2) SRC_VIDEO_HEIGHT=$(echo "${IDENTIFY}" | grep 'ID_VIDEO_HEIGHT' | cut -d '=' -f 2) if [ ${CROP} -eq 1 ];then echo -n "Calculating the cropping for the video" start_bound=$(( ${SRC_LENGTH} / 4 / 60 )) # take a sample every 10 minutes (with a guaranteed sample) samples=$(( ( ${SRC_LENGTH} / 1200 ) + 1 )) left=$(( ${SRC_VIDEO_WIDTH} / 2 )) right=${left} top=$(( ${SRC_VIDEO_HEIGHT} / 2 )) bottom=${top} for (( i = 0; i < ${samples}; i++ )); do minute=$(( ${start_bound} + ${i} * 10 )) sample=$(mplayer -nocache -dvd-device ${DEVICE} dvd://${TRACK} -vf cropdetect=24:1 -vo null -ao dummy -frames 100 -ss ${minute}:00 2>/dev/null | sed -n 's/.*-vf crop=\([0-9:]*\)).*/\1/p') sample=$(echo "${sample}" | sed -n "$(echo "${sample}" | wc -l)p") xA=$(echo "${sample}" | cut -d ':' -f 3) xB=$(echo "${sample}" | cut -d ':' -f 1) xB=$(( ${xB} + ${xA} )) yA=$(echo "${sample}" | cut -d ':' -f 4) yB=$(echo "${sample}" | cut -d ':' -f 2) yB=$(( ${yB} + ${yA} )) if [ ${xA} -lt ${left} ]; then left=${xA}; fi if [ ${xB} -gt ${right} ]; then right=${xB}; fi if [ ${yA} -lt ${top} ]; then top=${yA}; fi if [ ${yB} -gt ${bottom} ]; then bottom=${yB}; fi echo -n "." done width=$(( ${xB} - ${xA} )) height=$(( ${yB} - ${yA} )) if [ $(( ${width} % 16 )) -ne 0 ]; then increase=$(( 16 - ( ${width} % 16 ) )) half_increase=$(( ${increase} / 2 )) xA=$(( ${xA} - ${half_increase} )) width=$(( ${xB} + ( ${increase} - ${half_increase} ) )) if [ ${width} -gt ${SRC_VIDEO_WIDTH} ];then xA=$(( ${xA} + 8 )) width=$(( ${width} - 16 )) fi if [ ${xA} -lt 0 ]; then width=$(( ${width} - ${xA} )) xA=0 fi if [ $(( ${xA} + ${width} )) -gt ${SRC_VIDEO_WIDTH} ]; then offset=$(( ( ${xA} + ${width} ) - ${SRC_VIDEO_WIDTH} )) width=$(( ${width} - ${offset} )) xA=$(( ${xA} - ${offset} )) fi fi if [ $(( ${height} % 8 )) -ne 0 ]; then increase=$(( 8 - ( ${height} % 8 ) )) half_increase=$(( ${increase} / 2 )) yA=$(( ${yA} - ${half_increase} )) height=$(( ${yB} + ( ${increase} - ${half_increase} ) )) if [ ${height} -gt ${SRC_VIDEO_HEIGHT} ];then yA=$(( ${yA} + 4 )) height=$(( ${height} - 8 )) fi if [ ${yA} -lt 0 ]; then height=$(( ${height} - ${yA} )) yA=0 fi if [ $(( ${yA} + ${height} )) -gt ${SRC_VIDEO_HEIGHT} ]; then offset=$(( ( ${yA} + ${height} ) - ${SRC_VIDEO_HEIGHT} )) height=$(( ${height} - ${offset} )) yA=$(( ${yA} - ${offset} )) fi fi CROP="${width}:${height}:${xA}:${yA}" DIMENSIONS="${width}x${height}" echo " ${CROP}" else CROP="" DIMENSIONS="${SRC_VIDEO_WIDTH}x${SRC_VIDEO_HEIGHT}" fi # work out the SAR echo -n "Calculating the SAR... " resize=$(mplayer -nocache -dvd-device ${DEVICE} dvd://${TRACK} -frames 1 -vo yuv4mpeg:file=/dev/null -ao null 2>/dev/null | grep "VO:") start_size=$(echo "${resize}" | cut -d ' ' -f 3) start_size_w=$(echo "${start_size}" | cut -d 'x' -f 1) start_size_h=$(echo "${start_size}" | cut -d 'x' -f 2) end_size=$(echo "${resize}" | cut -d ' ' -f 5) end_size_w=$(echo "${end_size}" | cut -d 'x' -f 1) end_size_h=$(echo "${end_size}" | cut -d 'x' -f 2) if [ ${start_size_h} -eq ${end_size_h} ]; then # 960 is the least common multiple of the SAR numerators (remeber, bash is integer math). ratio=$(( ( ${start_size_w} * 960 ) / ${end_size_w} )) case ${ratio} in 792) SAR="40:33" ITU="ITU" RATIO="16:9 NTSC" ;; 1056) SAR="10:11" ITU="ITU" RATIO="4:3 NTSC" ;; 660) SAR="16:11" ITU="ITU" RATIO="16:9 PAL" ;; 880) SAR="12:11" ITU="ITU" RATIO="4:3 PAL" ;; 810) if [ ${ITU} -eq 1 ];then SAR="40:33" ITU="ITU" else SAR="32:27" ITU="Non-ITU" fi RATIO="16:9 NTSC" ;; 1080) if [ ${ITU} -eq 1 ];then SAR="10:11" ITU="ITU" else SAR="8:9" ITU="Non-ITU" fi RATIO="4:3 NTSC" ;; 675) if [ ${ITU} -eq 1 ];then SAR="16:11" ITU="ITU" else SAR="64:45" ITU="Non-ITU" fi RATIO="16:9 PAL" ;; 900) if [ ${ITU} -eq 1 ];then SAR="12:11" ITU="ITU" else SAR="16:15" ITU="Non-ITU" fi RATIO="4:3 PAL" ;; *) echo "960:${ratio} does not match a known SAR!" exit 1 ;; esac else echo "Different video height after applying the SAR!" exit 1 fi echo "${SAR} ${ITU}" # sort out the pretty printing for the audio case ${SRC_CODEC_AUDIO} in 8192 ) SRC_CODEC_AUDIO_PRETTY="AC-3" EN_ENCODE="copy" ;; * ) SRC_CODEC_AUDIO_PRETTY="Unknown (${SRC_CODEC_AUDIO})" EN_ENCODE="ffmpeg" ;; esac case ${SRC_CODEC_AUDIO_ALANG} in 8192 ) SRC_CODEC_AUDIO_ALANG_PRETTY="AC-3" AL_ENCODE="copy" ;; * ) SRC_CODEC_AUDIO_ALANG_PRETTY="Unknown (${SRC_CODEC_AUDIO_ALANG})" AL_ENCODE="ffmpeg" ;; esac case ${SRC_CHANNELS_AUDIO_PRETTY} in '5.1' | '5.1/6.1' ) SRC_CHANNELS_AUDIO=6 ;; 'stereo' ) SRC_CHANNELS_AUDIO=2 ;; * ) SRC_CHANNELS_AUDIO="0 (${SRC_CHANNELS_AUDIO_ALANG})" ;; esac case ${SRC_CHANNELS_AUDIO_ALANG_PRETTY} in '5.1' | '5.1/6.1' ) SRC_CHANNELS_AUDIO_ALANG=6 ;; 'stereo' ) SRC_CHANNELS_AUDIO_ALANG=2 ;; * ) SRC_CHANNELS_AUDIO_ALANG="0 (${SRC_CHANNELS_AUDIO_ALANG_PRETTY})" ;; esac echo "" echo "==Source details==" echo "Title: ${TITLE}" echo "DVD Track chosen: ${TRACK}" echo "Length: ${SRC_LENGTH} seconds" echo "Video bitrate: ${SRC_BITRATE_VIDEO} bps" echo "Video size: ${SRC_VIDEO_WIDTH}x${SRC_VIDEO_HEIGHT} (${end_size_w}x${end_size_h})" if [ -n "${CROP}" ]; then echo "Video crop size: ${CROP}" CROP=$(echo ",crop=${CROP}") fi echo "Video SAR: ${SAR} ${ITU} (${RATIO})" echo "Video FPS: ${SRC_FPS}" echo "en Audio bitrate: ${SRC_BITRATE_AUDIO} bps" echo "en Audio codec: ${SRC_CODEC_AUDIO_PRETTY}" echo "en Audio channels: ${SRC_CHANNELS_AUDIO}" if [ -n "${ALANG}" ]; then echo "secondary Audio bitrate: ${SRC_BITRATE_AUDIO_ALANG} bps" echo "secondary Audio codec: ${SRC_CODEC_AUDIO_ALANG_PRETTY}" echo "secondary Audio channels: ${SRC_CHANNELS_AUDIO_ALANG}" fi echo "number of chapters: $(echo "${CHAPTERS}" | wc -l)" echo "number of subtitles chosen: $(echo "${SLANG}" | wc -w)" # copy the audio bitrate and channels EN_BITRATE=${SRC_BITRATE_AUDIO} EN_CHANNELS=${SRC_CHANNELS_AUDIO} AL_BITRATE=${SRC_BITRATE_AUDIO_ALANG} AL_CHANNELS=${SRC_CHANNELS_AUDIO_ALANG} if [ ${ABR} -ne 0 ]; then EN_BITRATE=${ABR} if [ -n "${ALANG}" ]; then AL_BITRATE=${ABR} fi fi AUDIO_SIZE=$(( ( ( ${EN_BITRATE} + ${AL_BITRATE} ) * ${SRC_LENGTH} ) / 8 )) # calculate an ideal video bitrate # we calculate for 20 MiB under the required size since the specifications # allow a 40 MiB undersize, and an oversize is absolutely useless. sizes="447 498 560 640 745 896 1120 1493 2240 2713 4479 6719 8140 8959" N_BITRATE="" if [ ${VBR} -eq 0 ]; then if [ ${SIZE} -ne 0 ]; then V_BITRATE=$(( ( ( ( ( ${SIZE} - 20 ) * (1024*1024) - ${AUDIO_SIZE} ) * 8 ) / ${SRC_LENGTH} ) / 1000 )) V_BITRATE=$(( ${V_BITRATE} * 1000 )) else for size in ${sizes}; do v_bitrate=$(( ( ( ( ( ${size} - 20 ) * (1024*1024) - ${AUDIO_SIZE} ) * 8 ) / ${SRC_LENGTH} ) / 1000 )) if [ ${v_bitrate} -lt 2100 ]; then V_BITRATE=$(( ${v_bitrate} * 1000 )) SIZE=${size} else if [ -z "${N_BITRATE}" ]; then N_BITRATE=" ($(( ${v_bitrate} * 1000 )) bps @ ${size} MiB)" fi fi done fi else V_BITRATE=${VBR} fi VIDEO_SIZE=$(( ( ${V_BITRATE} * ${SRC_LENGTH} ) / 8 )) echo "" echo "==Pre-Encode details==" echo "Target maximum file size: ${SIZE} MiB" echo "Video bitrate: ${V_BITRATE} bps${N_BITRATE}" echo "Estimated total size of video track: $(( ${VIDEO_SIZE} / (1024*1024) )) MiB" echo "en Audio bitrate: ${EN_BITRATE} bps" if [ -n "${ALANG}" ]; then echo "secondary Audio bitrate: ${AL_BITRATE} bps" fi echo "Estimated total size of audio track(s): $(( ${AUDIO_SIZE} / (1024*1024) )) MiB" echo "Estimated total size of video + audio: $(( ( ${VIDEO_SIZE} + ${AUDIO_SIZE} ) / (1024*1024) )) MiB" echo "" # -is this scene compatible? (give a 10 second escape countdown if not) # make a temporary directory to store the streams in SANITISED_TITLE=$(echo "${TITLE}" | sed 's/:/-/g;s/[^0-9a-zA-Z\-]/_/g') if [ ${DONOTHING} -eq 0 ]; then echo -n "Creating temporary working folder... " mkdir -p "${SANITISED_TITLE}" cd "${SANITISED_TITLE}" DIR=$(mktemp -p. -d XXXXXX) cd "${DIR}" echo "${SANITISED_TITLE}/${DIR}" else echo "#!/bin/bash" >rip.txt echo "" >>rip.txt fi echo "${CHAPTERS}" > chapters.txt # rip the audio (and subtitles) echo "Ripping audio and subtitles..." SLANG_COUNT=$(echo "${SLANG}" | wc -w) if [ "${SLANG_COUNT}" -ge 1 ]; then slang_detail=$(echo "${SLANG}" | cut -d ' ' -f 1) SLANG_A_COMMAND="-vobsubout subtitles -vobsuboutindex 0 -vobsuboutid $(echo "${slang_detail}" | cut -d ':' -f 1) -sid $(echo "${slang_detail}" | cut -d ':' -f 2)" SLANG_A_TEXT=" and $(echo "${slang_detail}" | cut -d ':' -f 1) subtitles" fi if [ "${SLANG_COUNT}" -ge 2 ]; then slang_detail=$(echo "${SLANG}" | cut -d ' ' -f 2) SLANG_B_COMMAND="-vobsubout subtitles -vobsuboutindex 1 -vobsuboutid $(echo "${slang_detail}" | cut -d ':' -f 1) -sid $(echo "${slang_detail}" | cut -d ':' -f 2)" SLANG_B_TEXT=" and $(echo "${slang_detail}" | cut -d ':' -f 1) subtitles" fi # to play a raw ac3 stream: # mplayer -demuxer rawaudio -rawaudio format=0x2000 input.ac3 if [ "${EN_ENCODE}" == "copy" ]; then echo -n "Ripping en audio${SLANG_A_TEXT}... " if [ ${DONOTHING} -eq 1 ]; then echo "mencoder -nocache -dvd-device ${DEVICE} dvd://${TRACK} -aid ${AID} -channels ${EN_CHANNELS} -ofps ${SRC_FPS} -of rawaudio -ovc copy -oac copy -o en_audio.ac3 ${SLANG_A_COMMAND}" >>rip.txt else echo "Ripping en audio${SLANG_A_TEXT}..." >mplayer-log.txt echo "mencoder -nocache -dvd-device ${DEVICE} dvd://${TRACK} -aid ${AID} -channels ${EN_CHANNELS} -ofps ${SRC_FPS} -of rawaudio -ovc copy -oac copy -o en_audio.ac3 ${SLANG_A_COMMAND}" >>mplayer-log.txt mencoder -nocache -dvd-device ${DEVICE} dvd://${TRACK} -aid ${AID} -channels ${EN_CHANNELS} -ofps ${SRC_FPS} -of rawaudio -ovc copy -oac copy -o en_audio.ac3 ${SLANG_A_COMMAND} >>mplayer-log.txt 2>&1 echo "" >>mplayer-log.txt fi echo "Done." else echo -n "Encoding en audio${SLANG_A_TEXT}... " if [ ${DONOTHING} -eq 1 ]; then echo "mkfifo en_audio.fifo" >>rip.txt echo "mencoder -nocache -dvd-device ${DEVICE} dvd://${TRACK} -aid ${AID} -channels ${EN_CHANNELS} -ofps ${SRC_FPS} -ovc copy -oac copy -o en_audio.fifo ${SLANG_A_COMMAND} &" >>rip.txt echo "ffmpeg -i en_audio.fifo -vn -acodec ac3 -ab ${EN_BITRATE} -ac ${EN_CHANNELS} -f ac3 en_audio.ac3" >>rip.txt echo "rm en_audio.fifo" >>rip.txt else echo "Encoding en audio${SLANG_A_TEXT}..." >mplayer-log.txt echo "Encoding en audio${SLANG_A_TEXT}..." >ffmpeg-log.txt echo "mencoder -nocache -dvd-device ${DEVICE} dvd://${TRACK} -aid ${AID} -channels ${EN_CHANNELS} -ofps ${SRC_FPS} -ovc copy -oac copy -o en_audio.fifo ${SLANG_A_COMMAND}" >>mplayer-log.txt echo "ffmpeg -i en_audio.fifo -vn -acodec ac3 -ab ${EN_BITRATE} -ac ${EN_CHANNELS} -f ac3 en_audio.ac3" >>ffmpeg-log.txt mkfifo en_audio.fifo mencoder -nocache -dvd-device ${DEVICE} dvd://${TRACK} -aid ${AID} -channels ${EN_CHANNELS} -ofps ${SRC_FPS} -ovc copy -oac copy -o en_audio.fifo ${SLANG_A_COMMAND} >>mplayer-log.txt 2>&1 & ffmpeg -i en_audio.fifo -vn -acodec ac3 -ab ${EN_BITRATE} -ac ${EN_CHANNELS} -f ac3 en_audio.ac3 >>ffmpeg-log.txt 2>&1 rm en_audio.fifo echo "" >>mplayer-log.txt echo "" >>ffmpeg-log.txt fi echo "Done." fi if [ -n "${ALANG}" ]; then if [ "${AL_ENCODE}" == "copy" ]; then echo -n "Ripping secondary audio${SLANG_B_TEXT}... " if [ ${DONOTHING} -eq 1 ]; then echo "mencoder -nocache -dvd-device ${DEVICE} dvd://${TRACK} -aid ${ALANG_AID} -channels ${AL_CHANNELS} -ofps ${SRC_FPS} -of rawaudio -ovc copy -oac copy -o al_audio.ac3 ${SLANG_B_COMMAND}" >>rip.txt else echo "Ripping secondary audio${SLANG_B_TEXT}..." >>mplayer-log.txt echo "mencoder -nocache -dvd-device ${DEVICE} dvd://${TRACK} -aid ${ALANG_AID} -channels ${AL_CHANNELS} -ofps ${SRC_FPS} -of rawaudio -ovc copy -oac copy -o al_audio.ac3 ${SLANG_B_COMMAND}" >>mplayer-log.txt mencoder -nocache -dvd-device ${DEVICE} dvd://${TRACK} -aid ${ALANG_AID} -channels ${AL_CHANNELS} -ofps ${SRC_FPS} -of rawaudio -ovc copy -oac copy -o al_audio.ac3 ${SLANG_B_COMMAND} >>mplayer-log.txt 2>&1 echo "" >>mplayer-log.txt fi echo "Done." else echo -n "Encoding secondary audio${SLANG_B_TEXT}... " if [ ${DONOTHING} -eq 1 ]; then echo "mkfifo al_audio.fifo" >>rip.txt echo "mencoder -nocache -dvd-device ${DEVICE} dvd://${TRACK} -aid ${ALANG_AID} -channels ${AL_CHANNELS} -ofps ${SRC_FPS} -ovc copy -oac copy -o al_audio.fifo ${SLANG_B_COMMAND} &" >>rip.txt echo "ffmpeg -i al_audio.fifo -vn -acodec ac3 -ab ${AL_BITRATE} -ac ${AL_CHANNELS} -f ac3 al_audio.ac3" >>rip.txt echo "rm al_audio.fifo" >>rip.txt else echo "Encoding secondary audio${SLANG_B_TEXT}..." >>mplayer-log.txt echo "Encoding secondary audio${SLANG_B_TEXT}..." >>ffmpeg-log.txt echo "mencoder -nocache -dvd-device ${DEVICE} dvd://${TRACK} -aid ${ALANG_AID} -channels ${AL_CHANNELS} -ofps ${SRC_FPS} -ovc copy -oac copy -o al_audio.fifo ${SLANG_B_COMMAND}" >>mplayer-log.txt echo "ffmpeg -i al_audio.fifo -vn -acodec ac3 -ab ${AL_BITRATE} -ac ${AL_CHANNELS} -f ac3 al_audio.ac3" >>ffmpeg-log.txt mkfifo al_audio.fifo mencoder -nocache -dvd-device ${DEVICE} dvd://${TRACK} -aid ${ALANG_AID} -channels ${AL_CHANNELS} -ofps ${SRC_FPS} -ovc copy -oac copy -o al_audio.fifo ${SLANG_B_COMMAND} >>mplayer-log.txt 2>&1 & ffmpeg -i al_audio.fifo -vn -acodec ac3 -ab ${AL_BITRATE} -ac ${AL_CHANNELS} -f ac3 al_audio.ac3 >>ffmpeg-log.txt 2>&1 rm al_audio.fifo echo "" >>mplayer-log.txt echo "" >>ffmpeg-log.txt fi echo "Done." fi else if [ "${SLANG_COUNT}" -ge 2 ]; then echo -n "Ripping $(echo "${slang_detail}" | cut -d ':' -f 1) subtitles... " if [ ${DONOTHING} -eq 1 ]; then echo "mencoder -nocache -dvd-device ${DEVICE} dvd://${TRACK} -ofps ${SRC_FPS} -ovc copy -oac copy -o /dev/null ${SLANG_B_COMMAND}" >>rip.txt else echo "Ripping $(echo "${slang_detail}" | cut -d ':' -f 1) subtitles... " >>mplayer-log.txt echo "mencoder -nocache -dvd-device ${DEVICE} dvd://${TRACK} -ofps ${SRC_FPS} -ovc copy -oac copy -o /dev/null ${SLANG_B_COMMAND}" >>mplayer-log.txt mencoder -nocache -dvd-device ${DEVICE} dvd://${TRACK} -ofps ${SRC_FPS} -ovc copy -oac copy -o /dev/null ${SLANG_B_COMMAND} >>mplayer-log.txt 2>&1 echo "" >>mplayer-log.txt fi echo "Done." fi fi # rip the remaining subtitles subtitleindex=0 for SUB in ${SLANG}; do if [ ${subtitleindex} -ge 2 ]; then echo -n "Ripping $(echo "${SUB}" | cut -d ':' -f 1) subtitles... " slang_command="-vobsubout subtitles -vobsuboutindex ${subtitleindex} -vobsuboutid $(echo "${SUB}" | cut -d ':' -f 1) -sid $(echo "${SUB}" | cut -d ':' -f 2)" if [ ${DONOTHING} -eq 1 ]; then echo "mencoder -nocache -dvd-device ${DEVICE} dvd://${TRACK} -ofps ${SRC_FPS} -ovc copy -oac copy -o /dev/null ${slang_command}" >>rip.txt else echo "Ripping $(echo "${SUB}" | cut -d ':' -f 1) subtitles... " >>mplayer-log.txt echo "mencoder -nocache -dvd-device ${DEVICE} dvd://${TRACK} -ofps ${SRC_FPS} -ovc copy -oac copy -o /dev/null ${slang_command}" >>mplayer-log.txt mencoder -nocache -dvd-device ${DEVICE} dvd://${TRACK} -ofps ${SRC_FPS} -ovc copy -oac copy -o /dev/null ${slang_command} >>mplayer-log.txt 2>&1 echo "" >>mplayer-log.txt fi echo "Done." fi subtitleindex=$(( ${subtitleindex} + 1 )) done echo "" # rip the video with multiple passes using a fifo and x264 # -have an option to -dumpstream first so you dont read the DVD multiple times? echo "Ripping the video..." if [ ${DONOTHING} -eq 1 ]; then echo "" >>rip.txt echo "mkfifo video.fifo" >>rip.txt else mkfifo video.fifo fi for ((PASS = 0; PASS < ${PASSES}; PASS++)); do echo -n "Doing pass $(( ${PASS} + 1 ))... " output="video.264" x264opts="--partitions all --8x8dct --me esa --subme 9 --merange 24 --b-adapt 2 --weightb --bframes 3 --qcomp 1.0 --ref 8 --mixed-refs --no-dct-decimate --aq-strength 0.6 --trellis 2 --direct auto --no-fast-pskip --deblock -3:-3 --psy-rd 1.0:0.0 --threads auto --progress" if [ ${PASS} -eq 0 ]; then if [ ${PASSES} -eq 1 ];then pass="" else pass="--pass 1" output="${FIRSTPASS}" x264opts="--partitions all --8x8dct --me esa --subme 1 --merange 24 --b-adapt 2 --weightb --bframes 3 --qcomp 1.0 --ref 1 --mixed-refs --no-dct-decimate --aq-strength 0.6 --direct auto --no-fast-pskip --deblock -3:-3 --threads auto --progress" fi else if [ ${PASSES} -eq 2 ]; then pass="--pass 2" else pass="--pass 3" fi fi if [ ${DONOTHING} -eq 1 ]; then echo "mencoder -nocache -dvd-device ${DEVICE} dvd://${TRACK} -vf ${FILTERS}${CROP},format=i420 -ofps ${SRC_FPS} -of rawvideo -ovc raw -oac copy -o video.fifo &" >>rip.txt echo "x264 ${pass} --bitrate $(( ${V_BITRATE} / 1000 )) --fps ${SRC_FPS} --sar ${SAR} ${x264opts} --output ${output} video.fifo ${DIMENSIONS}" >>rip.txt echo "" >>rip.txt else echo "Doing pass $(( ${PASS} + 1 ))..." >>mplayer-log.txt echo "Doing pass $(( ${PASS} + 1 ))..." >>x264-log.txt echo "mencoder -nocache -dvd-device ${DEVICE} dvd://${TRACK} -vf ${FILTERS}${CROP},format=i420 -ofps ${SRC_FPS} -of rawvideo -ovc raw -oac copy -o video.fifo" >>mplayer-log.txt mencoder -nocache -dvd-device ${DEVICE} dvd://${TRACK} -vf ${FILTERS}${CROP},format=i420 -ofps ${SRC_FPS} -of rawvideo -ovc raw -oac copy -o video.fifo >>mplayer-log.txt 2>&1 & echo "x264 ${pass} --bitrate $(( ${V_BITRATE} / 1000 )) --fps ${SRC_FPS} --sar ${SAR} ${x264opts} --output ${output} video.fifo ${DIMENSIONS}" >>x264-log.txt x264 ${pass} --bitrate $(( ${V_BITRATE} / 1000 )) --fps ${SRC_FPS} --sar ${SAR} ${x264opts} --output ${output} video.fifo ${DIMENSIONS} >>x264-log.txt 2>&1 echo "" >>mplayer-log.txt echo "" >>x264-log.txt fi echo "Done." done echo "" if [ ${DONOTHING} -eq 1 ]; then echo "rm video.fifo" >>rip.txt echo "" >>rip.txt else rm video.fifo fi # pack it all into the matroska container AUDIO="--default-track 0 --language 0:en en_audio.ac3" if [ -n "${ALANG}" ]; then AUDIO=$(echo "${AUDIO} --language 0:${ALANG_LAN} al_audio.ac3") fi echo -n "Packing into Matroska container... " if [ ${DONOTHING} -eq 1 ]; then echo "mkvmerge -o ../../${SANITISED_TITLE}.mkv --title \"${TITLE}\" --chapters chapters.txt --default-duration 0:${SRC_FPS}fps -A video.264 ${AUDIO} subtitles.idx" >>rip.txt else echo "Packing into Matroska container..." >mkvmerge-log.txt echo "mkvmerge -o ../../${SANITISED_TITLE}.mkv --title \"${TITLE}\" --chapters chapters.txt --default-duration 0:${SRC_FPS}fps -A video.264 ${AUDIO} subtitles.idx" >>mkvmerge-log.txt mkvmerge -o ../../${SANITISED_TITLE}.mkv --title "${TITLE}" --chapters chapters.txt --default-duration 0:${SRC_FPS}fps -A video.264 ${AUDIO} subtitles.idx >>mkvmerge-log.txt 2>&1 fi echo "Done." echo "" echo "==Post-Encode details==" if [ ${DONOTHING} -eq 1 ]; then POST_SIZE=0 else POST_SIZE=$(( $(ls -l ../../${SANITISED_TITLE}.mkv | cut -d ' ' -f 5) / (1024*1024) )) fi echo "File size: ${POST_SIZE} MiB" echo "Undersize by: $(( ${SIZE} - ${POST_SIZE} )) MiB" echo "" echo "Rip complete. Enjoy."