summaryrefslogtreecommitdiffstats
path: root/abs/core-testing/linhes-scripts/myth2fuze
blob: f4d1ce216ee9d72f5be13b3091867b4f11ccbb52 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
#!/bin/bash
# convert recording to avi compatable with San Disk Sansa Fuze
# Based on and/or inspired by myth2xvid, the video4fuze project:
# http://code.google.com/p/video4fuze
# and the fuzemux project:
# http://code.google.com/p/fuzemux
#
# version 0.1
#
# usage:
# first parameter must be %DIR%/%FILE% of the recording
# second parameter must be the desired base name of the output
# third parameter must be %CHANID% if you set USECUTLIST=Y
# fourth parameter must be %STARTTIME% if you set USECUTLIST=Y
# fifth parameter must be %JOBID% for the User Job status to be updated in MythTV
# in the mythtv setup screen invoke this script like this:
# MYTHTV User Job Command:
# /usr/bin/myth2fuze "%DIR%/%FILE%" "%TITLE% - %SUBTITLE%" "%CHANID%" "%STARTTIME%" "%JOBID%"

# options:
USECUTLIST=Y		# Y or N

# check prerequesites
for APP in {fuzemux,mencoder,ffmpeg,mythcommflag,mythtranscode,mysql}; do
   /usr/bin/which $APP &>/dev/null
   ERROR=$?
   if [ $ERROR -ne 0 ]; then
      echo "$APP not found in your PATH! Aborting! ERROR: $ERROR" >> $LOGFILE
      update_status 304
      update_comment "$APP not found in your PATH! Aborting! Exit status: $ERROR"
      exit 1
   fi
done

# where the converted video is stored
OUT_DIR=/myth/md0/video/fuze

# Ensure output directory exists
if [ ! -d $OUT_DIR ] ; then
  mkdir -p -m777 $OUT_DIR
fi

# database settings
BACKEND_HOSTNAME=${BACKEND_HOSTNAME:-"localhost"}
DBUSERNAME=${DBUSERNAME:-"mythtv"}
DBPASSWORD=${DBPASSWORD:-"mythtv"}
SQLCMD="mysql -u $DBUSERNAME --password=$DBPASSWORD -h $BACKEND_HOSTNAME mythconverg -e"

#------FUNCTIONS---------------
update_comment()
# Arg_1 = COMMENT
{
if [ $NO_JOBID = 0 ]; then
    `$SQLCMD "update jobqueue set comment=\"$1\" where id=\"$JOBID\";"`
fi
}

update_status()
# Arg_1 = status code
{
if [ $NO_JOBID = 0 ]; then
    `$SQLCMD "update jobqueue set status=\"$1\" where id=\"$JOBID\";"`
fi
}

check_background_progress()
# check mencoder progress in background
# Arg_1 = PROGRESS CALCULATION
{
while [ `tail -1 $STATUSFILE | grep -cE "^Audio stream:|^Video stream:"` = 0 ]
do
    sleep 10
    check_myth_jobcmds
    current_status=`tail -1 $STATUSFILE | grep "([ 0-9]\{1,\}%)"`
    prog_percent=`echo "$current_status" | sed 's_.*(\([ 0-9][ 0-9]\)%).*_\1_'`
    current_FPS=`echo "$current_status" | sed 's_.*\([ 0-9][ 0-9].[ 0-9][ 0-9]\)fps.*_\1_'`
    if [ -n "$prog_percent" ]; then
        prog_percent=`expr $prog_percent / $1`
        echo "$prog_percent% Completed @ $current_FPS fps"
        update_comment "$prog_percent% Completed @ $current_FPS fps"
    fi
    sleep 10
done
}

check_myth_jobcmds()
# check the myth database for stop pause or resume commands
{
if [ $NO_JOBID = 0 ]; then
    CURRENT_CMD=`$SQLCMD "select cmds from jobqueue where id=\"$JOBID\";" | sed '/[0-9]/!d'`
    case "$CURRENT_CMD" in
	# JOB_RUN
	0) ;;
	# JOB_PAUSE
	1) update_status 6
	   kill -s STOP $mencoder_pid ;;
	# JOB_RESUME
	2) update_status 4
       `$SQLCMD "update jobqueue set cmds=\"0\" where id=\"$JOBID\";"`
       kill -s CONT $mencoder_pid ;;
	# JOB_STOP
	4) update_status 5
	   `$SQLCMD "update jobqueue set cmds=\"0\" where id=\"$JOBID\";"`
       kill -9 $mencoder_pid $command_pid
       clean_up_files
       echo "Encode Cancelled" >> $LOGFILE
       update_status 320
 	   exit ;;
    esac
fi
}

get_mencoder_pid()
{
process_name=""
i1=1
while [ "$process_name" != "found" ]; do
   if [ "`ps $mencoder_pid | grep mencoder | sed 's_.*\(mencoder\).*_\1_'`" = "mencoder" ]; then
      process_name="found"
   else
      mencoder_pid=`expr $mencoder_pid + 1`
   fi
   i1=`expr $i1 + 1`
   if [ $i1 -gt 20 ]; then
      break
   fi
done
}

run_fuzemux()
# Remux avi to fuze compatable avi
{
/usr/bin/fuzemux ${TMPFILE} ${OUTPUTFILE} >> $LOGFILE || return 1
}

create_thumbnail()
# Create a thumbnail image for the fuze
{
/usr/bin/ffmpeg -y -v -1 -i ${OUTPUTFILE} -t 1 -ss 3 -s 224x176 -f image2 ${OUTPUTFILE%.*}.thm >> $LOGFILE
}

clean_up_files()
# clean up left over files
{
unlink $TMPFILE 2> /dev/null
unlink $TMPCUTFILE 2> /dev/null
unlink $TMPCUTFILE.map 2> /dev/null
unlink $TWOPASSFILE 2> /dev/null
unlink $TWOPASSFILE.tmp 2> /dev/null
unlink $STATUSFILE 2> /dev/null
unlink $MENCODER_RETURN_CODE 2> /dev/null
unlink $MENCODER_RETURN_CODE_2 2> /dev/null
}

#-------MAIN SCRIPT------------

# check if %JOBID% is passed from command line
JOBID=$5
if [ -z "$JOBID" ]; then
    NO_JOBID=1
else
    NO_JOBID=0
fi

# create temp filename so multiple instances won't conflict
TMPNAME=toFUZE-$$
TMPFILE=/myth/md0/tmp/$TMPNAME.avi
TMPCUTFILE=/myth/md0/tmp/$TMPNAME.mpg
MENINPUTFILE=$1
TWOPASSFILE=/tmp/$TMPNAME-2pass.log
STATUSFILE=/tmp/$TMPNAME-status.log
MENCODER_RETURN_CODE=/tmp/$TMPNAME-mencoder_return_code
MENCODER_RETURN_CODE_2=/tmp/$TMPNAME-mencoder_return_code_2

# log file location
LOGFILE=/var/log/mythtv/myth2fuze.log
CDate="`date`"
echo "" >> $LOGFILE
echo $CDate >> $LOGFILE
echo "File to encode: $MENINPUTFILE     Name: $2" >> $LOGFILE

# start timer
beforetime="$(date +%s)"

check_myth_jobcmds

# check if using cutlist
if [ $USECUTLIST = Y ]; then
    MYTHCOMMFRAMES=`mythcommflag --getcutlist -f $MENINPUTFILE | grep 'Cutlist:' | cut -d \  -f 2`
    if [ -n "$MYTHCOMMFRAMES" ]; then
        echo "Extracting Cutlist..." >> $LOGFILE
        update_comment "Extracting Cutlist"
        /usr/bin/nice -n19 /usr/bin/mythtranscode --chanid "$3" --starttime "$4" --outfile "$TMPCUTFILE" --mpeg2 --honorcutlist
        MENINPUTFILE=$TMPCUTFILE
    fi
fi

# run mencoder in background to do 1st pass conversion
echo "Encoding 1st Pass for the Fuze..." >> $LOGFILE
( /usr/bin/nice -n19 /usr/bin/mencoder $MENINPUTFILE -passlogfile $TWOPASSFILE \
-ffourcc DX50 -ofps 20 -vf pp=li,expand=:::::224/176,scale=224:176,harddup \
-ovc lavc -lavcopts vcodec=mpeg4:vbitrate=683:vmax_b_frames=0:keyint=15:turbo:vpass=1 \
-nosound -o /dev/null > $STATUSFILE 2>&1 ; echo $? > $MENCODER_RETURN_CODE ) &
mencoder_pid=$!
command_pid=$mencoder_pid
get_mencoder_pid

check_background_progress "2"

if [ `cat $MENCODER_RETURN_CODE` -ne 0 ]; then
   echo "Mencoder pass #1 exited with error $MENCODER_RETURN_CODE.  Encoding fa$
   update_status 304
   update_comment "ERROR: Mencoder pass #1 exited with error $MENCODER_RETURN_C$
   clean_up_files
   exit 1
fi

# run mencoder in background to do 2nd pass conversion
echo "Encoding 2nd Pass for the Fuze..." >> $LOGFILE
( /usr/bin/nice -n19 /usr/bin/mencoder $MENINPUTFILE -passlogfile $TWOPASSFILE \
-ffourcc DX50 -ofps 20 -vf pp=li,expand=:::::224/176,scale=224:176,harddup \
-ovc lavc -lavcopts vcodec=mpeg4:vbitrate=683:vmax_b_frames=0:keyint=15:vpass=2 \
-srate 44100 -af resample=44100:0:1,format=s16le -oac mp3lame \
-lameopts cbr:br=128 -o "$TMPFILE" > $STATUSFILE 2>&1 ; echo $? \
> $MENCODER_RETURN_CODE_2 ) &
mencoder_pid=$!
command_pid=$mencoder_pid
get_mencoder_pid

check_background_progress "2"

if [ `cat $MENCODER_RETURN_CODE_2` -ne 0 ]; then
   echo "Mencoder pass #1 exited with error $MENCODER_RETURN_CODE.  Encoding fa$
   update_status 304
   update_comment "ERROR: Mencoder pass #1 exited with error $MENCODER_RETURN_C$
   clean_up_files
   exit 1
fi

# make output filename unique, remove punctuation and "special" characters,
# replace spaces with underscores and force lowercase names
FILENAME=$( echo ${2} | tr -d '[:punct:]' | tr -d "\"" | tr -d "\!" \
          | tr -d "\`" | tr -s '[:blank:]' '[_]' \
          | tr '[:upper:]' '[:lower:]' )_fuze.avi | tr -s '[_]'
ERROR=$?

if [ $ERROR -ne 0 ]; then
   echo "Creating unique file name exited with error $ERROR" >> $LOGFILE
   update_status 304
   update_comment "ERROR: Creating unique file name exited with error $ERROR  Job Failed!"
   clean_up_files
   exit 1
fi

OUTPUTFILE=${OUT_DIR}/${FILENAME}
ERROR=$?

if [ $ERROR -ne 0 ]; then
   echo "Setting output file name exited with error $ERROR" >> $LOGFILE
   update_status 304
   update_comment "ERROR: Setting output file name exited with error $ERROR  Job failed!"
   clean_up_files
   exit 1
fi

i=1
while [ -e "$OUTPUTFILE" ]
do
    FILENAME=$( echo ${2} | tr -d '[:punct:]' | tr -d "\"" | tr -d "\!" \
              | tr -d "\`" | tr -s '[:blank:]' '[_]' \
              | tr '[:upper:]' '[:lower:]' )_fuze-$i.avi
    OUTPUTFILE=${OUT_DIR}/${FILENAME}
    i=`expr $i + 1`
done
ERROR=$?

if [ $ERROR -ne 0 ]; then
   echo "Setting output file name exited with error $ERROR" >> $LOGFILE
   update_status 304
   update_comment "ERROR: Setting output file name exited with error $ERROR  Job failed!"
   clean_up_files
   exit 1
fi

run_fuzemux
ERROR=$?

if [ $ERROR -ne 0 ]; then
   echo "Fuzemux exited with error $ERROR" >> $LOGFILE
   update_status 304
   update_comment "ERROR: Fuzemux exited with error $ERROR  Job Failed!"
   clean_up_files
   exit 1
fi

# ensure mythtv owns the final avi
chown mythtv ${OUTPUTFILE}
ERROR=$?

if [ $ERROR -ne 0 ]; then
   echo "Changing ownership of avi to mythtv exited with error $ERROR"
   update_status 304
   update_comment "ERROR: Changing ownership of avi to mythtv exited with error $ERROR  Job failed!"
   clean_up_files
   exit 1
fi

create_thumbnail

# ensure mythtv owns the thumbnail
chown mythtv ${OUTPUTFILE%.*}.thm
ERROR=$?

if [ $ERROR -ne 0 ]; then
   echo "Changing ownership of thumbnail to mythtv exited with error $ERROR"
   update_status 304
   update_comment "ERROR: Changing ownership of thumbnail to mythtv exited with error $ERROR  Job failed!"
   clean_up_files
   exit 1
fi

# stop timer
aftertime="$(date +%s)"
seconds="$(expr $aftertime - $beforetime)"
    echo "File Encoded Successfully: $OUTPUTFILE" >> $LOGFILE
    hours=$((seconds / 3600))
    seconds=$((seconds % 3600))
    minutes=$((seconds / 60))
    seconds=$((seconds % 60))
    echo "Encoding took $hours hour(s) $minutes minute(s) $seconds second(s) @ $current_FPS fps." >> $LOGFILE
    update_status 272
    update_comment "Encode Successful. Encoding Time: $hours hour(s) $minutes minute(s) $seconds second(s)"

clean_up_files