User:Iamlindoro
From MythTV Official Wiki
Here is a script that allows lossless cutting of HD-PVR content. Set this script as executable, and as a userjob. It works on the cutlist, so get that set before running. You could technically swap --getcutlist for --getskiplist and this would probably work as an auto-commercial-removal, but that is an insanely bad idea.
PS, Discussion pages are for suggesting changes, don't just edit someone's user page. :)
hdpvr_lossless_cut.sh
#!/bin/sh -e # # Written by Robert McNamara # (robert DOT mcnamara ATSIGN gmail DOT com) # # Requires: # # AVIDemux 2.4 SVN revision 4445 or later (current 10/7/08) # Working MythTV setup (To steal the cutlist from) # FFMpeg (to fix indexing and drop into an MKV) # # This script *might* work on 1080i material now. Who knows? # # This script works at the keyframe level only. I strongly advise # you to set cutpoints approximately one second into actual program # material to avoid accidentally inserting commercials. # # The output MKV file will be in your recordings directory. # # Basic user job setup is: # # h264cut %DIR% %FILE% # test -f /etc/mythtv/mysql.txt && . /etc/mythtv/mysql.txt test -f ~/.mythtv/mysql.txt && . ~/.mythtv/mysql.txt mysqlconnect="mysql -N -h$DBHostName -u$DBUserName -p$DBPassword $DBName" export mysqlconnect RECDIR=$1 BASENAME=$2 chanid=`echo "select chanid from recorded where basename=\"$BASENAME\";" | $mysqlconnect` starttime=`echo "select starttime from recorded where basename=\"$BASENAME\";" | $mysqlconnect` if test "$chanid" = "" || test "$starttime" = "" ; then echo "Recording not found in MythTV database, aborted." exit 1 fi cat > $RECDIR/$BASENAME.cut << EOF //AD <- Needed to identify// var app = new Avidemux(); //** Video ** // 01 videos source app.load("/$RECDIR/$BASENAME"); app.clearSegments(); EOF CUTLIST=`mythcommflag --getcutlist -f /$RECDIR/$BASENAME |grep Cutlist| sed 's/Cutlist//g' | sed 's/-/ /g' |sed 's/,/-/g' | sed 's/: 0 //'| sed 's/: /-/'`- FIRSTFRAME=`echo "select MIN(mark) from recordedseek where chanid=$chanid and starttime='$starttime';" | $mysqlconnect` LASTFRAME=`echo "select MAX(mark) from recordedseek where chanid=$chanid and starttime='$starttime';" | $mysqlconnect` for i in ${CUTLIST} do # Get exact frame cut number from Myth STARTKEYFRAME=`echo $i | cut -d '-' -f 1` ENDKEYFRAME=`echo $i | cut -d '-' -f 2` # Turn those framenumbers into nearest keyframe prior to cutpoint. START=`echo "select mark from recordedseek where mark < $STARTKEYFRAME and chanid=$chanid and starttime='$starttime' order by mark DESC LIMIT 1;" | $mysqlconnect || continue` END=`echo "select mark from recordedseek where mark < $ENDKEYFRAME and chanid=$chanid and starttime='$starttime' order by mark DESC LIMIT 1;" | $mysqlconnect || continue` if [ .${START}. = .. ] then START=0 fi if [ ${START} -ge $LASTFRAME ] then continue fi if [ .${END}. = .. ] then END=$LASTFRAME fi LENGTH=$((${END} - ${START} )) if [ ${LENGTH} -le 0 ] then echo LENG $LENGTH continue fi cat >> $RECDIR/$BASENAME.cut << EOF app.addSegment(0,${START},${LENGTH}); EOF count=$((${count} + 1)) done cat >> $RECDIR/$BASENAME.cut << EOF app.markerA=$FIRSTFRAME; app.markerB=$LASTFRAME; app.rebuildIndex(); //** Postproc ** app.video.setPostProc(3,3,0); app.video.setFps1000(59940); //** Filters ** //** Video Codec conf ** app.video.codec("Copy","CQ=4","0 "); //** Audio ** app.audio.reset(); app.audio.codec("copy",128,0,""); app.audio.normalizeMode=0; app.audio.normalizeValue=0; app.audio.delay=0; app.audio.mixer("NONE"); app.setContainer("MATROSKA"); setSuccess(1); //app.Exit(); //End of script EOF CORENAME=`basename $BASENAME .mpg` # Run through AVIDemux. Don't know how the audio sync will be. # nice -n 9 avidemux2_cli --force-alt-h264 --autoindex --rebuild-index --nogui --force-smart --load "$RECDIR/$BASENAME" --run $RECDIR/$BASENAME.cut --save "$RECDIR/$CORENAME.avi" --quit 2> /dev/null # Move the AVI file into a Matroska. # Failure to do this will result in broken seeking. ffmpeg -i $RECDIR/$CORENAME.avi -acodec copy -vcodec copy $RECDIR/$CORENAME.mkv # Do a little cleanup. rm $RECDIR/$CORENAME.avi rm $RECDIR/$BASENAME.idx rm $RECDIR/$BASENAME.cut
This is a script that will correct broken MPEG-2 TSs from firewire or DVB. The script replaces the original recording with a file that will work with mythtranscode rather than crashing it.
#!/bin/sh # # # mpeg2fixup.sh # # Written in 2008 by Robert McNamara. Please redistribute freely and without # restriction. (robert DOT mcnamara ATSIGN g m a i l DOTCOM) # # Script to clean up Firewire and DVB recordings that kill mythtranscode. # It appears the bogus PTS information makes mythtrascode lossless transcoding # fail with error 232 (Unknown). It complains about a deadlock. # # This solution is not the most elegant in the world, but it *does* work and # ultimately permits Myth to successfully lossless-transcode the files. # # There are two prerequisites for this script. The first is the xport # transport stream demuxer. It is only distributed for Windows but it compiles # fine on linux. Get the following file: # # http://www.w6rz.net/xport.zip # # And unzip it. Compile it with "cc -o xport xport.c" and copy the resulting # file to somewhere in your path (in my case, /usr/bin). # # You will also need a copy of ffmpeg with AC3 and MPEG-2 support. # # In essence, this script demuxes the file recorded from DVB/Firewire, and # remuxes the streams with ffmpeg into a "clean" MPEG container. It copies the # existing recording file to the same location with extension .tmp and inserts # the new file in its place. Commercial flags and cutlists are cleared, and # commflagging is run on the new file. In my limited testing, Myth can now # successfully transcode the resulting file losslessly. # # Here's how it should be set up as a userjob: # # mpeg2fixup.sh "%DIR%" "%FILE%" # # I set the script to work within /tmp. If you don't want it to do that, # change the first variable below. # # Even on a powerful processor (I run this on a Q6600) you can expect this to cost # you 10 or so minutes of processing time for each hourlong show. It's the price # you pay to preserve quality and end up with lossless-transcode-able files. WORKINGDIR=/tmp DIR=$1 FILE=$2 # Make the directory to work in: mkdir "$WORKINGDIR/$FILE" cd "$WORKINGDIR/$FILE" # First step is dumping the PIDs to files xport "$DIR/$FILE" 1 1 1 # Once we're done with that, let's mux everything into a new file. ffmpeg -i bits0001.mpv -i bits0001.mpa -vcodec copy -acodec copy "$WORKINGDIR/$FILE/$FILE" # Let's move the old file out of the way, and the new file into its place. mv "$DIR/$FILE" "$DIR/$FILE.old" mv "$WORKINGDIR/$FILE/$FILE" "$DIR/$FILE" # Now we need to clear the cutlist on the file, rebuild its seektable, and rerun commflagging. mythcommflag --clearcutlist -f "$DIR/$FILE" ERROR=$? if [ $ERROR -ne 0 ]; then echo "Clearing cutlist failed for $FILE with error $ERROR" exit $ERROR fi # *Don't* rebuild the seektable traditionally or you will end up with screwed up times and it will be uneditable. # Use mythtranscode on lossless/buildindex mode instead. mythtranscode --mpeg2 --infile "$DIR/$FILE" --buildindex --showprogress ERROR=$? if [ $ERROR -ne 0 ]; then echo "Rebuilding seektable failed for $FILE with error $ERROR" exit $ERROR fi # Commercial Flagging. This mostly sucks on my broken recordings, you can comment it out if # you wish. I find that I basically have to go in and manually set cutpoints anyway. mythcommflag -f "$DIR/$FILE" ERROR=$? if [ $ERROR -ne 0 ]; then echo "Commercial flagging failed for ${FILENAME} with error $ERROR" exit $ERROR fi # Remove the contents of the working directory rm -rf "$WORKINGDIR/$FILE" # If you want to remove the old recording, uncomment the last line: # rm "$DIR/$FILE.old"