[mythtv-users] Error parsing config.xml?

Raymond Wagner raymond at wagnerrp.com
Sat May 12 00:50:10 UTC 2012


On 5/11/2012 15:18, John Pilkington wrote:
> On 11/05/12 19:10, Bill Meek wrote:
>> On 05/11/2012 11:57 AM, Michael T. Dean wrote:
>> ...
>>> Probably best would be to use a language designed for parsing text,...
>>
>> As an example (of using a tank to kill a mosquito)
>> http://pastebin.ca/2147582 is
>> what I wrote. Save it as xml2src. Replace . ~mythtv/.mythtv/mysql.txt
>> with:
>>
>> for V in $(xml2src); do export $V; done
>>
>> Truth be told, I'm finding that I don't use most of my old SQL scripts
>> and
>> using python bindings and Services API are of more interest.
>>
>> But, this gives me time to learn then convert anything I actually use.
>>
>> Cue the part where someone who knows what they're doing writes the
>> whole thing in one line.
>>
> Thanks, Bill - and Mike and Raymond.  I take the point about using the
> bindings, but the advice is along the lines of 'Can you please tell me
> the way to XXX?  Ooh, I wouldn't start from here' :-)

Change your job to something like...

mythcutprojectx.py %VERBOSEMODE% %JOBID%

The bindings will automatically handle logging through the same 
mechanism as the internal code.  All you have to do is pick up the jobid 
from the last argument.  Pull the job from the database with...

 >>> import sys
 >>> from MythTV import Job
 >>> job = Job(sys.argv[-1])

Extract the recording...

 >>> from MythTV import Recorded
 >>> rec = Recorded.fromJob(job)

Find the recording...

 >>> import os
 >>> from MythTV import findfile
 >>> sg = findfile(rec.basename, rec.storagegroup)
 >>> if sg is None:
 >>>     raise Exception("recording not found")
 >>> absfile = os.path.expand(sg.dirname, rec.basename)

It appears ProjectX uses selection lists, so find the closest outer 
keyframes to the sections...

 >>> i = iter(rec.seek)
 >>> cur = i.next()
 >>> segments = []
 >>> try:
 >>>     for start,end in rec.markup.getuncutlist():
 >>>         segstart = segend = None
 >>>         while True:
 >>>             prev = cur
 >>>             cur = i.next()
 >>>             if (prev.mark <= start) and (cur.mark > start):
 >>>                 # start of segment bracketed, use left outside frame
 >>>                 segstart = prev.offset
 >>>                 break
 >>>         while True:
 >>>             prev = cur
 >>>             cur = i.next()
 >>>             if (prev.mark < end) and (cur.mark >= end):
 >>>                 # end of segment bracketed, use right outside frame
 >>>                 segend = cur.offset
 >>>                 break
 >>>         segments.append((segstart,segend))
 >>> except StopIteration:
 >>>    if segstart is not None:
 >>>        # segment start found, but end was unbounded
 >>>        segments.append((segstart, rec.filesize))
 >>> fd = open(rec.basename+'.cutlist')
 >>> fd.write('CollectionPanel.CutMode=0\n')
 >>> for start,end in segments:
 >>>     fd.write('{0}\n{1}\n'.format(start,end))

Grab stream IDs from ffmpeg...

 >>> import re
 >>> r = re.compile('[ ]+Stream #[0-9\.]+\[(?P<streamid>0x[0-9]+)\].*')
 >>> from MythTV import System
 >>> ffmpeg = System('mythffmpeg')
 >>> videopid = audiopid = None
 >>> for line in ffmpeg('-i', abspath).split('\n'):
 >>>     match = r.match(line)
 >>>     if match:
 >>>         if ('Video' in line) and (videopid is None):
 >>>             videopid = match.group('streamid')
 >>>         if ('Audio' in line) and (audiopid is None):
 >>>             audiopid = match.group('streamid')

Run ProjectX. No need to ionice, jobqueue does that for us...

 >>> basename = rec.basename.rsplit('.',1)[0]
 >>> projectx = System('java -jar /path/to/ProjectX.jar')
 >>> projectx('-name {0}'.format(basename),
 >>>          '-id {0},{1}'.format(videopid, audiopid),
 >>>          '-out {0}'.format(sg.dirname),
 >>>          '-cut {0}.cutlist'.format(rec.basename),
 >>>          absfile)
 >>> mplex = System('mplex')
 >>> mplex('-o {0}'.format(absfile+'.tmp'),
 >>>       '-V', '-f 9',
 >>>       os.path.join(sg.dirname, basename)+'.m2v',
 >>>       os.path.join(sg.dirname, basename)+audext)

Shuffle files, update database, rebuild seektable...

 >>> os.rename(absfile, absfile+'.old')
 >>> os.rename(absfile+'.tmp', absfile)
 >>> rec.update({'filesize':os.stat(absfile).st_size})
 >>> rec.mark.clean()
 >>> Job.fromRecorded(rec, Job.COMMFLAG, flags=Job.REBUILD)


More information about the mythtv-users mailing list