Ticket #6236: mythburn.py.3.diff

File mythburn.py.3.diff, 24.4 KB (added by brandons@…, 15 years ago)

Updated version.

  • mythburn.py

    old new  
    6767#*********************************************************************************
    6868#Dont change the stuff below!!
    6969#*********************************************************************************
    70 import os, string, socket, sys, getopt, traceback, signal
     70import os, popen2, string, socket, sys, getopt, traceback, signal
    7171import xml.dom.minidom
    7272import Image, ImageDraw, ImageFont, ImageColor
    7373import MySQLdb, codecs, unicodedata
     
    18211821        os.remove(sourcefile)
    18221822
    18231823#############################################################
     1824# Re-encodes a mv2 video stream
     1825
     1826def encodeVideo(sourcefile, destinationfile, aspectratio, profile, deletesourceafterencode):
     1827    """Encodes an mv2 source file use ffmpeg"""
     1828
     1829    profileNode = findEncodingProfile(profile)
     1830
     1831    passes = int(getText(profileNode.getElementsByTagName("passes")[0]))
     1832
     1833    command = path_ffmpeg[0]
     1834
     1835    if cpuCount > 1:
     1836        command += " -threads %d" % cpuCount
     1837
     1838
     1839    parameters = profileNode.getElementsByTagName("parameter")
     1840
     1841    for param in parameters:
     1842        name = param.attributes["name"].value
     1843        value = param.attributes["value"].value
     1844
     1845        # do some parameter substitution
     1846        if value == "%inputfile":
     1847            value = quoteFilename(sourcefile)
     1848        if value == "%outputfile":
     1849            #Encode elementry stream only
     1850            command += " -f mpeg2video"
     1851            value = quoteFilename(destinationfile)
     1852        if value == "%aspect":
     1853            value = aspectratio
     1854
     1855        if name != "":
     1856            command += " " + name
     1857
     1858        if value != "":
     1859            command += " " + value
     1860
     1861    if passes == 1:
     1862        write(command)
     1863        result = runCommand(command)
     1864        if result!=0:
     1865            fatalError("Failed while running ffmpeg to re-encode video.\n"
     1866                       "Command was %s" % command)
     1867
     1868    else:
     1869        passLog = os.path.join(getTempPath(), 'pass')
     1870
     1871        pass1 = string.replace(command, "%passno","1")
     1872        pass1 = string.replace(pass1, "%passlogfile", passLog)
     1873        write("Pass 1 - " + pass1)
     1874        result = runCommand(pass1)
     1875
     1876        if result!=0:
     1877            fatalError("Failed while running ffmpeg (Pass 1) to re-encode video.\n"
     1878                       "Command was %s" % command)
     1879
     1880        if os.path.exists(destinationfile):
     1881            os.remove(destinationfile)
     1882
     1883        pass2 = string.replace(command, "%passno","2")
     1884        pass2 = string.replace(pass2, "%passlogfile", passLog)
     1885        write("Pass 2 - " + pass2)
     1886        result = runCommand(pass2)
     1887
     1888        if result!=0:
     1889            fatalError("Failed while running ffmpeg (Pass 2) to re-encode video.\n"
     1890                       "Command was %s" % command)
     1891
     1892    if deletesourceafterencode==True:
     1893        os.remove(sourcefile)
     1894
     1895
     1896#############################################################
    18241897# Recombines a video and one or two audio streams back together
    18251898# adding in the NAV packets required to create a DVD
    18261899
     
    20412114            write("Failed to generate Project-X cutlist.")
    20422115            return False
    20432116
    2044     pxbasename = os.path.splitext(os.path.basename(file))[0]
    2045 
    20462117    if os.path.exists(file) != True:
    20472118        write("Error: input file doesn't exist on local filesystem")
    20482119        return False
    20492120
     2121    # Projectx does not like spaces in file names,
     2122    # create a symbolic link in destination folder.
     2123    if os.path.exists(os.path.join(folder, "inputfile" )):
     2124        os.remove(os.path.join(folder, "inputfile" ))
     2125    os.symlink(file, os.path.join(folder, "inputfile" ))
     2126
     2127    file = os.path.join(folder, "inputfile" )
     2128    pxbasename = "inputfile"
    20502129
    20512130    qdestdir = quoteFilename(folder)
    20522131    qpxbasename = quoteFilename(pxbasename)
    20532132    qfile = quoteFilename(file)
    2054     qcutlist = os.path.join(folder, "cutlist_x.txt")
     2133    qcutlist = quoteFilename(os.path.join(folder, "cutlist_x.txt"))
    20552134
    20562135    command = path_projectx[0] + " -id %s" % getStreamList(folder)
     2136
     2137    if addSubtitles:
     2138        (txtindex, txtpage) = findTeletextSubtitles(folder, file)
     2139        createProjectxIni(folder, txtpage)
     2140        if txtpage != "-1":
     2141            command += ",%s -ini %s" % (txtindex,os.path.join(folder, "projectx.ini"))
     2142        else:
     2143            command += " -ini %s" % (os.path.join(folder, "projectx.ini"))
     2144
    20572145    if usecutlist == True:
    20582146        command += " -cut %s -out %s -name %s %s" % (qcutlist, qdestdir, qpxbasename, qfile)
    20592147    else:
     
    21902278                    else:
    21912279                        os.rename(streamFiles[streamIds.index(stream)], os.path.join(folder, "stream1.mp2"))
    21922280
     2281            if streamFiles[streamIds.index(stream)].endswith(".sup"):
     2282                write("found subtitle streamID", False)
     2283                if os.path.exists(streamFiles[streamIds.index(stream)]):
     2284                    write("found subtitle stream file", False)
     2285                    os.rename(streamFiles[streamIds.index(stream)], os.path.join(folder, "stream.sup"))
     2286                    if os.path.exists(streamFiles[streamIds.index(stream)] + ".IFO"):
     2287                        os.rename(streamFiles[streamIds.index(stream)] + ".IFO", os.path.join(folder, "stream.sup.IFO"))
     2288                               
    21932289    # final chance to find the correct stream files
    21942290    if not os.path.exists(os.path.join(folder, "stream.mv2")):
    21952291        if os.path.exists(os.path.join(folder, pxbasename + ".m2v")):
     
    22172313    write("renameProjectXFiles end -----------------------------------------", False)
    22182314
    22192315#############################################################
     2316# Run projectx to look for teletext pages that hold subtitles
     2317
     2318def findTeletextSubtitles(folder, file):
     2319
     2320    # find captions
     2321    firststreamId = '-1'
     2322    firstlanguage = "N/A"
     2323    firstpage = '-1'
     2324
     2325    txtstreamId = '-1'
     2326    txtlanguage = "N/A"
     2327    txtpage = '-1'
     2328
     2329    streamId = '-1'
     2330    language = "N/A"
     2331    page = '-1'
     2332
     2333    qdestdir = quoteFilename(folder)
     2334    qfile = quoteFilename(file)
     2335
     2336    command = path_projectx[0] + " -out %s -name teletext_temp  %s" % (qdestdir, qfile)
     2337
     2338    projectx = popen2.Popen4(command,1)
     2339   
     2340    while projectx.poll() == -1:
     2341        line = projectx.fromchild.readline()
     2342
     2343        if len(line) == 0:
     2344            continue
     2345        if line.startswith("Teletext:"):
     2346            # we have found the teletext section
     2347            while 1:
     2348                line = projectx.fromchild.readline()
     2349                if line.startswith("Subpict.:"):
     2350                    break
     2351                index = line.find("PID: 0x")
     2352                if index >= 0:
     2353                    # found a stream
     2354                    streamId = line[index + 5:index + 10]
     2355                    write("Found Teletext stream: %s" % streamId, False)
     2356                    # get list of available pages
     2357                    pages = line[index + 11:-1]
     2358                    # strip trailing )
     2359                    closebrace = pages.find(")")
     2360                    if closebrace > 0:
     2361                        pages = pages[0:closebrace]
     2362                    # convert into array of pages
     2363                    pagelist = pages.split()
     2364   
     2365                    for pagedetails in pagelist:
     2366                        # look for caption pages
     2367                        index = pagedetails.find("_s")
     2368                        if index > 0:
     2369                            language = pagedetails[0:index]
     2370                            page = pagedetails[index+2:index+5]
     2371                            write("Found %s subtitles in page %s" % (language, page), False)
     2372                            if firstlanguage == "N/A":
     2373                                #retain first subtitles as fall back
     2374                                firstlanguage = language
     2375                                firstpage = page
     2376                                firststreamId = streamId
     2377                            if language == preferredlang1:
     2378                                txtlanguage = language
     2379                                txtpage = page
     2380                                txtstreamId = streamId
     2381                            else:
     2382                                if preferredlang1 != preferredlang2:
     2383                                    if language == preferredlang2 and txtlanguage == "N/A":
     2384                                        txtlanguage = language
     2385                                        txtpage = page
     2386                                        txtstreamId = streamId
     2387                               
     2388        if line.startswith("Subpict.:"):
     2389            break
     2390
     2391        if txtlanguage == preferredlang1:
     2392            break
     2393
     2394    if txtlanguage == "N/A":
     2395        txtlanguage = firstlanguage
     2396        txtpage = firstpage
     2397        txtstreamId = firststreamId
     2398
     2399    if txtlanguage != "N/A":
     2400        write("Found %s subtitles in PID: %s, at page %s" % (txtlanguage, txtstreamId, txtpage))
     2401    else:
     2402        write("Did not find any teletext subtitles")
     2403
     2404    #kill the projectx process, this is all we need from this run
     2405    os.system("pkill -P %d" % projectx.pid)
     2406    os.kill(projectx.pid,15)
     2407    projectx.wait()
     2408    return (streamId, txtpage)
     2409
     2410#############################################################
     2411# create an ini file
     2412
     2413def createProjectxIni(folder, txtpage):
     2414    if os.path.exists(os.path.join(folder, "projectx.ini" )):
     2415        os.remove(os.path.join(folder, "projectx.ini" ))
     2416    inif = open(os.path.join(folder, "projectx.ini"),"w")
     2417   
     2418    if txtpage != "-1":
     2419        inif.write("SubtitlePanel.TtxPage1=%s\n" % txtpage)
     2420        inif.write("SubtitlePanel.decodeHiddenRows=0\n")
     2421    inif.write("SubtitlePanel.SubtitleExportFormat=SUP\n")
     2422
     2423    inif.close()
     2424
     2425#############################################################
    22202426# convert time stamp to pts
    22212427
    22222428def ts2pts(time):
     
    48695075
    48705076    #do we need to re-encode the file to make it DVD compliant?
    48715077    if not isFileOkayForDVD(file, folder):
    4872         if getFileType(folder) == 'nuv':
    4873             #file is a nuv file which ffmpeg has problems reading so use mythtranscode to pass
    4874             #the video and audio streams to ffmpeg to do the reencode
    4875 
    4876             #we need to re-encode the file, make sure we get the right video/audio streams
    4877             #would be good if we could also split the file at the same time
    4878             getStreamInformation(mediafile, os.path.join(folder, "streaminfo.xml"), 0)
     5078        if string.lower(getVideoCodec(folder)) == "mpeg2video":
     5079            #we need to demultiplex the file using projectx,
     5080            #make sure we get the right video/audio streams,
     5081            #re-encode the video elementary stream to be dvd complient.
     5082            getStreamInformation(mediafile, os.path.join(folder, "streaminfo.xml"), 1)
    48795083
    48805084            #choose which streams we need
    48815085            video, audio1, audio2 = selectStreams(folder)
     
    48835087            #choose which aspect ratio we should use
    48845088            aspectratio = selectAspectRatio(folder)
    48855089
    4886             write("Re-encoding audio and video from nuv file")
     5090            # Run from local file?
     5091            if file.hasAttribute("localfilename"):
     5092                mediafile = file.attributes["localfilename"].value
     5093
     5094            # now attempt to split the source file into video and audio parts
     5095            # using projectX
     5096
     5097            # If this is a myth recording and there is a cut list available and the
     5098            # user wants to use it run projectx to cut out commercials etc
     5099            if file.attributes["type"].value == "recording":
     5100                if file.attributes["usecutlist"].value == "1" and getText(infoDOM.getElementsByTagName("hascutlist")[0]) == "yes":
     5101                    chanid = getText(infoDOM.getElementsByTagName("chanid")[0])
     5102                    starttime = getText(infoDOM.getElementsByTagName("starttime")[0])
     5103                    write("File has a cut list - running Project-X to remove unwanted segments")
     5104                    if not runProjectX(chanid, starttime, folder, True, mediafile):
     5105                        fatalError("Failed to run Project-X to remove unwanted segments and demux")
     5106                else:
     5107                    # no cutlist so just demux this file
     5108                    chanid = getText(infoDOM.getElementsByTagName("chanid")[0])
     5109                    starttime = getText(infoDOM.getElementsByTagName("starttime")[0])
     5110                    write("Using Project-X to demux file")
     5111                    if not runProjectX(chanid, starttime, folder, False, mediafile):
     5112                        fatalError("Failed to run Project-X to demux file")
     5113            else:
     5114                # just demux this file
     5115                chanid = -1
     5116                starttime = -1
     5117                write("Running Project-X to demux file")
     5118                if not runProjectX(chanid, starttime, folder, False, mediafile):
     5119                    fatalError("Failed to run Project-X to demux file")
     5120
     5121            write("Re-encoding video")
    48875122
    48885123            # what encoding profile should we use
    48895124            if file.hasAttribute("encodingprofile"):
     
    48915126            else:
    48925127                profile = defaultEncodingProfile
    48935128
    4894             if file.hasAttribute("localfilename"):
    4895                 mediafile = file.attributes["localfilename"].value
    4896                 chanid = -1
    4897                 starttime = -1
    4898                 usecutlist = -1
    4899             elif file.attributes["type"].value == "recording":
    4900                 mediafile = -1
    4901                 chanid = getText(infoDOM.getElementsByTagName("chanid")[0])
    4902                 starttime = getText(infoDOM.getElementsByTagName("starttime")[0])
    4903                 usecutlist = (file.attributes["usecutlist"].value == "1" and
    4904                             getText(infoDOM.getElementsByTagName("hascutlist")[0]) == "yes")
    4905             else:
    4906                 chanid = -1
    4907                 starttime = -1
    4908                 usecutlist = -1
    4909 
    4910             encodeNuvToMPEG2(chanid, starttime, mediafile, os.path.join(folder, "newfile2.mpg"), folder,
    4911                          profile, usecutlist)
    4912             mediafile = os.path.join(folder, 'newfile2.mpg')
     5129            #do the re-encode
     5130            encodeVideo(os.path.join(folder, "stream.mv2"), os.path.join(folder, "stream2.mv2"), aspectratio, profile, True)
     5131            if os.path.exists(os.path.join(folder, "stream2.mv2")):
     5132                os.rename(os.path.join(folder, "stream2.mv2"), os.path.join(folder, "stream.mv2"))
    49135133        else:
    4914             #we need to re-encode the file, make sure we get the right video/audio streams
    4915             #would be good if we could also split the file at the same time
    4916             getStreamInformation(mediafile, os.path.join(folder, "streaminfo.xml"), 0)
     5134            if getFileType(folder) == 'nuv':
     5135                #file is a nuv file which ffmpeg has problems reading so use mythtranscode to pass
     5136                #the video and audio streams to ffmpeg to do the reencode
    49175137
    4918             #choose which streams we need
    4919             video, audio1, audio2 = selectStreams(folder)
     5138                #we need to re-encode the file, make sure we get the right video/audio streams
     5139                #would be good if we could also split the file at the same time
     5140                getStreamInformation(mediafile, os.path.join(folder, "streaminfo.xml"), 0)
    49205141
    4921             #choose which aspect ratio we should use
    4922             aspectratio = selectAspectRatio(folder)
     5142                #choose which streams we need
     5143                video, audio1, audio2 = selectStreams(folder)
    49235144
    4924             write("Re-encoding audio and video")
     5145                #choose which aspect ratio we should use
     5146                aspectratio = selectAspectRatio(folder)
    49255147
    4926             # Run from local file?
    4927             if file.hasAttribute("localfilename"):
    4928                 mediafile = file.attributes["localfilename"].value
     5148                write("Re-encoding audio and video from nuv file")
    49295149
    4930             # what encoding profile should we use
    4931             if file.hasAttribute("encodingprofile"):
    4932                 profile = file.attributes["encodingprofile"].value
     5150                # what encoding profile should we use
     5151                if file.hasAttribute("encodingprofile"):
     5152                    profile = file.attributes["encodingprofile"].value
     5153                else:
     5154                    profile = defaultEncodingProfile
     5155
     5156                if file.hasAttribute("localfilename"):
     5157                    mediafile = file.attributes["localfilename"].value
     5158                    chanid = -1
     5159                    starttime = -1
     5160                    usecutlist = -1
     5161                elif file.attributes["type"].value == "recording":
     5162                    mediafile = -1
     5163                    chanid = getText(infoDOM.getElementsByTagName("chanid")[0])
     5164                    starttime = getText(infoDOM.getElementsByTagName("starttime")[0])
     5165                    usecutlist = (file.attributes["usecutlist"].value == "1" and
     5166                                getText(infoDOM.getElementsByTagName("hascutlist")[0]) == "yes")
     5167                else:
     5168                    chanid = -1
     5169                    starttime = -1
     5170                    usecutlist = -1
     5171
     5172                encodeNuvToMPEG2(chanid, starttime, mediafile, os.path.join(folder, "newfile2.mpg"), folder,
     5173                             profile, usecutlist)
     5174                mediafile = os.path.join(folder, 'newfile2.mpg')
    49335175            else:
    4934                 profile = defaultEncodingProfile
     5176                #we need to re-encode the file, make sure we get the right video/audio streams
     5177                #would be good if we could also split the file at the same time
     5178                getStreamInformation(mediafile, os.path.join(folder, "streaminfo.xml"), 0)
    49355179
    4936             #do the re-encode
    4937             encodeVideoToMPEG2(mediafile, os.path.join(folder, "newfile2.mpg"), video,
    4938                             audio1, audio2, aspectratio, profile)
    4939             mediafile = os.path.join(folder, 'newfile2.mpg')
     5180                #choose which streams we need
     5181                video, audio1, audio2 = selectStreams(folder)
    49405182
    4941     #remove an intermediate file
    4942     if os.path.exists(os.path.join(folder, "newfile1.mpg")):
    4943         os.remove(os.path.join(folder,'newfile1.mpg'))
     5183                #choose which aspect ratio we should use
     5184                aspectratio = selectAspectRatio(folder)
    49445185
    4945     # the file is now DVD compliant now we need to remove commercials
    4946     # and split it into video, audio, subtitle parts
     5186                write("Re-encoding audio and video")
    49475187
    4948     # find out what streams we have available now
    4949     getStreamInformation(mediafile, os.path.join(folder, "streaminfo.xml"), 1)
     5188                # Run from local file?
     5189                if file.hasAttribute("localfilename"):
     5190                    mediafile = file.attributes["localfilename"].value
    49505191
    4951     # choose which streams we need
    4952     video, audio1, audio2 = selectStreams(folder)
     5192                # what encoding profile should we use
     5193                if file.hasAttribute("encodingprofile"):
     5194                    profile = file.attributes["encodingprofile"].value
     5195                else:
     5196                    profile = defaultEncodingProfile
    49535197
    4954     # now attempt to split the source file into video and audio parts
    4955     # using projectX
     5198                #do the re-encode
     5199                encodeVideoToMPEG2(mediafile, os.path.join(folder, "newfile2.mpg"), video,
     5200                                audio1, audio2, aspectratio, profile)
     5201                mediafile = os.path.join(folder, 'newfile2.mpg')
    49565202
    4957     # If this is an mpeg2 myth recording and there is a cut list available and the
    4958     # user wants to use it run projectx to cut out commercials etc
    4959     if file.attributes["type"].value == "recording":
    4960         if file.attributes["usecutlist"].value == "1" and getText(infoDOM.getElementsByTagName("hascutlist")[0]) == "yes":
    4961             chanid = getText(infoDOM.getElementsByTagName("chanid")[0])
    4962             starttime = getText(infoDOM.getElementsByTagName("starttime")[0])
    4963             write("File has a cut list - running Project-X to remove unwanted segments")
    4964             if not runProjectX(chanid, starttime, folder, True, mediafile):
    4965                 fatalError("Failed to run Project-X to remove unwanted segments and demux")
    4966         else:
    4967             # no cutlist so just demux this file
    4968             chanid = getText(infoDOM.getElementsByTagName("chanid")[0])
    4969             starttime = getText(infoDOM.getElementsByTagName("starttime")[0])
    4970             write("Using Project-X to demux file")
     5203            #remove an intermediate file
     5204            if os.path.exists(os.path.join(folder, "newfile1.mpg")):
     5205                os.remove(os.path.join(folder,'newfile1.mpg'))
     5206
     5207            # the file is now DVD compliant split it into video and audio parts
     5208
     5209            # find out what streams we have available now
     5210            getStreamInformation(mediafile, os.path.join(folder, "streaminfo.xml"), 1)
     5211
     5212            # choose which streams we need
     5213            video, audio1, audio2 = selectStreams(folder)
     5214
     5215            # now attempt to split the source file into video and audio parts
     5216            # using projectX
     5217
     5218            # If this is an mpeg2 myth recording and there is a cut list available and the
     5219            # user wants to use it run projectx to cut out commercials etc
     5220            if file.attributes["type"].value == "recording":
     5221                # no cutlist so just demux this file
     5222                chanid = getText(infoDOM.getElementsByTagName("chanid")[0])
     5223                starttime = getText(infoDOM.getElementsByTagName("starttime")[0])
     5224                write("Using Project-X to demux file")
     5225                if not runProjectX(chanid, starttime, folder, False, mediafile):
     5226                    fatalError("Failed to run Project-X to demux file")
     5227            else:
     5228                # just demux this file
     5229                chanid = -1
     5230                starttime = -1
     5231                write("Running Project-X to demux file")
     5232                if not runProjectX(chanid, starttime, folder, False, mediafile):
     5233                    fatalError("Failed to run Project-X to demux file")
     5234
     5235       
     5236    else:
     5237        #remove an intermediate file
     5238        if os.path.exists(os.path.join(folder, "newfile1.mpg")):
     5239            os.remove(os.path.join(folder,'newfile1.mpg'))
     5240
     5241        # the file is now DVD compliant now we need to remove commercials
     5242        # and split it into video, audio, subtitle parts
     5243
     5244        # find out what streams we have available now
     5245        getStreamInformation(mediafile, os.path.join(folder, "streaminfo.xml"), 1)
     5246
     5247        # choose which streams we need
     5248        video, audio1, audio2 = selectStreams(folder)
     5249
     5250        # now attempt to split the source file into video and audio parts
     5251        # using projectX
     5252
     5253        # If this is an mpeg2 myth recording and there is a cut list available and the
     5254        # user wants to use it run projectx to cut out commercials etc
     5255        if file.attributes["type"].value == "recording":
     5256            if file.attributes["usecutlist"].value == "1" and getText(infoDOM.getElementsByTagName("hascutlist")[0]) == "yes":
     5257                chanid = getText(infoDOM.getElementsByTagName("chanid")[0])
     5258                starttime = getText(infoDOM.getElementsByTagName("starttime")[0])
     5259                write("File has a cut list - running Project-X to remove unwanted segments")
     5260                if not runProjectX(chanid, starttime, folder, True, mediafile):
     5261                    fatalError("Failed to run Project-X to remove unwanted segments and demux")
     5262            else:
     5263                # no cutlist so just demux this file
     5264                chanid = getText(infoDOM.getElementsByTagName("chanid")[0])
     5265                starttime = getText(infoDOM.getElementsByTagName("starttime")[0])
     5266                write("Using Project-X to demux file")
     5267                if not runProjectX(chanid, starttime, folder, False, mediafile):
     5268                    fatalError("Failed to run Project-X to demux file")
     5269        else:
     5270            # just demux this file
     5271            chanid = -1
     5272            starttime = -1
     5273            write("Running Project-X to demux file")
    49715274            if not runProjectX(chanid, starttime, folder, False, mediafile):
    49725275                fatalError("Failed to run Project-X to demux file")
    4973     else:
    4974         # just demux this file
    4975         chanid = -1
    4976         starttime = -1
    4977         write("Running Project-X to demux file")
    4978         if not runProjectX(chanid, starttime, folder, False, mediafile):
    4979             fatalError("Failed to run Project-X to demux file")
    49805276
    49815277    # we now have a video stream and one or more audio streams
    49825278    # check if we need to convert any of the audio streams to ac3