| 1825 | # Re-encodes a mv2 video stream |
| 1826 | |
| 1827 | def encodeVideo(sourcefile, destinationfile, aspectratio, profile, deletesourceafterencode): |
| 1828 | """Encodes an mv2 source file use ffmpeg""" |
| 1829 | |
| 1830 | profileNode = findEncodingProfile(profile) |
| 1831 | |
| 1832 | passes = int(getText(profileNode.getElementsByTagName("passes")[0])) |
| 1833 | |
| 1834 | command = path_ffmpeg[0] |
| 1835 | |
| 1836 | if cpuCount > 1: |
| 1837 | command += " -threads %d" % cpuCount |
| 1838 | |
| 1839 | |
| 1840 | parameters = profileNode.getElementsByTagName("parameter") |
| 1841 | |
| 1842 | for param in parameters: |
| 1843 | name = param.attributes["name"].value |
| 1844 | value = param.attributes["value"].value |
| 1845 | |
| 1846 | # do some parameter substitution |
| 1847 | if value == "%inputfile": |
| 1848 | value = quoteFilename(sourcefile) |
| 1849 | if value == "%outputfile": |
| 1850 | #Encode elementry stream only |
| 1851 | command += " -f mpeg2video" |
| 1852 | value = quoteFilename(destinationfile) |
| 1853 | if value == "%aspect": |
| 1854 | value = aspectratio |
| 1855 | |
| 1856 | if name != "": |
| 1857 | command += " " + name |
| 1858 | |
| 1859 | if value != "": |
| 1860 | command += " " + value |
| 1861 | |
| 1862 | if passes == 1: |
| 1863 | write(command) |
| 1864 | result = runCommand(command) |
| 1865 | if result!=0: |
| 1866 | fatalError("Failed while running ffmpeg to re-encode video.\n" |
| 1867 | "Command was %s" % command) |
| 1868 | |
| 1869 | else: |
| 1870 | passLog = os.path.join(getTempPath(), 'pass') |
| 1871 | |
| 1872 | pass1 = string.replace(command, "%passno","1") |
| 1873 | pass1 = string.replace(pass1, "%passlogfile", passLog) |
| 1874 | write("Pass 1 - " + pass1) |
| 1875 | result = runCommand(pass1) |
| 1876 | |
| 1877 | if result!=0: |
| 1878 | fatalError("Failed while running ffmpeg (Pass 1) to re-encode video.\n" |
| 1879 | "Command was %s" % command) |
| 1880 | |
| 1881 | if os.path.exists(destinationfile): |
| 1882 | os.remove(destinationfile) |
| 1883 | |
| 1884 | pass2 = string.replace(command, "%passno","2") |
| 1885 | pass2 = string.replace(pass2, "%passlogfile", passLog) |
| 1886 | write("Pass 2 - " + pass2) |
| 1887 | result = runCommand(pass2) |
| 1888 | |
| 1889 | if result!=0: |
| 1890 | fatalError("Failed while running ffmpeg (Pass 2) to re-encode video.\n" |
| 1891 | "Command was %s" % command) |
| 1892 | |
| 1893 | if deletesourceafterencode==True: |
| 1894 | os.remove(sourcefile) |
| 1895 | |
| 1896 | |
| 1897 | ############################################################# |
| 2316 | # Run projectx to look for teletext pages that hold subtitles |
| 2317 | |
| 2318 | def 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 | break |
| 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 | |
| 2413 | def 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 | ############################################################# |
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") |
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")) |
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') |
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") |