#!/bin/bash # # Version: 0.5.5 # # Licence: GPL # # 2004-05-22 Giacomo Comes <encode2mpeg at users.sourceforge.net> # 2006-01-14 <encode2mpeg at katamail.com> # # Pourpose: Convert anything MPlayer can play to AVI/VCD/SVCD/DVD mpeg # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ############################################################################### # encode2mpeglight is a program that can create VCD/SVCD/DVD mpegs # and eventually extract VobSub subtitles from a DVD using only # MEncoder/MPlayer. # # encode2mpeglight is a stripped release of encode2mpeg and therefore the # code is redundant in several places, with many variables defined and # used for no apparent reason. This cannot be avoided easily. # A command line like: # encode2mpeglight <encode2mpeglight options> # will produce almost the same results as: # encode2mpeg -mpeg -mpegonly <encode2mpeglight options> # # If you need more features like: # - two or more audio streams, chapters, subtitles, menu # - creation, burn and verification of the disk image # - creation of MPEG-4 avi and subtitles for a hardware player # and more, consider to use the full release (http://encode2mpeg.sf.net) # # encode2mpeglight is mainly tested with the stable release of MPlayer, # I try to make it work with CVS too, but due to the "instable" nature of # CVS, bugs may suddenly appear. If you find any, please report it to me. ############################################################################### ############################################################################### #### start ############################################################################### export LC_ALL=POSIX set -B +f shopt -u xpg_echo nullglob PROGNAME=${0##*/} PROGFILE=$(type -p "$0") VERSION=$(awk '$2=="Version:"{print $3;exit}' <"$PROGFILE") BROWSER= ############################################################################### #### some functions ############################################################################### OptionsText () { echo echo "Arguments enclosed in [ ] are optional" } ############################################################################### ModeText () { echo echo -e "$PROGNAME defaults to encode2mpeg's Mpeg Mode, the others mode are not" echo -e "available" } ############################################################################### usage () { echo -e "Usage: $PROGNAME options source\nOptions:" sed -n '/^#### PARSING/,/^done/!d;/^done/q;/^[ ]*-[^)]*)/,/#-/!d;s/)$//;s/) *#/ /;s/#-/# /;s/ *#L.$//;s/#//;p' "$PROGFILE" ModeText OptionsText } ############################################################################### shortusage () { echo -e "\n$PROGNAME v. $VERSION Copyright (C) 2004-2006 Giacomo Comes\n" echo "This is free software; see the source for copying conditions. There is NO" echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE," echo "to the extent permitted by law." echo echo "Usage: $PROGNAME options source" echo "Options:" sed -n '/^#### PARSING/,/^done/!d;/^done/q;/^[ ]*-[^)]*)/!d;s/)$//;s/) *#/ /;s/ *#L.$//;p' "$PROGFILE" OptionsText } ############################################################################### mp_identify () { mplayer -identify -vo null -ao null -nocache "$@" -frames 0 2>/dev/null } ############################################################################### get_aspect () { mplayer -vo null -ao null -nocache -frames 4 "$@" 2>/dev/null | sed '/^Movie-Aspect is/!d;s/.*Movie-Aspect is //;s/:.*//' } ############################################################################### mlistopt () { mplayer -list-options 2>&1 | awk '$1=="Name"{m=1}{if(m&&$1!="Name"&&$1!=""&&$1!="Total:")print "\""$1"\""}' } ############################################################################### pre_log () { echo "$1" WARN="$WARN${WARN:+\n}$1" } ############################################################################### isarg () { if [[ ${2:0:1} = - || ! $2 || $2 = help ]]; then [[ ${2:0:1} = - ]] && echo "**ERROR: [$PROGNAME] invalid argument '$2' for option '$1'" [[ ! $2 ]] && echo "**ERROR: [$PROGNAME] invalid null argument for option '$1'" "$PROGFILE" -norc -l | sed '/^ '$1'$/,/^ -/!d' | sed '$d' "$PROGFILE" -norc -l | sed '/^ '$1'[ |]/,/^ -/!d' | sed '$d' exit 1 fi if [[ $2 = doc ]]; then show_html ${3:+$3.html} exit fi } ############################################################################### pr_date () { echo "[$(date '+%Y-%m-%d %H:%M:%S')]" } ############################################################################### pr_time () { date '+%j %H %M %S' | awk '{print $1*86400+$2*3600+$3*60+$4}' } ############################################################################### get_abr () { local INFO ABR INFO=$(mp_identify "${MPLAYEROPT[@]}" ${dvddev:+-dvd-device "$dvddev"} "$@" | grep '^ID_') ABR=$(echo "$INFO" | grep '^ID_AUDIO_BITRATE' | cut -f2 -d=) case $(echo "$INFO" | grep '^ID_AUDIO_CODEC' | cut -f2 -d=) in dvdpcm) abr=$((abr+ABR/1024)) ;; *) abr=$((abr+ABR/1000)) ;; esac } ############################################################################### get_pwd () { pushd &>/dev/null "$1" echo "$PWD/$2" popd &>/dev/null } ############################################################################### show_html () { local i LIST HTML PREFIX OPTION INSTDOCDIR SRCDOCDIR INSTDOCDIR=${PROGFILE%/bin/$PROGNAME}/share/doc/encode2mpeg SRCDOCDIR=${PROGFILE%/$PROGNAME}/doc if [[ -f $INSTDOCDIR/encode2mpeg.html ]]; then HTML=$(get_pwd "$INSTDOCDIR" encode2mpeg.html) elif [[ -f $SRCDOCDIR/encode2mpeg.html ]]; then HTML=$(get_pwd "$SRCDOCDIR" encode2mpeg.html) else HTML="http://encode2mpeg.sourceforge.net" fi if [[ -f $INSTDOCDIR/html/$1 ]]; then HTML=$(get_pwd "$INSTDOCDIR/html" $1) elif [[ -f $SRCDOCDIR/html/$1 ]]; then HTML=$(get_pwd "$SRCDOCDIR/html" $1) elif [[ $1 && ! -d $INSTDOCDIR/html && ! -d $SRCDOCDIR/html ]]; then HTML="http://encode2mpeg.sourceforge.net/html/$1" fi LIST=(mozilla firefox) [[ ${HTML:0:1} = / ]] && PREFIX=file:// || PREFIX= for ((i=0;i<${#LIST[*]};i++)); do type ${LIST[i]} &>/dev/null && ${LIST[i]} -remote 'openURL('"$PREFIX$HTML"',new-tab)' 2>/dev/null && return done LIST=(mozilla firefox opera konqueror epiphany galeon) if [[ $BROWSER ]]; then type "$BROWSER" &>/dev/null && LIST=("$BROWSER") || echo "++ WARN: default browser '$BROWSER' not found, using builtin browser list" fi for ((i=0;i<${#LIST[*]};i++)); do if type "${LIST[i]}" &>/dev/null; then case ${LIST[i]} in opera) OPTION=--newpage ;; epiphany|galeon) OPTION=--new-tab ;; *) OPTION= ;; esac "${LIST[i]}" $OPTION "$HTML" & return fi done } ############################################################################### #### variables initialization ############################################################################### abr=;asr=;vbr=;vfr=;videonorm=;frameformat=;output=;audioformat=;mp1=;mp2=;mp3=;ac3=;dts=;lpcm=;normalize=;volume=;multiaudio=;mpegchannels=;quiet=;resume=;blank=;encode=;ofps=;mono=;usesbr=;sbr=;clear=;keep=;frames=;avisplit=;channels=;vcustom=;acustom=;cpu=;interlaced=;mpegaspect=;intra_matrix=;inter_matrix=;fixavi=;mpeg=;crop=;audioid=;dvdaudiolang=;bframes=;firstchap=;lastchap=;dvdtrack=;addchapter=;cdi=;mpegfixaspect=;nowait=;vf=;frameres=;trick=;autocrop=;ac=;afm=;cache=;removecache=;turbo=;dvddev=;srate=;endpos=;fourcc=;menu=;menubg=;dvdtitle=;rotate=;menuvtsbg=;autosync=;telecine=;AFMT=;telesrc=;vcodec=;vrfyumnt=;burniso=;verify=;fixasync=;removedir=;MPGRES=;GOP=;TXTSUBOPT=;usespeed=;testmca=;chconf=;noodml=;pictsrc=;slideaudio=;audioonly=;norc= unset encsid encsdx encsla addsub addsdx addsla savecache txtsub txtsubopts zoom=0 scale=1 fast=1 MAXSTEP=6 # burn is the default step=$MAXSTEP split=0 vbitrate=16000 mpegmbr=0 overscan=0 iter=0 bakiter=0 hispeed=0 BGTITLE=1 TANIM=0 TFMT=png TMODE=0 TKFRM=0 TSECS=5 TPART=4 TPARTSEC=15 TFONTSIZE=1 TFONTBG=1 TLINES=2 TCPR=2 MENUERR=0 DVDPLAY=0 MENUOS=0 TSETB=1 DVDFS=1 VTSMBG=0 menufix=0 cdburndevice=0,0,0 dvdburndevice=/dev/cdrecorder fsize=;fint=;ffrac=;fpre=;audiosize=0 ASPECT=(1 1 4/3 16/9 2.21) CH6LIST=(l r ls rs c lfe) TOOL= MPEG2ENCOPT=;YUVSCALEROPT=;YUVDENOISE=;MPLEXOPT=;VCDIMAGEROPT=;DVDAUTHOROPT=;CDRDAOOPT=;GROWISOFSOPT=;MUSICINOPT= unset MPLAYEROPT MPLEXSTREAM MENCODEROPT LPCMPAR= SUBLANG= unset SUBTEXT AUDIOTEXT CHAPTERTEXT TITLESET EXTWAV PROFILE MSRC unset CLEAN DEBUG=0 LAVC= WARN= LOG= MAXFIX=20 timelen=0 ocrsub=0 slidefps=1 default_intra=8,16,19,22,26,27,29,34,16,16,22,24,27,29,34,37,19,22,26,27,29,34,34,38,22,22,26,27,29,34,37,40,22,26,27 default_intra=$default_intra,29,32,35,40,48,26,27,29,32,35,40,48,58,26,27,29,34,38,46,56,69,27,29,35,38,46,56,69,83 default_inter=16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16 default_inter=$default_inter,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16 hires_intra=8,16,18,20,24,25,26,30,16,16,20,23,25,26,30,30,18,20,22,24,26,28,29,31,20,21,23,24,26,28,31,31,21,23,24 hires_intra=$hires_intra,25,28,30,30,33,23,24,25,28,30,30,33,36,24,25,26,29,29,31,34,38,25,26,28,29,31,34,38,42 hires_inter=$default_inter kvcd_intra=8,9,12,22,26,27,29,34,9,10,14,26,27,29,34,37,12,14,18,27,29,34,37,38,22,26,27,31,36,37,38,40,26,27,29 kvcd_intra=$kvcd_intra,36,39,38,40,48,27,29,34,37,38,40,48,58,29,34,37,38,40,48,58,69,34,37,38,40,48,58,69,79 kvcd_inter=16,18,20,22,24,26,28,30,18,20,22,24,26,28,30,32,20,22,24,26,28,30,32,34,22,24,26,30,32,32,34,36,24,26 kvcd_inter=$kvcd_inter,28,32,34,34,36,38,26,28,30,32,34,36,38,40,28,30,32,34,36,38,42,42,30,32,34,36,38,40,42,44 tmpgenc_intra=8,16,19,22,26,27,29,34,16,16,22,24,27,29,34,37,19,22,26,27,29,34,34,38,22,22,26,27,29,34,37,40,22,26,27 tmpgenc_intra=$tmpgenc_intra,29,32,35,40,48,26,27,29,32,35,40,40,58,26,27,29,34,38,46,56,69,27,29,35,38,46,56,69,83 tmpgenc_inter=16,17,18,19,20,21,22,23,17,18,19,20,21,22,23,24,18,19,20,21,22,23,24,25,19,20,21,22,23,24,26,27,20,21,22 tmpgenc_inter=$tmpgenc_inter,23,25,26,27,28,21,22,23,24,26,27,28,30,22,23,24,26,27,28,30,31,23,24,25,27,28,30,31,33 TXTSUBDEF=( languageId nolang delay 0 font arial.ttf size 28 bottom-margin 30 characterset ISO8859-1 movie-height-reduction 0 fps default ) AVISUBDEF=( format SubViewer name-extension null fileformat unix version-number off delay 0 fps default suffix default ) #### encode2mpeglight defauls mpeg=1 encode=7:2:2 (($#)) || ! shortusage || exit 1 CMD=( "$@" ) #### options array MOPT=( $(mlistopt | grep -v -e : -e '*') $(mlistopt | sed -n '/:/s/:.*/"/p' | uniq) $(mplayer -vfhelp 2>&1 | awk '/vf-/{printf("\"%s\"\n",$1)}') $(mplayer -vophelp 2>&1 | awk '/vop-/{printf("\"%s\"\n",$1)}') $(mplayer -zrhelp 2>/dev/null | awk '$1~/^-zr/{printf("\"%s\"\n",substr($1,2))}') ) ############################################################################### #### check rc file ############################################################################### if [[ -s ~/.encode2mpegrc ]]; then for ((i=0;i<${#CMD[*]};i++)); do [[ ${CMD[i]} = -norc ]] && norc=1 && break done if [[ ! $norc ]] && ! awk '{if($1~"^#")exit 1}' ~/.encode2mpegrc ; then WARN="$WARN${WARN:+\n}++ WARN: [$PROGNAME] ~/.encode2mpegrc appears to contain comments, ignoring it" norc=1 fi [[ ! $norc ]] && set -- $(<~/.encode2mpegrc) "$@" fi ############################################################################### #### arguments parsing ############################################################################### while (($#)) ; do #### PARSING case $1 in -h|-help) #-list the available options [[ $2 = doc || $2 = help ]] && isarg $1 $2 shortusage exit ;; -l|-longhelp) #-print this help page [[ $2 = doc || $2 = help ]] && isarg $1 $2 usage exit ;; -doc|-documentation) #[[<browser>:][<html page>]] #-show the html documentation [[ $2 = doc || $2 = help ]] && isarg $1 $2 [[ ${2%:*} != $2 ]] && BROWSER=${2%:*} show_html ${2#*:} exit ;; -noshowlog) #-do not show the log file [[ $2 = doc || $2 = help ]] && isarg $1 $2 quiet=1 ;; -o|-output) #<filename> #-filename of the output stream echo "$2" | grep -q '/' && [[ ! -d ${2%/*} ]] && echo "**ERROR: [$PROGNAME] directory ${2%/*} argument of '$1' not found" && exit 1 output=$2 shift ;; -a) #<n> # aspect ratio VCD SVCD DVD # 1 - 1:1 x * x x = mpeg2enc and mencoder # 2 - 4:3 x x x * = mencoder only # 3 - 16:9 x x x #- 4 - 2.21:1 * x MPEG2ENCOPT="$MPEG2ENCOPT -a $2" [[ $2 -eq 0 ]] && MPEG2ENCOPT="${MPEG2ENCOPT% ${2}} 1" mpegaspect=$2 isarg $1 "$2" direct shift ;; -mpegfixaspect) #[pad|crop] # force the aspect ratio of the source video to match the one # specified with -a; this can be done padding the video with #-black lines or cropping the video; the default is padding [[ $2 = doc || $2 = help ]] && isarg $1 $2 aspect mpegfixaspect=0 if [[ $2 = pad || $2 = crop ]]; then [[ $2 = crop ]] && mpegfixaspect=1 shift fi ;; -rotate) #<0-3> # rotate the source video by 90 degrees; set -mpegfixaspect; # 0 rotate clockwise and flip, 1 rotate clockwise #-2 rotate counterclockwise, 3 rotate counterclockwise and flip rotate=1 echo "$2" | grep -q '^[0-3]$' && rotate=$2 isarg $1 "$2" aspect shift : ${mpegfixaspect:=0} ;; -overscan) #<n> # shrink the video of n% and surround it with black borders, # n can be 1-99, using 10 should make visible on a TV the full video # image; if n is negative, the result is a magnification of the # central part of the image; n>0 set -mpegfixaspect pad, n<0 set #--mpegfixaspect crop; in Avi Mode n can only be positive echo "$2" | grep -qE '^-?[0-9]?[0-9]$' && overscan=$2 [[ ${2:0:1} = - ]] && mpegfixaspect=1 || mpegfixaspect=0 isarg $1 "${2#-}" $( ((step==1)) && echo Avi || echo aspect) shift ;; -abr) #<n> #-audio bit rate of the VCD/SVCD/DVD [MP2:224,MP3:128,AC3:448] if [[ $2 = list ]]; then sed '/^check_abr/,/case/!d;/'"$audioformat"':/!d;/[^0-9]'"$asr"'/!d;s/[^)]*)//;s/ */ /g;s/^/'"$audioformat $asr"'/' "$PROGFILE" exit fi abr=$2 isarg $1 "$2" direct shift ;; -asr) #<n> #-audio sample rate of the VCD/SVCD/DVD [MP2/MP3:44100,AC3:48000] asr=$2 isarg $1 "$2" direct shift ;; -vbr) #<n> #-video bit rate of the VCD/SVCD/DVD [VCD:1152,SVCD:2500,DVD:7500] vbr=$2 isarg $1 "$2" direct shift ;; -vfr) #<n> # video frame rate of the output stream # [NTSC/VCD:4,NTSC/SVCD-DVD:1,PAL:3,AVI:2] # 1 - 24000.0/1001.0 (NTSC 3:2 pulldown converted FILM) # 2 - 24.0 (NATIVE FILM) # 3 - 25.0 (PAL/SECAM VIDEO / converted FILM) # 4 - 30000.0/1001.0 (NTSC VIDEO) # 5 - 30.0 # 6 - 50.0 (PAL FIELD RATE) # 7 - 60000.0/1001.0 (NTSC FIELD RATE) #- 8 - 60.0 vfr=$2 isarg $1 "$2" direct shift ;; -n|-video-norm) #<n|p|s> #-set the video norm of the VCD/SVCD/DVD case $2 in n|N|ntsc|NTSC) videonorm=n ;; p|P|pal|PAL) videonorm=p ;; s|S|secam|SECAM) videonorm=s ;; doc|help) isarg $1 $2 direct ;; *) echo "**ERROR: [$PROGNAME] invalid argument '$2' for option '$1'" ; "$PROGFILE" -norc $1 help ; exit 1 ;; esac shift ;; -p|-pulldown|-telecine) # # set a flag in the output stream of the SVCD/DVD that tell the # decoder to play the movie as NTSC video using "3:2 pull-down" #-instead of "-vfr 4" use "-vfr 1 -p" (smaller output stream) [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct telecine=1 ;; -res) #<1-7> # force one of the following video resolutios: # PAL NTSC # 1 352x288 352x240 (VCD) # 2 352x576 352x480 (CVD) # 3 480x576 480x480 (SVCD) # 4 528x576 528x480 (KVCD) # 5 544x576 544x480 (KVCD) # 6 704x576 704x480 (DVB) #- 7 720x576 720x480 (DVD) isarg $1 "$2" direct echo "$2" | grep -q '^[1-7]$' && MPGRES=$2 shift ;; -gop) #<n> # set the number of pictures per GOP; the default value is the one #-required by the standard isarg $1 "$2" direct GOP=$2 shift ;; -kvcd) #<1-4> # generate KVCD (www.kvcd.net) compliant frames on output; the # following resolutions are possible: # PAL NTSC GOP # 1 528x576 528x480 24 # 2 528x576 528x480 def # 3 544x576 544x480 24 #- 4 544x576 544x480 def isarg $1 "$2" direct a=1 echo "$2" | grep -q '^[1-4]$' && a=$2 shift 2 set -- " " -qmatrix kvcd -res $((3+(a+1)/2)) $([[ $a == [13] ]] && echo "-gop 24") "$@" ;; -vcd) # #-generate VCD compliant frames on output (default) [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct frameformat=VCD ;; -svcd) #[1-2] # generate SVCD compliant frames on output; the following resolutions # are possible: PAL NTSC # 1 480x576 480x480 # 2 352x288 352x240 #-default is 1 [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct frameformat=SVCD frameres=1 echo "$2" | grep -q '^[1-2]$' && frameres=$2 && shift ;; -svcdht) # # enable the VCD header trick; this trick could allow to play SVCD on # DVD player that does not support SVCD. For more details see: #-http://www.videohelp.com/svcd [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct trick=1 ;; -dvd) #[1-5] # generate DVD compliant frames on output; the following resolutions # are possible: PAL NTSC # 1 720x576 720x480 # 2 704x576 704x480 # 3 480x576 480x480 (non standard DVD-SVCD) # 4 352x576 352x480 # 5 352x288 352x240 #-default is 1 [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct frameformat=DVD frameres=1 echo "$2" | grep -q '^[1-5]$' && frameres=$2 && shift ;; -vcodec) #<mpeg1|mpeg2|mpeg4> #-force the selected video codec [VCD:mpeg1,SVCD-DVD:mpeg2,AVI:mpeg4] isarg $1 "$2" Avi [[ $2 == mpeg[124] ]] && vcodec=$2 && [[ ${vcodec:4:1} == [12] ]] && vcodec=${vcodec}video shift ;; -qmatrix) #<kvcd|tmpgenc|default|hi-res> # mpeg2enc custom quantization matrices: kvcd produce a smaller #-output stream, hi-res is good for hi-quality source material case $2 in kvcd|tmpgenc|default|hi-res) MPEG2ENCOPT="$MPEG2ENCOPT -K $2" intra_matrix=$(eval echo \$${2/-}_intra) inter_matrix=$(eval echo \$${2/-}_inter) ;; *) MPEG2ENCOPT="$MPEG2ENCOPT -K default" intra_matrix= inter_matrix= ;; esac isarg $1 "$2" direct shift ;; -mpeg1vbr) # # produce a VCD/MPEG-1 variable bit rate stream, the output stream # is smaller and a complete movie could fit in one VCD; check if #-your hardware player support variable bit rate VCD [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct MPEG2ENCOPT="$MPEG2ENCOPT -q 8" LAVC=":vrc_buf_size=327" ;; -mpegmbr) #<n> # set the maximum video bit rate; the default is the value of vbr; #-a value of 0 remove the limit mpegmbr=$2 [[ $2 -eq 0 ]] && mpegmbr= isarg $1 "$2" mpeg shift ;; -mpegchannels) #<1-6> # number of channels of the mpeg audio stream, 1-6 for ac3 and lpcm; # 1-2 for mp1, mp2 and mp3; 3-6 for mp2 Multichannel Audio; for the #-avi audio stream use MPlayer's option -channels mpegchannels=2 isarg $1 "$2" direct echo "$2" | grep -q '^[1-6]$' && mpegchannels=$2 shift ;; -normalize) #-normalize to the audio stream(s) [[ $2 = doc || $2 = help ]] && isarg $1 $2 $([[ $encode ]] && echo Avi || echo direct) normalize=1 ;; -volume) #<n> # change amplitude of the audio stream; less than 1.0 decreases, #-greater than 1.0 increases (float) volume=$2 isarg $1 "$2" direct shift ;; -noscale) # # encode2mpeg automatically scales the video according to the mpeg # profile chosen, this option disable this feature; used mainly #-for debug purpose [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct scale= ;; -monochrome) #-create B/W video or avoid color artifacts in B/W source streams [[ $2 = doc || $2 = help ]] && isarg $1 $2 direct YUVSCALEROPT="$YUVSCALEROPT -O MONOCHROME" ;; -split) #<n> #-split the resulting mpeg stream in <n> MB chunks. split=$2 isarg $1 "$2" direct shift ;; -encode) #<n:m:i[,b]> # the parameter n:m:i selects the audio codec, video codec options # and number of pass for mencoder, possible values are: # n m i # 0 copy 0 copy 1 # 1 pcm 1 libavcodec/mpeg 2 # 2 mp3lame/fast 2 as 1 + mbd=2 3 # 3 mp3lame/standard 3 as 1 + compression opts # 4 libavcodec/mp2 4 as 1 + quality opts # 5 libavcodec/mp3 # 6 libavcodec/ac3 for m=[2-4] and i>1 turbo is on # 7 toolame/mp2 #- with n=[3-7] b specify the audio bit rate encode=5:3:2 echo "$2" | grep -qE '^[0-7]:[0-4]:[1-9](,[0-9]+)?$' && encode=$2 isarg $1 "$2" $([[ $mpeg ]] && echo mpeg || echo Avi) shift ;; -telecinesrc) # # if you use -encode n:0:i in Mpeg Mode, encode2mpeg needs to know # if the source NTSC mpeg is telecined, otherwise the stream copy may # not work properly; normally encode2mpeg is able to detect telecined # sources, but, if the source mpeg is mixed, part not telecined and # part telecined, encode2mpeg may fail to detect it. In such case, #-you can use this option to specify a telecined source. [[ $2 = doc || $2 = help ]] && isarg $1 $2 mpeg telesrc=1 ;; -turbo) #<0-1> # disable (0) or force (1) turbo mode for the first pass of N pass #-encoding (N>1) echo "$2" | grep -q '^[0-1]$' && turbo=$2 isarg $1 "$2" Avi shift ;; -hispeed) # # increase the encoding speed of 25-50% (with -encode n:1:1); the # output video stream will be bigger and can have poor quality; this # option is mainly intented for testing, but it can be used if you #-want to create more quickly an mpeg4/avi or a DVD [[ $2 = doc || $2 = help ]] && isarg $1 $2 Avi hispeed=1 ;; -bframes) #<0-4> # specify the number of B frames; if -encode is n:3:i the default 2, #-otherwise the default is no B frames; for VCD the default is 2 echo "$2" | grep -q '^[0-4]$' && bframes=$2 isarg $1 "$2" Avi shift ;; -vcustom) #<libavcodec options> # specify a custom set of video options for libavcodec, use with #--encode n:1:i vcustom=$2 isarg $1 "$2" Avi shift ;; -acustom) #<mp3lame options> #-specify a custom set of lame options, use with -encode 2:m:i acustom=$2 isarg $1 "$2" Avi shift ;; -encsid) #<sid0,sid1,...> #-dump the DVD vobsub, sid is the number you give the -sid option # of MPlayer. encsid=( ${2//,/ } ) isarg $1 "$2" subtitle shift ;; -encsdx) #<sid0,sid1,...> # if you dump subtitle 2 and 4 and you want them to have id 0 and 1 #-use -encsid 2,4 -encsdx 0,1 encsdx=( ${2//,/ } ) isarg $1 "$2" subtitle shift ;; -encsla) #<sla0,sla1,...> #-see doc/html/subtitle.html encsla=( ${2//,/ } ) isarg $1 "$2" subtitle shift ;; -usespeed) # # do frame rate conversion changing the playback speed; this option # can be used if you are converting from NTSC 24fps, with or without # telecine, to PAL 25fps and viceversa; during normal frame rate # conversion, frames are skipped or duplicated as needed; with this #-option all the frames are encoded [[ $2 = doc || $2 = help ]] && isarg $1 $2 mpeg usespeed=1 ;; -usesbr) #[1-6|>100] # use the suggested video bitrate to set the output stream size # 1 - for 650MB CD 4 - for 2 x 650MB CD # 2 - for 700MB CD (default) 5 - for 2 x 700MB CD # 3 - for 800MB CD 6 - for 2 x 800MB CD # n where n > 100 will set the file size to n MB #-with -multiaudio you must to set the streamsize in MB usesbr=2 SBR=(650 700 800 "2 x 650" "2 x 700" "2 x 800") echo "$2" | grep -q '^[1-6]$' && usesbr=$2 && shift echo "$2" | grep -qE '^[1-9][0-9]{2,}$' && usesbr=$2 && shift [[ $2 = doc || $2 = help ]] && isarg $1 $2 Avi ;; -cpu) #<n> #-number of cpu to use, default all the cpu present in the system cpu=1 echo "$2" | grep -q '^[1-8]$' && cpu=$2 isarg $1 "$2" Avi shift ;; -interlaced) #-turn on optimization for interlaced source video. [[ $2 = doc || $2 = help ]] && isarg $1 $2 $([[ $mpeg ]] && echo mpeg || echo Avi) interlaced=1 ;; -slidefps) #<n> # fps to use when creating video from pictures, default is 1; if # there is a audio file associated with a picture, the duration of #-the audio file is used slidefps=$(awk -v a=$2 'BEGIN{printf("%.3f",1/a)}') isarg $1 "$2" images shift ;; -slideaudio) #<audio file> # use the content of <audio file> as audio stream when creating video #-from pictures; it works correctly only if used with mf://singlepic slideaudio=$2 if [[ ! -f $2 && $2 != /dev/null ]]; then [[ $2 = doc || $2 = help || ! $2 ]] && isarg $1 "$2" images || ! echo "**ERROR: [$PROGNAME] slide audio file '$2' not found" || exit 1 fi shift ;; -norc) #-do not use the settings in the file $HOME/.encode2mpegrc [[ $2 = doc || $2 = help ]] && isarg $1 $2 rc ;; -debug) # make a more verbose log file and creates a debug file; if you are # submitting a bug report, use this option and compress and send the #-log file and the debug file [[ $2 = doc || $2 = help ]] && isarg $1 $2 ((DEBUG)) && DEBUG=2 || DEBUG=1 ;; (-frames) frames=$2 isarg $1 $2 shift ;; (-channels) channels=$2 isarg $1 $2 shift ;; (-srate) MPLAYEROPT=( "${MPLAYEROPT[@]}" -srate $2 -af-adv force=1 ) srate=$2 isarg $1 $2 shift ;; (-endpos) endpos=$2 isarg $1 $2 shift ;; (-hr-edl-seek) MENCODEROPT=( "${MENCODEROPT[@]}" $1 ) ;; (-vf) vf="-vf $2" MPLAYEROPT=( "${MPLAYEROPT[@]}" $vf ) isarg $1 $2 shift ;; (-dvd-device) dvddev=$2 isarg $1 $2 shift ;; (mf://*) MPLAYEROPT[${#MPLAYEROPT[*]}]=$1 pictsrc=1 a=$IFS IFS=, PICTSRC=( ${1#mf://} ) IFS=$a srate=48000 ;; (-mpeg|-mpegonly|-nosplit) ;; *) if [[ ! $TOOL ]]; then [[ ${1:0:1} = - ]] && ! echo "${MOPT[@]}" | grep -q "\"${1#-}\"" && \ echo -e "Unknown option $1\nIf this is a valid MPlayer option add '-toolopts mplayer' in front of it" && exit 1 MPLAYEROPT[${#MPLAYEROPT[*]}]=$1 else case $TOOL in *) MPLAYEROPT[${#MPLAYEROPT[*]}]=$1 ;; esac fi ;; esac shift done [[ -s ~/.encode2mpegrc && ! $norc ]] && pre_log " INFO: [$PROGNAME] using .encode2mpegrc settings: '$(<~/.encode2mpegrc)'" ############################################################################### #### redirect stdout and stderr to the debug file ############################################################################### if ((DEBUG)); then exec 3>&1 rm -f "$output".debug.fifo mkfifo "$output".debug.fifo tee "$output".debug <"$output".debug.fifo >&3 & PROCTEE=$! exec &>"$output".debug.fifo ((DEBUG==2)) && set -x fi ############################################################################### #### ERROR if some options conflict is detected part 1/2 ############################################################################### #### mplayer/mencoder for a in mplayer mencoder ; do type $a &>/dev/null || ! echo "**ERROR: [$PROGNAME] $a missing, install $(echo ${a:0:2} | tr '[:lower:]' '[:upper:]')${a:2}" || exit 1 done #### output stream name check [[ ! $output ]] && echo "**ERROR: [$PROGNAME] name of the output stream missing (-o name)" && exit 1 #### unspecified video norm [[ ! $videonorm && step -gt 1 && ! ( $mpeg && ${encode%,*} == ?:0:? && ! $menu ) ]] && \ echo "**ERROR: [$PROGNAME] you must specify a video norm (-n n|p|s)" && exit 1 #### pictsrc if [[ $pictsrc ]]; then [[ $slideaudio != /dev/null && ${encode%,*} == 0:?:? && $mpeg ]] && \ echo "**ERROR: [$PROGNAME] -encode 0:m:i is not compatible with mf:// in Mpeg Mode" && exit 1 [[ $audioonly ]] && echo "**ERROR: [$PROGNAME] -audioonly does not work with mf://" && exit 1 fi #### -encode 1:m:i is not allowed [[ ${encode%,*} == 1:?:? ]] && echo "**ERROR: [$PROGNAME] do not use -encode 1:m:i" && exit 1 ############################################################################### #### WARN if some options conflict is detected ############################################################################### #### missing toolame support if [[ ${encode%,*} == 7:?:? ]]; then if ! mencoder -oac help 2>/dev/null | grep -q toolame ; then encode=4:${encode#?:} pre_log "++ WARN: [$PROGNAME] missing toolame support in mencoder, setting -encode $encode" fi fi ############################################################################### #### set default values for unspecified parameters ############################################################################### if [[ ! $multiaudio ]]; then audiostream=1 fi ############################################################################### if [[ $encode ]]; then case ${encode%%:*} in 0) [[ ! $pictsrc ]] && AFMT=acopy ;; 2|3|5) AFMT=mp3 ;; 4|7) AFMT=mp2 ;; 6) AFMT=ac3 ;; esac [[ $AFMT ]] && eval : ${audioformat:-\${$AFMT:=copy}} fi : ${frameformat:=VCD} : ${audioformat:=${AFMT:-mp2}} : ${mp1:=mp2enc} ((${mpegchannels:-2}>2)) && : ${mp2:=musicin} || : ${mp2:=mp2enc} : ${mp3:=lame} : ${ac3:=mencoder} : ${dts:=copy} case $audioformat in mp1) case ${mpegchannels:-2} in 1) : ${abr:=192} ;; 2) : ${abr:=384} ;; esac ;; mp2) case ${mpegchannels:-2} in 1) : ${abr:=112} ;; 2) : ${abr:=224} ;; [3-6]) : ${abr:=384} ;; esac ;; mp3) case ${mpegchannels:-2} in 1) : ${abr:=64} ;; 2) : ${abr:=128} ;; esac ;; ac3) case ${mpegchannels:-2} in 1) : ${abr:=96} ;; 2) : ${abr:=192} ;; 3) : ${abr:=320} ;; # to verify 4) : ${abr:=384} ;; # to verify 5) : ${abr:=448} ;; # to verify 6) : ${abr:=448} ;; esac ;; #### mplex fails with asr != 48000 for lpcm lpcm) : ${asr:=48000} ${abr:=$((asr*16*${mpegchannels:-2}/1024))} ;; esac if [[ ${encode%,*} == 0:?:? && ${!audioformat} = copy ]]; then abr=0 if [[ ! $multiaudio ]]; then get_abr fi fi [[ $mpeg && ${encode%,*} == ?:0:? ]] && \ vbr=$(($(mp_identify "${MPLAYEROPT[@]}" ${dvddev:+-dvd-device "$dvddev"} "$@" | grep '^ID_VIDEO_BITRATE' | cut -f2 -d=)/1000)) case $frameformat in DVD) : ${asr:=48000} ;; *) : ${asr:=44100} ;; esac case $videonorm in p|s) : ${vfr:=3} ;; n) #FIXME remove the encode 3 check once the mpeg muxer is fixed [[ $frameformat != VCD && ! $vfr && $hispeed -eq 0 && ! $testmca && ${encode%,*} != ?:3:? ]] && vfr=1 && telecine=1 : ${vfr:=4} ;; esac [[ $encode ]] && : ${vfr:=2} if [[ ! $ofps ]]; then case $vfr in 1) ofps=24000/1001 ;; 2) ofps=24 ;; 3) ofps=25 ;; 4) ofps=30000/1001 ;; 5) ofps=30 ;; 6) ofps=50 ;; 7) ofps=60000/1001 ;; 8) ofps=60 ;; esac fi if [[ $split && $split -eq 0 ]]; then [[ $mpeg ]] && split= || split=800 fi ############################################################################### #### get MPlayer version ############################################################################### mver=$(mencoder 2>/dev/null | awk '$1=="MEncoder"{print $2;exit}') ############################################################################### #### threads check ############################################################################### if [[ ! $cpu && -f /proc/cpuinfo ]]; then cpu=$(grep -c ^processor /proc/cpuinfo) #### if there are 2 logical cpu but 1 physical (hyperthreading) #### use only one thread. With kernel 2.4.x it is more efficent. ((cpu==2)) && [[ $(uname -r | cut -f 1-2 -d .) = 2.4 ]] && \ [[ $(grep ^siblings /proc/cpuinfo | uniq | wc -l) -eq 1 ]] && \ cpu=$((cpu/$(grep ^siblings /proc/cpuinfo | uniq | awk 'END{print $NF}'))) fi ((cpu<2)) && cpu= ############################################################################### #### -ao pcm arguments ############################################################################### PCM=(pcm:waveheader:file="$output".wav) PCMTMP=(pcm:waveheader:file="$output".tmp) PCMNOWYUV=(pcm:nowaveheader:file=/dev/fd/4) [[ $dvddev ]] && MPLAYEROPT=( "${MPLAYEROPT[@]}" -dvd-device "$dvddev" ) ############################################################################### #### mplayer/mencoder/mjpegtools options ############################################################################### #### mencoder output suffix if [[ $encode ]]; then [[ $mpeg ]] && SUF=mpeg || SUF=avi fi #### MPLAYERINFO is used for [info] MPLAYERINFO=( "${MPLAYEROPT[@]}" ) #### mf:// case if [[ $pictsrc ]]; then if [[ $slideaudio && $slideaudio != /dev/null ]]; then [[ $(mp_identify "$slideaudio" | grep ID_AUDIO_RATE | cut -f2 -d=) != $asr ]] && SRATE="-srate $asr -af-adv force=1" || SRATE= CLEAN[${#CLEAN[*]}]="$output".wav mplayer "$slideaudio" $SRATE -vo null -vc dummy -ao "${PCM[@]}" $VOL $ac $afm ${mpegchannels:+-channels $mpegchannels -af channels=$mpegchannels} MPLAYEROPT=( "${MPLAYEROPT[@]}" -fps 1/$(mp_identify "$output".wav | sed -n '/^ID_LENGTH=/s/.*=//p') -audiofile "$output".wav ) else if [[ $slideaudio == /dev/null ]]; then MPLAYEROPT=( "${MPLAYEROPT[@]}" -fps $slidefps ) encode=0:${encode#?:} else MPLAYEROPT=( "${MPLAYEROPT[@]}" -fps $slidefps -audiofile /dev/zero -audio-demuxer 20 -rawaudio format=0x1:rate=48000 ) fi fi fi #### MENCODERARG is used for mencoding, vobsub dumping MENCODERARG=( "${MPLAYEROPT[@]}" ${frames:+-frames $frames} ) MENCODERARG=( "${MENCODERARG[@]}" "${MENCODEROPT[@]}" ${endpos:+-endpos $endpos} ) if [[ $mpeg && $mpegchannels ]]; then MENCODERARG=( "${MENCODERARG[@]}" -channels $mpegchannels ) else MENCODERARG=( "${MENCODERARG[@]}" ${channels:+-channels $channels} ) fi #### if video copy then no ofps [[ ${encode%,*} != ?:0:? ]] && MENCODERARG=( "${MENCODERARG[@]}" ${ofps:+-ofps $ofps} ) YUVSCALEROPT="-v 1 -n $videonorm ${scale:+-O $frameformat} $YUVSCALEROPT" MPEG2ENCOPT="${cpu:+-M $cpu }-v 1 -S ${split:-50000} -n $videonorm -F $vfr -s -r 16 ${telecine:+-p} $MPEG2ENCOPT" case $vfr in 1|2) MPEG2ENCOPT="-g 6 -G ${GOP:-12} $MPEG2ENCOPT" ;; 3|6) MPEG2ENCOPT="-g 6 -G ${GOP:-15} $MPEG2ENCOPT" ;; 4|5|7|8) MPEG2ENCOPT="-g 9 -G ${GOP:-18} $MPEG2ENCOPT" ;; esac [[ $frameformat = VCD ]] && MPEG2ENCOPT="-R 2 $MPEG2ENCOPT" echo "$MPEG2ENCOPT" | grep -q -e '-K hi-res' && YUVSCALEROPT="-M BICUBIC $YUVSCALEROPT" && \ MPEG2ENCOPT="-4 1 -2 1 $MPEG2ENCOPT" || MPEG2ENCOPT="-4 2 -2 1 $MPEG2ENCOPT" case $frameformat in VCD) MPGRES=${MPGRES:-1} ;; SVCD) case $frameres in 1) MPGRES=${MPGRES:-3} ;; 2) MPGRES=${MPGRES:-1} ;; esac ;; DVD) case $frameres in 1) MPGRES=${MPGRES:-7} ;; 2) MPGRES=${MPGRES:-6} ;; 3) MPGRES=${MPGRES:-3} ;; 4) MPGRES=${MPGRES:-2} ;; 5) MPGRES=${MPGRES:-1} ;; esac ;; esac case $MPGRES in 1) H_RES=352 ; [[ $videonorm = n ]] && V_RES=240 || V_RES=288 ;; 2) H_RES=352 ; [[ $videonorm = n ]] && V_RES=480 || V_RES=576 ;; 3) H_RES=480 ; [[ $videonorm = n ]] && V_RES=480 || V_RES=576 ;; 4) H_RES=528 ; [[ $videonorm = n ]] && V_RES=480 || V_RES=576 ;; 5) H_RES=544 ; [[ $videonorm = n ]] && V_RES=480 || V_RES=576 ;; 6) H_RES=704 ; [[ $videonorm = n ]] && V_RES=480 || V_RES=576 ;; 7) H_RES=720 ; [[ $videonorm = n ]] && V_RES=480 || V_RES=576 ;; esac case $frameformat in VCD) : ${vbr:=1152} MPEG2ENCOPT="-f 2 -b $vbr -V 46 -B $(((abr*audiostream*101875-vbr*2819+3980000)/100000)) $MPEG2ENCOPT" MPLEXOPT="-f 2 -V -b 46 -r $(((abr*audiostream+vbr)*4)) $MPLEXOPT" VCDIMAGEROPT="-t vcd2 $VCDIMAGEROPT" H_STILL=704 [[ $videonorm = n ]] && V_STILL=480 || V_STILL=576 ((MPGRES!=1)) && YUVSCALEROPT="-O SIZE_${H_RES}x${V_RES} ${YUVSCALEROPT/ -O $frameformat}" MAXBR=1394 ;; SVCD) : ${vbr:=2500} MPEG2ENCOPT="-f 5 -b $vbr -V 113 -B $(((abr*audiostream*101250+vbr*742+1665400)/100000)) $MPEG2ENCOPT" MPLEXOPT="-V -b 113 -r $(((abr*audiostream+vbr)*4)) $MPLEXOPT" if [[ $trick ]]; then MPLEXOPT="-f 2 $MPLEXOPT" VCDIMAGEROPT="-t vcd2 $VCDIMAGEROPT" else MPLEXOPT="-f 5 $MPLEXOPT" VCDIMAGEROPT="-t svcd $VCDIMAGEROPT" fi H_STILL=704 [[ $videonorm = n ]] && V_STILL=480 || V_STILL=576 ((frameres>1||MPGRES!=3)) && YUVSCALEROPT="-O SIZE_${H_RES}x${V_RES} ${YUVSCALEROPT/ -O $frameformat}" MAXBR=2778 ;; DVD) : ${vbr:=7500} MPEG2ENCOPT="-f 8 -b $vbr -V 230 -B $(((abr*audiostream*101250+vbr*742+1665400)/100000)) $MPEG2ENCOPT" MPLEXOPT="-f 8 -V -b 230 -r $(((abr*audiostream+vbr)*4)) $MPLEXOPT" H_STILL=720 [[ $videonorm = n ]] && V_STILL=480 || V_STILL=576 ((frameres>1||MPGRES!=7)) && YUVSCALEROPT="-O SIZE_${H_RES}x${V_RES} ${YUVSCALEROPT/ -O $frameformat}" MAXBR=10080 ;; esac ############################################################################### #### mencoder audio/video/pass options ############################################################################### if [[ $encode ]]; then OPTIONS="-noskiplimit -sws $((hispeed?1:7))" if [[ $mpeg ]]; then # mencoder can put in the mpeg container: # video: mpeg1, mpeg2, mpeg4 # audio: mp1, mp2, mp3, ac3, aac (not yet: lpcm, dts) [[ ${encode%,*} != ?:0:? ]] && : ${mpegaspect:=2} #MUX="-mpegopts ${mpegaspect:+vaspect=${ASPECT[mpegaspect]}:}:vbitrate=${vbr}" MUX="-mpegopts ${mpegaspect:+vaspect=${ASPECT[mpegaspect]}:}" MUX2="${telecine:+:telecine}" case $frameformat in VCD) MUX="${MUX}format=xvcd" LAVC="vcodec=${vcodec:-mpeg1video}${LAVC:-:vrc_buf_size=327:vrc_minrate=${vbr}:vrc_maxrate=${vbr}}" ;; SVCD) if [[ $trick ]]; then MUX="${MUX}format=xvcd" ; else MUX="${MUX}format=xsvcd" ; fi ; LAVC="vcodec=${vcodec:-mpeg2video}:vrc_buf_size=917" ;; DVD) MUX="${MUX}format=dvd" LAVC="vcodec=${vcodec:-mpeg2video}:vrc_buf_size=1835" ;; esac case $vfr in 1|2) LAVC="$LAVC:keyint=$((hispeed?1:${GOP:-12}))" ;; 3|6) LAVC="$LAVC:keyint=$((hispeed?1:${GOP:-15}))" ;; 4|5|7|8) LAVC="$LAVC:keyint=$((hispeed?1:${GOP:-18}))" ;; esac [[ $frameformat = VCD && ! $bframes ]] && LAVC="$LAVC:vmax_b_frames=2" [[ $mpegmbr ]] && [[ $mpegmbr -lt $vbr ]] && mpegmbr=$vbr #### -a 1 really means aspect undefined (do not scale), not aspect 1:1 [[ $vcodec != mpeg4 || $mpegaspect != 1 ]] && LAVC="${LAVC}:aspect=${ASPECT[mpegaspect]}" LAVC="${LAVC}${mpegmbr:+:vrc_maxrate=$mpegmbr}${inter_matrix:+:inter_matrix=${inter_matrix}}${intra_matrix:+:intra_matrix=${intra_matrix}}" OF="-of mpeg" NOSKIP=-noskip vbitrate=$vbr if [[ ${encode%,*} != ?:0:? ]]; then for ((a=0;a<${#MENCODERARG[*]};a++)); do while [[ ${MENCODERARG[a]} = -vf ]]; do unset MENCODERARG[a] MENCODERARG[a+1] MENCODERARG=( "${MENCODERARG[@]}" ) done done MENCODERARG=( "${MENCODERARG[@]}" ${vf:--vf }${vf:+,}${scale:+scale=${H_RES}:${V_RES}${interlaced:+:1},}harddup ) fi fi BASIC="$LAVC:vbitrate=${vbitrate}${cpu:+:threads=$cpu}${bframes:+:vmax_b_frames=$bframes}" ((hispeed)) && BASIC="$BASIC:vme=0" || BASIC="$BASIC:psnr" [[ $mpeg && $frameformat = VCD ]] || BASIC="$BASIC${interlaced:+:ildct:ilme}" echo "$YUVSCALEROPT" | grep -q -e '-O MONOCHROME' && BASIC="$BASIC:gray" HQ="${BASIC}:mbd=2" if [[ $mpeg ]]; then #### dia=6 could be added BESTSIZE="${BASIC}:mbd=1:loop:mv0:vlelim=-4:vcelim=7:trell:precmp=1:cmp=1:subcmp=1" [[ ! $bframes ]] && BESTSIZE="$BESTSIZE:vmax_b_frames=2" #### last_pred=1-2 could be added BESTQUALITY="${BASIC}:mbd=2:mv0:precmp=6:cmp=6:subcmp=6" [[ $vbitrate -ge 3500 && $frameformat != VCD && $vcodec != mpeg1video ]] && BESTQUALITY="$BESTQUALITY:dc=9" fi case $encode in 0:?:?|0:?:?,*) AUDIOPASS="-oac copy" ;; 1:?:?|1:?:?,*) AUDIOPASS="-oac pcm" ;; 2:?:?|2:?:?,*) AUDIOPASS="-oac mp3lame -lameopts ${acustom:-fast}" ;; 3:?:?) AUDIOPASS="-oac mp3lame -lameopts preset=standard" ;; 4:?:?) AUDIOPASS="-oac lavc -lavcopts acodec=mp2:abitrate=$abr" ;; 5:?:?) AUDIOPASS="-oac lavc -lavcopts acodec=mp3:abitrate=$abr" ;; 6:?:?) AUDIOPASS="-oac lavc -lavcopts acodec=ac3:abitrate=$abr" ;; 7:?:?) AUDIOPASS="-oac toolame -toolameopts br=$abr" ;; 3:?:?,*) AUDIOPASS="-oac mp3lame -lameopts preset=${encode#*,}" ;; 4:?:?,*) AUDIOPASS="-oac lavc -lavcopts acodec=mp2:abitrate=${encode#*,}" ;; 5:?:?,*) AUDIOPASS="-oac lavc -lavcopts acodec=mp3:abitrate=${encode#*,}" ;; 6:?:?,*) AUDIOPASS="-oac lavc -lavcopts acodec=ac3:abitrate=${encode#*,}" ;; 7:?:?,*) AUDIOPASS="-oac toolame -toolameopts br=${encode#*,}" ;; esac encode=${encode%,*} case $encode in ?:0:?) VIDEOPASS="$OF $MUX -ovc copy $NOSKIP" ; encode=${encode%%:*}:0:1 ; turbo=0 ;; # copy uses only one pass ?:1:?) VIDEOPASS="$OF $MUX$MUX2 -ovc lavc -lavcopts ${BASIC}${vcustom:+:$vcustom}" ; : ${turbo:=0} ;; ?:2:?) VIDEOPASS="$OF $MUX$MUX2 -ovc lavc -lavcopts ${HQ}" ; : ${turbo:=1} ;; ?:3:?) VIDEOPASS="$OF $MUX$MUX2 -ovc lavc -lavcopts ${BESTSIZE}" ; : ${turbo:=1} ;; ?:4:?) VIDEOPASS="$OF $MUX$MUX2 -ovc lavc -lavcopts ${BESTQUALITY}" ; : ${turbo:=1} ;; esac ((turbo)) && turbo=:turbo || turbo= PASS=${encode##*:} [[ $normalize && $encode != 0:?:? ]] && AUDIOPASS="-af volnorm $AUDIOPASS" fi ############################################################################### #### more functions ############################################################################### status_bit () { local a case $1 in avi) bit=0 ;; mpv) bit=1 ;; mpa) bit=2 ;; mpg) bit=3 ;; img) bit=4 ;; sub) bit=5 ;; ach) bit=6 ;; fno) bit=7 ;; ch0) bit=8 ;; sbm) bit=9 ;; spl) bit=10 ;; esac if [[ $2 = set ]]; then skip=$((skip|1<<bit)) else return $(((skip&1<<bit) && 1)) fi } ############################################################################### file_size () { #fsize,fint,ffrac,fpre local -a PRE=([1]=K M G T) local i=0 fsize=$(ls -l "$1" | awk '{print $5}') fint=$fsize ffrac=0 while ((fint>=1024)) ; do ((fint/1024 < 1024)) && fint=$((fint+51)) i=$((++i)) ffrac=$((fint%1024)) fint=$((fint/1024)) done ffrac=$((ffrac*10/1024)) fpre=${PRE[i]} } ############################################################################### show_file_info () { file_size "$2" echo " $1: $2 is $fsize bytes, $fint.$ffrac ${fpre}B" >>"$output".log } ############################################################################### show_finalvideo_info () { local codec TYPE i VIDEO OUT ASPECT VIDEO="$(mplayer -nocache -frames 0 -vo null -nosound "$2" 2>/dev/null | grep "^VIDEO:")" if [[ ! $VIDEO ]]; then # mpegs with mpeg4 video do not show all the video informations in one line, # assebmling the informations (kbps is missing): OUT="$(mplayer -nocache -frames 1 -vo null -nosound -v "$2" 2>/dev/null)" if echo "$OUT" | grep -q '^\[V].*fourcc:0x10000004' ; then VIDEO="VIDEO: MPEG4 $(echo "$OUT" | awk '$1=="VO:"&&$2=="[null]"{print $3}')" ASPECT=$(echo "$OUT" | awk '$1=="Movie-Aspect"{print $3}') case $ASPECT in undefined) VIDEO="$VIDEO (aspect 1)" ;; 1.33:1) VIDEO="$VIDEO (aspect 2)" ;; 1.78:1) VIDEO="$VIDEO (aspect 3)" ;; 2.21:1) VIDEO="$VIDEO (aspect 4)" ;; *) VIDEO="$VIDEO (aspect $ASPECT)" ;; esac VIDEO="$VIDEO $(echo "$OUT" | awk '$1=="[V]"{print $5}')" fi fi echo " $1: $VIDEO" >>"$output".log #### removed -vc dummy for i in $(mplayer -vo null -ao null -nocache -frames 1 -v "$2" 2>/dev/null | awk '/==> Found audio str/{print $NF}' | sort -n) ; do echo -n " $1: AUDIO[$i]: " >>"$output".log codec=$(mplayer -ac mp3, -nocache -frames 0 -v -ao null -vo null "$2" -aid $i 2>/dev/null | sed '/Selected audio codec:/!d;s/[^(]*(//;s/).*//;s/.* //') mplayer -ac mp3, -nocache -frames 0 -v -ao null -vo null "$2" -aid $i 2>/dev/null | sed '/^Opening audio decode/,/^AUDIO:/!d;s/\r//g' | \ grep -e '^AC3:' -e '^MPEG' -e '^AUDIO:' | sed 's/AUDIO/'"$codec"'/;q' >>"$output".log done TYPE=$1 shift for i ; do show_file_info "$TYPE" "$i" done } ############################################################################### video_duration () { mencoder "$@" -ovc copy -nosound -o /dev/null -quiet 2>&1 | awk '/^Video stream:/{print $10+$10/$12}' } ############################################################################### job_exit () { EXIT=$? status_bit mpg || [[ ! -f ${output}.mpg && ! -f ${output}01.mpg ]] || show_finalvideo_info "MPEG" "${output}"*.mpg sec=$(($(pr_time)-STARTTIME)) echo " JOBEND: $output $(pr_date) ($((sec/3600))h$((sec/60%60))m$((sec%60))s)" >>"$output".log rm -f "${CLEAN[@]}" psnr_??????.log ((DEBUG)) && exec >&1- >&2- && exec >&3 if [[ -f $output.yuvscaler.log || -f $output.mpeg2enc.log ]]; then echo else ((!EXIT)) && [[ ! $quiet ]] && cat "$output".log fi ((DEBUG)) && rm -f "$output".debug.fifo && kill $PROCTEE } ############################################################################### mplayer_log () { tee -a /dev/stderr | sed 's/.*\r//' | \ awk '/^PSNR:|^M[EP][ln]|^There are |^\[open]|^==> |^Recommended video bitrate/{sub(/^/," INFO: ['"$1"'] ");print}' >>"$output".log } ############################################################################### mp_single_log () { tee -a /dev/stderr | sed 's/.*\r//;/'"$2"'/!d;s/^/ INFO: ['$1'] /' >>"$output".log } ############################################################################### check_abr () { # abr permitted: # ac3: ( 8000/11025/12000) 8 16 24 32 40 48 56 64 80 96 112 128 144 160 # ac3: (16000/22050/24000) 16 24 32 40 48 56 64 80 96 112 128 160 192 224 256 288 320 # ac3: (32000/44100/48000) 32 40 48 56 64 80 96 112 128 160 192 224 256 320 384 448 512 576 640 # mp3: ( 8000/11025/12000) 8 16 24 32 40 48 56 64 80 96 112 128 144 160 # mp3: (16000/22050/24000) 8 16 24 32 40 48 56 64 80 96 112 128 144 160 # mp3: (32000/44100/48000) 32 40 48 56 64 80 96 112 128 160 192 224 256 320 # mp2: ( 8000/11025/12000) # mp2: (16000/22050/24000) 8 16 24 32 40 48 56 64 80 96 112 128 144 160 # mp2: (32000/44100/48000) 32 48 56 64 80 96 112 128 160 192 224 256 320 384 # mp1: ( 8000/11025/12000) # mp1: (16000/22050/24000) 32 48 56 64 80 96 112 128 144 160 176 192 224 256 # mp1: (32000/44100/48000) 32 64 96 128 160 192 224 256 288 320 352 384 416 448 case $1 in ac3) case $2 in 8000|11025|12000) case $3 in 8|16|24|32|40|48|56|64|80|96|112|128|144|160) : ;; *) return 1 ;; esac ;; 16000|22050|24000) case $3 in 16|24|32|40|48|56|64|80|96|112|128|160|192|224|256|288|320) : ;; *) return 1 ;; esac ;; 32000|44100|48000) case $3 in 32|40|48|56|64|80|96|112|128|160|192|224|256|320|384|448|512|576|640) : ;; *) return 1 ;; esac ;; *) return 1 ;; esac ;; mp3) case $2 in 8000|11025|12000|16000|22050|24000) case $3 in 8|16|24|32|40|48|56|64|80|96|112|128|144|160) : ;; *) return 1 ;; esac ;; 32000|44100|48000) case $3 in 32|40|48|56|64|80|96|112|128|160|192|224|256|320) : ;; *) return 1 ;; esac ;; *) return 1 ;; esac ;; mp2) case $2 in 16000|22050|24000) case $3 in 8|16|24|32|40|48|56|64|80|96|112|128|144|160) : ;; *) return 1 ;; esac ;; 32000|44100|48000) case $3 in 32|48|56|64|80|96|112|128|160|192|224|256|320|384) : ;; *) return 1 ;; esac ;; *) return 1 ;; esac ;; mp1) case $2 in 16000|22050|24000) case $3 in 32|48|56|64|80|96|112|128|144|160|176|192|224|256) : ;; *) return 1 ;; esac ;; 32000|44100|48000) case $3 in 32|64|96|128|160|192|224|256|288|320|352|384|416|448) : ;; *) return 1 ;; esac ;; *) return 1 ;; esac ;; *) return 1 ;; esac } ############################################################################### debug_line () { echo "--DEBUG: [$PROGNAME] $2($1) $(eval echo $(sed -n $1p "$PROGFILE" | sed 's/ |.*//;s/.>.*//;s/</\\\</'))" >>"$output".log } ############################################################################### check_mencoder_abr () { local codec lib ASR codec=([4]=mp2 mp3 ac3 mp2) lib=([4]=libavcodec libavcodec libavcodec libtoolame) ASR=${encode%%:*} check_abr ${codec[ASR]} $1 $2 || ! echo "**ERROR: [$PROGNAME] ${lib[ASR]} does not support $2 kbps / $1 Hz for ${codec[ASR]}" || exit 1 } ############################################################################### #### ERROR if some options conflict is detected part 2/2 ############################################################################### #### libavcodec codec/asr/abr #### libtoolame asr/abr #### libmp3lame asr #### no check is done on the other channel in case of multiaudio if [[ $encode == [2-7]:?:? ]]; then if [[ $srate ]]; then r=$srate else r=$(mp_identify "${MPLAYERINFO[@]}" | sed -n '/^ID_AUDIO_RATE=/s/.*=//p') if [[ $mpeg && ! $usespeed ]]; then case $frameformat in *VCD) ((r != 44100)) && pre_log "++ WARN: [$PROGNAME] $frameformat standard requires 44100kHz audio, add -srate 44100" ;; DVD) ((r != 48000)) && pre_log "++ WARN: [$PROGNAME] $frameformat standard requires 48000kHz audio, add -srate 48000" ;; esac fi fi if [[ $encode == [4-7]:?:? ]]; then check_mencoder_abr $r ${AUDIOPASS##*=} else case $r in 8000|11025|12000|16000|22050|24000|32000|44100|48000) : ;; *) echo "**ERROR: [$PROGNAME] libmp3lame does not support $r Hz sample rate" ; exit 1 ;; esac fi fi #### copy of non mpeg audio in a VCD if [[ $step -gt 1 && $frameformat = VCD && $encode == 0:?:? && ( $mpeg || ${!audioformat} = copy ) && ! $testmca && ! $pictsrc ]]; then a=$(mp_identify "${MPLAYERINFO[@]}" | sed -n '/^ID_AUDIO_CODEC=/s/.*=//p') [[ $a != mp3 ]] && echo "**ERROR: [$PROGNAME] you cannot copy $a audio in a $frameformat" && exit 1 fi #### mpegchannels > 2 only with ac3 [[ $mpeg && ${mpegchannels:-2} -gt 2 && $encode == [2-57]:?:? ]] && CODEC=([2]=mp3 mp3 mp2 mp3 [7]=mp2) && \ echo "**ERROR: [$PROGNAME] audio codec ${CODEC[${encode%%:*}]} selected with -encode $encode do not support more than 2 audio channels" && exit 1 ############################################################################### #### set cleanup ############################################################################### trap 'job_exit' 0 CLEAN[${#CLEAN[*]}]="$output".fifo skip=0 ############################################################################### #### start the log file ############################################################################### if [[ ! $resume ]] ; then { if [[ $LOG ]]; then echo "$LOG" else STARTTIME=$(pr_time) echo "### LOG: $output $(pr_date)" fi echo -n " INFO: [$PROGNAME] version $VERSION running in " if ((${#TITLESET[*]})); then echo -n "Titleset Mode" else if [[ $mpeg ]]; then [[ $testmca ]] && echo -n "Testmca Mode" || echo -n "Mpeg Mode" fi fi echo "${cpu:+ (cpu=$cpu)}" echo " INFO: [$PROGNAME] command line: '${CMD[@]}'" } >"$output".log fi ############################################################################### #### WARNING if some requested tools are missing and can be replaced ############################################################################### #### WARN if [[ $WARN ]]; then echo -e "$WARN" >>"$output".log fi #### volume and audio copy if [[ $volume ]]; then [[ $encode == 0:?:? && ( ${!audioformat} = copy || $step -eq 1 || $mpeg ) || ${!audioformat} = copy && ! $encode ]] && \ echo "++ WARN: [$PROGNAME] you cannot modify the volume of the output audio stream if you are making a copy the input audio stream" | \ tee -a "$output".log fi #### cpu and bframes if [[ $cpu && $bframes ]]; then ((bframes)) && echo "++ WARN: [$PROGNAME] with bframes>0 the encoding will be faster with cpu=1" | tee -a "$output".log fi #### -usespeed if [[ $usespeed && ( $encode == 0:?:? || $encode == ?:0:? ) ]]; then echo -en "++ WARN: [$PROGNAME] -usespeed may not work if you do not encode both audio and video.\nPress return to proceed" | tee -a "$output".log && read fi #### total br [[ $encode != ?:0:? ]] && ((step>1&&abr*audiostream*1024/1000+vbr>MAXBR)) && \ echo "++ WARN: [$PROGNAME] total video+audio bitrate ($vbr+$((abr*audiostream*1024/1000))kbps) exceed $frameformat specifications (${MAXBR}kbps)" | \ tee -a "$output".log #### -slideaudio/single picture if [[ $slideaudio && $slideaudio != /dev/null && $pictsrc ]]; then ((${#PICTSRC[*]}!=1||$(ls ${PICTSRC[0]} | wc -l)!=1)) && \ echo "++ WARN: [$PROGNAME] you should use only one source image if you use the option -slideaudio" | tee -a "$output".log fi #FIXME remove once the mpeg muxer is fixed #### NTSC telecined with B-frames if [[ $mpeg && $telecine && $videonorm = n && ( $frameformat = DVD || $frameformat = SVCD ) && ( $bframes -gt 0 || ! $bframes && $encode == ?:3:? ) ]]; then echo "++ WARN: [$PROGNAME] mpeg telecined and with B-frames are not created correctly by mencoder, do not use telecine or do not use B-frames" | \ tee -a "$output".log echo -n "Press return to proceed" && read fi ############################################################################### #### dump some info in the log file ############################################################################### { VARS=(frameformat ${split:+split} vfr vbr abr asr ${mpegchannels:+mpegchannels} ${GOP:+GOP} audioformat) # audioformat must be the last VARS[${#VARS[*]}]=${!VARS[${#VARS[*]}-1]} [[ $volume && ! $encode ]] && VARS[${#VARS[*]}]=volume echo -n " MPEG: " for ((i=0;i<${#VARS[*]};i++)) ; do echo -n "${VARS[i]}:${!VARS[i]} " done echo -n "${multiaudio:+multiaudio:${multiaudio// /,} }" echo -n "mpegencoder:$([ $mpeg ] && echo mencoder || echo mpeg2enc)" [[ $mpegaspect ]] && echo -n " aspect:${ASPECT[mpegaspect]}" [[ $cdi && $frameformat = VCD ]] && echo -n " CD-i" [[ $telecine ]] && echo -n " telecine" echo VARS=(encode ${vcodec:+vcodec} ${volume:+volume} ${usesbr:+usesbr} ${avisplit:+avisplit} ${channels:+channels} AUDIOPASS VIDEOPASS PASS) if [[ $encode ]]; then echo -n " $([ $mpeg ] && echo MPEG || echo \ AVI): " for ((i=0;i<${#VARS[*]};i++)) ; do echo -n "${VARS[i]}:${!VARS[i]} " done if ((PASS>1)); then [[ $turbo ]] && echo -n "TURBO:on " || echo -n "TURBO:off " fi txt= [[ $(echo $encode | cut -f 2 -d:) = 1 && $vcustom ]] && txt="libavcodec" [[ ${encode%%:*} = 2 && $acustom ]] && txt=${txt:+${txt} and} && txt="$txt lame" txt=${txt:+(custom ${txt} options)} echo $txt fi [[ ! $resume ]] && { [[ $audioonly ]] && mp_identify "$audioonly" || mp_identify "${MPLAYERINFO[@]}" ; } | sed -n '/^ID_/s/^/ INFO: [identify] /p' | uniq VARS=(${encode:+MENCODERARG} MPLAYERYUVOPT) VARS=(${encode:+MENCODERARG}) for ((i=0;i<${#VARS[*]};i++)) ; do s="INFO: [${VARS[i]}] \${${VARS[i]}[*]}" eval echo "\ \ \ $s" done } >>"$output".log h_res=$(grep ID_VIDEO_WIDTH "$output".log | tail -1 | cut -f2 -d=) v_res=$(grep ID_VIDEO_HEIGHT "$output".log | tail -1 | cut -f2 -d=) if [[ $pictsrc ]]; then v_res=$(mplayer -vo null "${MPLAYERINFO[@]}" -frames 1 2>/dev/null | awk '/^VO:/{print $3}' | head -n 1) h_res=${v_res%x*} v_res=${v_res#*x} fi [[ $mpeg && ${encode%,*} == ?:0:? ]] && H_RES=$h_res && V_RES=$v_res ############################################################################### #### put the volume in DB ############################################################################### [[ $volume ]] && volume="-af volume=$(awk -v a=$volume 'BEGIN{if(a>0) print 20*log(a)/log(10) ; else print 0}')" ############################################################################### #### NTSC telecined mpeg copy/speed encoding change ############################################################################### if [[ $mpeg && ( $encode == ?:0:? || $usespeed ) || $usespeed && ! $encode && $step -gt 1 ]]; then FPS=($(grep ID_VIDEO_FPS "$output".log | cut -f2 -d=) [1]=23.976 24.000 25.000 29.970 30.000 50.000 59.940 60.000) for ((i=1;i<9;i++)); do a=$(awk -v a=${FPS[0]} -v b=${FPS[i]} 'BEGIN{if (sqrt((a-b)*(a-b))<.02) print b}') if [[ $a ]]; then if [[ ${FPS[0]} != ${FPS[i]} ]]; then echo "++ WARN: [$PROGNAME] input video frame rate is not exactly ${FPS[i]}fps" | tee -a "$output".log FPS[0]=${FPS[i]} fi FPS[10]=$i break fi done [[ $usespeed && $i -eq 9 ]] && \ echo "++ WARN: [$PROGNAME] input video frame rate is not a valid NTSC/PAL value; disabling -usespeed" | tee -a "$output".log && usespeed= if [[ ${FPS[0]} = ${FPS[4]} || ${FPS[0]} = ${FPS[5]} ]]; then FPS[9]=$(mplayer -nocache -quiet "${MPLAYERINFO[@]}" -vo null -nosound -benchmark -frames 60 2>/dev/null | awk '/^demux_mpg:/{print $2}') [[ ${FPS[9]} = 24fps || ${FPS[9]} = 24000/1001fps ]] && FPS[10]=$((FPS[10]-3)) fi if [[ $usespeed ]]; then if ((vfr!=${FPS[10]})); then NSPEEDCOEF=([1]=1001 1001 5 1001 1001 5 1001 25 1250 5 25 2500 5 1200 6 2 2400 12 1001 1001 2 1001 5 2000 2 1200 6 1001 ) MSPEEDCOEF=([1]=1000 960 4 800 480 2 400 24 1001 4 12 1001 2 1001 5 1 1001 5 1000 200 1 500 3 1001 1 1001 5 1000 ) DCOEF=([1]=-2 3 7 10 12 13 13) if ((vfr>${FPS[10]})); then #### black magic here ;-) n=$((vfr+${FPS[10]}+${DCOEF[${FPS[10]}]})) a=${NSPEEDCOEF[n]}/${MSPEEDCOEF[n]} else n=$((vfr+${FPS[10]}+${DCOEF[vfr]})) a=${MSPEEDCOEF[n]}/${NSPEEDCOEF[n]} fi MENCODERARG=( -speed $a -srate $asr -af-adv force=1 "${MENCODERARG[@]}" ) MPLAYERYUVOPT=("${MPLAYERYUVOPT[@]}" -speed $a ) echo " INFO: [usespeed] using speed factor $a" | tee -a "$output".log fi elif [[ ${FPS[0]} = ${FPS[4]} || ${FPS[0]} = ${FPS[5]} ]]; then if [[ ${FPS[9]} = 24fps || ${FPS[9]} = 24000/1001fps || $telesrc ]]; then { echo -n " INFO: [$PROGNAME] " [[ ${FPS[9]} = 24fps || ${FPS[9]} = 24000/1001fps ]] && echo -n "detected" || echo -n "user selected" echo " telecined source" } | tee -a "$output".log MENCODERARG=( "${MENCODERARG[@]}" -ofps 24000/1001 -mc 0 ) fi fi fi ############################################################################### #### scale and expand/crop to adapt the aspect ratio #### added rotation and overscan ############################################################################### if [[ $mpegfixaspect && $step -gt 1 ]]; then a=$(get_aspect "${MPLAYERINFO[@]}") [[ ${a:0:9} = undefined ]] && a=$(awk -v a=$h_res -v b=$v_res 'BEGIN{printf("%f",a/b)}') [[ $mpegaspect == 1 ]] && b=$(awk -v a=$H_RES -v b=$V_RES 'BEGIN{printf("%f",a/b)}') || b=${ASPECT[${mpegaspect:-2}]} vfilter=$(awk -v a=$a -v A=$b -v W=$H_RES -v H=$V_RES -v crop=$mpegfixaspect -v i=${interlaced:-0} -v r=$rotate -v o=$overscan -v logfile="$(echo "$output" | sed 's/\\/\\\\/g')".log 'BEGIN{ ko=(1-o/100) if(a==1.78)a=16/9 if(a==1.33)a=4/3 if(A=="4/3")A=4/3 if(A=="16/9")A=16/9 if(r!=""){ A=1/A tmp=W W=H H=tmp } if(a>A&&crop==0||a<A&&crop==1){ Eh=A*H/a Ew=W }else{ Ew=W*a/A Eh=H } Ew=2*int(Ew*ko/2+0.50) Eh=2*int(Eh*ko/2+0.50) printf("-vf scale=%d:%d",Ew,Eh) printf(" INFO: [mpegfixaspect] -vf scale=%d:%d",Ew,Eh) >>logfile if(i==1)printf(":1") if(i==1)printf(":1") >>logfile if(crop==0){ printf(",expand=%d:%d",W,H) printf(",expand=%d:%d",W,H) >>logfile }else{ printf(",crop=%d:%d",W,H) printf(",crop=%d:%d",W,H) >>logfile } if(r!=""){ printf(",rotate=%d",r) printf(",rotate=%d",r) >>logfile } if(o!=0) printf(" [overscan=%d]",o) >>logfile printf("\n") >>logfile }') if [[ $mpeg ]]; then for ((a=0;a<${#MENCODERARG[*]};a++)); do if [[ ${MENCODERARG[a]} = -vf ]]; then MENCODERARG[a+1]=$(echo ${MENCODERARG[a+1]} | sed 's/scale=[^,]*,//;s/^/'"${vfilter#-vf }"',/') fi done fi fi ############################################################################### #### dvd vobsub ############################################################################### #### function to select the vobsub to extract next_vobsub_idx () { if ((${#SID[*]})); then if ((idx < ${#encsid[*]})); then SID=(-sid ${encsid[idx]} -vobsuboutindex ${encsdx[idx]} ${encsla:+-vobsuboutid ${encsla[idx]}} -vobsubout "$output") echo " INFO: [$PROGNAME] dumping subtitle ${encsid[idx]} to vobsub ${encsdx[idx]}${encsla:+ (${encsla[idx]})}" | tee -a "$output".log idx=$((idx+1)) else unset SID fi fi } #### turn on vobsub extraction if encsid is given if (( ${#encsid[*]} )) ; then (( ${#encsdx[*]} )) || encsdx=( ${encsid[*]} ) idx=0 SID=(0000) next_vobsub_idx else unset SID fi status_bit sub || unset SID ############################################################################### #### test condition "extra" ############################################################################### IDACOD=$(grep "ID_AUDIO_CODEC" "$output".log | tail -1 | cut -f2 -d=) [[ $mpeg && ! $pictsrc && ( $encode == 1:?:? || $multiaudio || $encode == 0:?:? && $IDACOD != mp3 && $IDACOD != a52 ) ]] && extra=1 || extra= [[ $extra ]] && echo "**ERROR: [$PROGNAME] output stream: unsupported audio codec $IDACOD" | tee -a "$output".log && exit 1 CLEAN[${#CLEAN[*]}]="$output".tmp ############################################################################### #### avi/mpeg section ############################################################################### if [[ $encode ]]; then if status_bit avi ; then find_sbr () { local kv k ka if [[ $mpeg ]]; then kv=9888 ; k=33 ; ka=996 fi if ((usesbr<=6)); then sbr=$(awk '/for '"${SBR[usesbr-1]}"'MB CD/{print $NF}' <"$output".log) [[ $sbr ]] && ((sbr<vbitrate)) && VIDEOPASS=${VIDEOPASS/vbitrate=$vbitrate:/vbitrate=$sbr:} && \ echo " INFO: [mencoder] using vbitrate=$sbr" | tee -a "$output".log else #### usesbr is in MB #### remind: 650-800,650-1400,800-1400 sbr[0]=650 sbr[1]=1400 sbr[2]=$(awk '/for '"${SBR[0]}"'MB CD/{print $NF}' <"$output".log) sbr[3]=$(awk '/for '"${SBR[4]}"'MB CD/{print $NF}' <"$output".log) [[ ${sbr[2]} && ${sbr[3]} ]] && \ sbr[4]=$(((((usesbr*kv/10000-k)-(audiosize*ka/1000))*(sbr[3]-sbr[2])+sbr[1]*sbr[2]-sbr[0]*sbr[3])/(sbr[1]-sbr[0]))) [[ ${sbr[4]} ]] && ((sbr[4]<vbitrate && sbr[4]>0)) && VIDEOPASS=${VIDEOPASS/vbitrate=$vbitrate:/vbitrate=${sbr[4]}:} && \ echo " INFO: [mencoder] using vbitrate=${sbr[4]}" | tee -a "$output".log fi } AID= #### start mencoder PLOG=( -passlogfile "$output".avi2pass.log ) rm -f frameno.avi if ((PASS==1)); then if [[ $usesbr && ! $extra ]]; then mencoder $OPTIONS -ovc frameno -o /dev/null "${SID[@]}" "${MENCODERARG[@]}" $AID $AUDIOPASS 2>&1 | \ mp_single_log mencoder '^Recommended video bitrate' find_sbr next_vobsub_idx fi ((DEBUG)) && debug_line $((LINENO+1)) "PASS 1/$PASS" mencoder $OPTIONS $VIDEOPASS -o "$output".$SUF "${SID[@]}" "${MENCODERARG[@]}" $AID $AUDIOPASS $volume -v | mplayer_log mencoder next_vobsub_idx else #### N pass if [[ $usesbr && ! $extra ]]; then mencoder $OPTIONS -ovc frameno -o /dev/null "${SID[@]}" "${MENCODERARG[@]}" $AID $AUDIOPASS 2>&1 | \ mp_single_log mencoder '^Recommended video bitrate' find_sbr next_vobsub_idx fi CLEAN[${#CLEAN[*]}]="$output".avi2pass.log ((DEBUG)) && debug_line $((LINENO+1)) "PASS 1/$PASS" mencoder $OPTIONS ${VIDEOPASS}:vpass=1$turbo -o /dev/null "${SID[@]}" "${MENCODERARG[@]}" $AID $AUDIOPASS $volume "${PLOG[@]}" next_vobsub_idx if ((PASS==2)); then ((DEBUG)) && debug_line $((LINENO+1)) "PASS 2/$PASS" mencoder $OPTIONS ${VIDEOPASS}:vpass=2 -o "$output".$SUF "${SID[@]}" "${MENCODERARG[@]}" $AID $AUDIOPASS $volume "${PLOG[@]}" -v | \ mplayer_log mencoder next_vobsub_idx else for ((a=2;a<PASS;a++)); do ((DEBUG)) && debug_line $((LINENO+1)) "PASS $a/$PASS" mencoder $OPTIONS ${VIDEOPASS}:vpass=3 -o /dev/null "${SID[@]}" "${MENCODERARG[@]}" $AID $AUDIOPASS $volume "${PLOG[@]}" next_vobsub_idx done ((DEBUG)) && debug_line $((LINENO+1)) "PASS $PASS/$PASS" mencoder $OPTIONS ${VIDEOPASS}:vpass=3 -o "$output".$SUF "${SID[@]}" "${MENCODERARG[@]}" $AID $AUDIOPASS $volume "${PLOG[@]}" -v | \ mplayer_log mencoder next_vobsub_idx fi fi status_bit avi set fi fi ############################################################################### #### if there are still vobsub to dump, do it now ############################################################################### while ((${#SID[*]})) ; do ((DEBUG)) && debug_line $((LINENO+1)) vobsub mencoder -ovc copy -o /dev/null $AID "${SID[@]}" "${MENCODERARG[@]}" -nosound next_vobsub_idx done if status_bit sub ; then if [[ -f $output.sub && -f $output.idx && ${#encsid[*]} -gt 0 ]]; then #### reset the subtitles with the wrong timestamp awk -v logfile="$(echo "$output" | sed 's/\\/\\\\/g')".log '{ if($1=="id:")id=" ("$0")" if($1=="timestamp:"){ n=$2; sub(/,/,"",n); # convert the timestamp in seconds m=3600*substr(n,1,index(n,":")-1); sub(/[0-9]*:/,"",n); m=m+60*substr(n,1,index(n,":")-1); sub(/[0-9]*:/,"",n); m=m+substr(n,1,index(n,":")-1); sub(/[0-9]*:/,"",n); m=m+n/1000; # .002 is already ok if(m+.004<t){ printf("++ WARN: [encsid] reset bad timestamp sequence: %s %s%s\n",gensub(/[^ ]* /,"",1,gensub(/,.*/,"",1,p)),substr($2,1,length($2)-1),id) >>logfile ; id=""; p=gensub(/ [^ ]* /," 00:00:00:000, ",1,p)" #"p} t=m} else t=0; if(NR>1)print p; p=$0 } END{print p}' <"$output".idx >"$output".idx.idx && mv "$output".idx.idx "$output".idx status_bit sub set fi fi ############################################################################### #### if fast mode skip multiplexing ############################################################################### if [[ $mpeg && $fast ]]; then if status_bit mpg ; then if [[ ! $extra ]]; then rm -f "$output".mpg "${output}"[0-9][0-9].mpg status_bit mpv set status_bit mpa set status_bit mpg set mv "$output".$SUF "$output".mpg fi fi #FIXME remove once the mpeg muxer is fixed #### NTSC dvd warn [[ $videonorm = n && $frameformat = DVD ]] && \ echo "++ WARN: [$PROGNAME] mencoder does not multiplex correctly NTSC mpeg, you may want to use encode2mpeg instead" | tee -a "$output".log fi ############################################################################### #### split the mpeg stream (for Mpeg Mode) ############################################################################### if status_bit spl ; then #### split for Mpeg Mode (mpeg4 codec not supported) #### mencoder does not support split as it does mpeg2enc/mplex #### this solution is slow, but it seems quite accurate if [[ $mpeg && $split && $vcodec != mpeg4 ]]; then [[ ! $fast ]] && mv "$output"01.mpg "$output".mpg file_size "$output".mpg if ((split*1024*1024<fsize)); then chunks=$((fsize/(split*1024*1024)+1)) CLEAN[${#CLEAN[*]}]="$output".framelist mplayer "$output".mpg -vf framestep=I -vo null -nosound -benchmark 2>/dev/null | tr '\015' '\012' | \ awk '{if($1=="I!")print t,substr(f,1,index(f,"/")-1);t=$2;f=$3}' >"$output".framelist m=0 #### removed -vc dummy [[ $multiaudio ]] && a=$(mplayer -vo null -ao null -frames 1 -v "$output".mpg 2>/dev/null | awk '/==> Found audio str/{print $NF}' | \ sort -n | tr '\012' ',' | sed 's/,$/\n/') for ((i=0;i<chunks;i++)); do if ((i<chunks-1)); then n=$(mplayer "$output".mpg -vf framestep=I -vo null -nosound -benchmark 2>/dev/null -sb $(((i+1)*split*1024*1024)) -frames 30 | \ tr '\015' '\012' | awk '{if($1=="I!"){print t;exit};t=$2}') n=$(awk '/^'"$n"'/{print $2-1;exit}' "$output".framelist) #should be -2 else n= fi ((DEBUG)) && debug_line $((LINENO+1)) "mpeg_split $((i+1))/$chunks" "$PROGFILE" -norc "$output".mpg -o "$output"$(printf "%02d" $((i+1))) -mpegonly -mpeg -encode 0:0:1 -$(echo $frameformat| tr '[:upper:]' '[:lower:]') -nosplit -noshowlog -sb $((i*split*1024*1024)) ${n:+-frames $((n-m))} -a ${mpegaspect:-2} ${multiaudio:+-multiaudio $a} -mc 0 rm "$output"$(printf "%02d" $((i+1))).log m=$n done rm "$output".mpg else mv "$output".mpg "$output"01.mpg fi status_bit spl set fi fi ################################################################################ #### done ################################################################################ exit