Even more linting: no more variable with camel case.
This commit is contained in:
295
removeads.py
295
removeads.py
@@ -53,7 +53,14 @@ from iso639.exceptions import InvalidLanguageValue
|
||||
# Then finally, change the Private Codec Data in the final MKV.
|
||||
|
||||
|
||||
def checkRequiredTools():
|
||||
def checkRequiredTools() -> tuple[bool,list[str]]:
|
||||
"""Check if required external tools are installed.
|
||||
|
||||
Args:
|
||||
|
||||
Returns:
|
||||
tuple[bool, list[str]] : does all optional tools are installed and the paths of all tools.
|
||||
"""
|
||||
logger = logging.getLogger(__name__)
|
||||
all_optional_tools = True
|
||||
paths = {}
|
||||
@@ -76,7 +83,15 @@ def checkRequiredTools():
|
||||
|
||||
return all_optional_tools, paths
|
||||
|
||||
def getTesseractSupportedLang(tesseract):
|
||||
def getTesseractSupportedLang(tesseract:str) -> dict[str,str]|None:
|
||||
"""Returns the set of natural languages supported by Tesseract OCR tool.
|
||||
|
||||
Args:
|
||||
tesseract: str: path to tesseract binary.
|
||||
|
||||
Returns:
|
||||
dict[str, str] : a mapping ....
|
||||
"""
|
||||
logger = logging.getLogger(__name__)
|
||||
res = {}
|
||||
|
||||
@@ -102,7 +117,7 @@ def getTesseractSupportedLang(tesseract):
|
||||
|
||||
return res
|
||||
|
||||
def getFrameRate(ffprobe, inputFile):
|
||||
def getFrameRate(ffprobe:str, inputFile) -> float|None:
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
infd = inputFile.fileno()
|
||||
@@ -167,7 +182,7 @@ def getFrameRate(ffprobe, inputFile):
|
||||
|
||||
return None
|
||||
|
||||
def getSubTitlesTracks(ffprobe, mkvPath):
|
||||
def getSubTitlesTracks(ffprobe:str, mkvPath: str) -> dict[str,str]|None:
|
||||
logger = logging.getLogger(__name__)
|
||||
tracks={}
|
||||
|
||||
@@ -199,7 +214,7 @@ def getSubTitlesTracks(ffprobe, mkvPath):
|
||||
|
||||
return tracks
|
||||
|
||||
def extractSRT(mkvextract, fileName, subtitles, langs):
|
||||
def extractSRT(mkvextract:str, fileName:str, subtitles:str, langs:list[str]) -> list|None:
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
params = [mkvextract, fileName, 'tracks']
|
||||
@@ -279,7 +294,7 @@ def doOCR(vobsubocr, idxs, duration, temporaries, dumpMemFD=False):
|
||||
write(srtfd, line.encode(encoding='UTF-8'))
|
||||
|
||||
m = re.match(timestamps, line)
|
||||
if m!=None:
|
||||
if m is not None:
|
||||
hours = int(m.group('hours'))
|
||||
minutes = int(m.group('hours'))
|
||||
seconds = int(m.group('seconds'))
|
||||
@@ -499,11 +514,11 @@ def parseRBSPTrailingBits(buf, bit_position):
|
||||
|
||||
bit_position, one = readBit(buf, bit_position)
|
||||
if one==0:
|
||||
raise Exception(f'Stop bit should be equal to one. Read: {one:d}')
|
||||
raise ValueError(f'Stop bit should be equal to one. Read: {one:d}')
|
||||
while bit_position%8 != 0:
|
||||
bit_position, zero = readBit(buf, bit_position)
|
||||
if zero==1:
|
||||
raise Exception('Trailing bit should be equal to zero')
|
||||
raise ValueError('Trailing bit should be equal to zero')
|
||||
|
||||
return bit_position
|
||||
|
||||
@@ -534,7 +549,7 @@ def moreRBSPData(buf, bit_position):
|
||||
break
|
||||
|
||||
if not found:
|
||||
raise Exception('Impossible to find trailing stop bit !')
|
||||
raise ValueError('Impossible to find trailing stop bit !')
|
||||
|
||||
# No more data
|
||||
if bit_position == pos:
|
||||
@@ -888,20 +903,10 @@ class SPS:
|
||||
logger = logging.getLogger(__name__)
|
||||
x264opts = []
|
||||
|
||||
if self.profile_idc in [ 0x42, 0x4D, 0x64, 0x6E, 0x7A, 0xF4, 0x2C]:
|
||||
if self.profile_idc == 0x42:
|
||||
profile = 'baseline'
|
||||
elif self.profile_idc == 0x4D:
|
||||
profile = 'main'
|
||||
elif self.profile_idc == 0x64 :
|
||||
profile = 'high'
|
||||
elif self.profile_idc == 0x6E:
|
||||
profile = 'high10'
|
||||
elif self.profile_idc == 0x7A:
|
||||
profile = 'high422'
|
||||
elif self.profile_idc == 0xF4:
|
||||
profile = 'high444'
|
||||
else:
|
||||
try:
|
||||
profile = {0x42:'baseline', 0x4D:'main', 0x64:'high', 0x6E:'high10', 0x7A:'high422',
|
||||
0xF4:'high444'}[self.profile_idc]
|
||||
except KeyError:
|
||||
logger.error('Unknow profile: %x', self.profile_idc)
|
||||
return []
|
||||
|
||||
@@ -942,13 +947,13 @@ class SPS:
|
||||
# NAL Unit SPS
|
||||
bit_position, zero = readBit(buf, bit_position)
|
||||
if zero != 0:
|
||||
raise Exception(f'Reserved bit is not equal to 0: {zero:d}')
|
||||
raise ValueError(f'Reserved bit is not equal to 0: {zero:d}')
|
||||
bit_position, nal_ref_idc = readBits(buf, bit_position,2)
|
||||
if nal_ref_idc != 3:
|
||||
raise Exception(f'NAL ref idc is not equal to 3: {nal_ref_idc:d}')
|
||||
raise ValueError(f'NAL ref idc is not equal to 3: {nal_ref_idc:d}')
|
||||
bit_position, nal_unit_type = readBits(buf, bit_position,5)
|
||||
if nal_unit_type != 7:
|
||||
raise Exception(f'NAL unit type is not a SPS: {nal_unit_type:d}')
|
||||
raise ValueError(f'NAL unit type is not a SPS: {nal_unit_type:d}')
|
||||
|
||||
bit_position, self.profile_idc = readByte(buf, bit_position)
|
||||
bit_position, self.constraint_set0_flag = readBit(buf,bit_position)
|
||||
@@ -959,7 +964,7 @@ class SPS:
|
||||
bit_position, self.constraint_set5_flag = readBit(buf,bit_position)
|
||||
bit_position, v = readBits(buf, bit_position, 2)
|
||||
if v!=0:
|
||||
raise Exception(f'Reserved bits different from 0b00: {v:x}')
|
||||
raise ValueError(f'Reserved bits different from 0b00: {v:x}')
|
||||
bit_position, self.level_idc = readByte(buf, bit_position)
|
||||
bit_position, self.seq_parameter_set_id = readUnsignedExpGolomb(buf, bit_position)
|
||||
if self.profile_idc in [44, 83, 86, 100, 110, 118, 122, 128, 134, 135, 138, 139, 244]:
|
||||
@@ -1153,13 +1158,13 @@ class PPS:
|
||||
# NAL Unit PPS
|
||||
bit_position, zero = readBit(buf, bit_position)
|
||||
if zero != 0:
|
||||
raise Exception(f'Reserved bit is not equal to 0: {zero:d}')
|
||||
raise ValueError(f'Reserved bit is not equal to 0: {zero:d}')
|
||||
bit_position, nal_ref_idc = readBits(buf, bit_position,2)
|
||||
if nal_ref_idc != 3:
|
||||
raise Exception(f'NAL ref idc is not equal to 3: {nal_ref_idc:d}')
|
||||
raise ValueError(f'NAL ref idc is not equal to 3: {nal_ref_idc:d}')
|
||||
bit_position, nal_unit_type = readBits(buf, bit_position,5)
|
||||
if nal_unit_type != 8:
|
||||
raise Exception(f'NAL unit type is not a PPS: {nal_unit_type:d}')
|
||||
raise ValueError(f'NAL unit type is not a PPS: {nal_unit_type:d}')
|
||||
|
||||
bit_position, self.pic_parameter_set_id = readUnsignedExpGolomb(buf, bit_position)
|
||||
bit_position, self.seq_parameter_set_id = readUnsignedExpGolomb(buf, bit_position)
|
||||
@@ -1348,17 +1353,17 @@ class AVCDecoderConfiguration:
|
||||
bit_position, self.AVCLevelIndication = readByte(buf, bit_position)
|
||||
bit_position, v = readBits(buf, bit_position, 6)
|
||||
if v != 0b111111:
|
||||
raise Exception(f'Reserved bits are not equal to 0b111111: {v:x}')
|
||||
raise ValueError(f'Reserved bits are not equal to 0b111111: {v:x}')
|
||||
bit_position, self.lengthSizeMinusOne = readBits(buf, bit_position, 2)
|
||||
bit_position, v = readBits(buf, bit_position, 3)
|
||||
if v != 0b111:
|
||||
raise Exception(f'Reserved bits are not equal to 0b111: {v:x}')
|
||||
raise ValueError(f'Reserved bits are not equal to 0b111: {v:x}')
|
||||
bit_position, self.numOfSequenceParameterSets= readBits(buf, bit_position, 5)
|
||||
logger.debug('Number of SPS: %d', self.numOfSequenceParameterSets)
|
||||
for _ in range(0,self.numOfSequenceParameterSets):
|
||||
bit_position, length = readWord(buf, bit_position)
|
||||
if bit_position % 8 != 0:
|
||||
raise Exception(f'SPS is not located at a byte boundary: {bit_position:d}')
|
||||
raise ValueError(f'SPS is not located at a byte boundary: {bit_position:d}')
|
||||
|
||||
sps = SPS()
|
||||
sodb = RBSP2SODB(buf[floor(bit_position/8):])
|
||||
@@ -1381,7 +1386,7 @@ class AVCDecoderConfiguration:
|
||||
for _ in range(0,self.numOfPictureParameterSets):
|
||||
bit_position, length = readWord(buf, bit_position)
|
||||
if bit_position % 8 != 0:
|
||||
raise Exception('PPS is not located at a byte boundary: {bit_position:d}')
|
||||
raise ValueError('PPS is not located at a byte boundary: {bit_position:d}')
|
||||
|
||||
pps = PPS()
|
||||
sodb = RBSP2SODB(buf[floor(bit_position/8):])
|
||||
@@ -1402,15 +1407,15 @@ class AVCDecoderConfiguration:
|
||||
if self.AVCProfileIndication in [100, 110, 122, 144]:
|
||||
bit_position, reserved = readBits(buf, bit_position, 6)
|
||||
if reserved != 0b111111:
|
||||
raise Exception(f'Reserved bits are different from 111111: {reserved:x}')
|
||||
raise ValueError(f'Reserved bits are different from 111111: {reserved:x}')
|
||||
bit_position, self.chroma_format = readBits(buf, bit_position, 2)
|
||||
bit_position, reserved = readBits(buf, bit_position, 5)
|
||||
if reserved != 0b11111:
|
||||
raise Exception(f'Reserved bits are different from 11111: {reserved:x}')
|
||||
raise ValueError(f'Reserved bits are different from 11111: {reserved:x}')
|
||||
bit_position, self.bit_depth_luma_minus8 = readBits(buf, bit_position, 3)
|
||||
bit_position, reserved = readBits(buf, bit_position, 5)
|
||||
if reserved != 0b11111:
|
||||
raise Exception(f'Reserved bits are different from 11111: {reserved:x}')
|
||||
raise ValueError(f'Reserved bits are different from 11111: {reserved:x}')
|
||||
bit_position, self.bit_depth_chroma_minus8 = readBits(buf, bit_position, 3)
|
||||
bit_position, self.numOfSequenceParameterSetExt = readByte(buf, bit_position)
|
||||
for _ in range(0, self.numOfSequenceParameterSetExt):
|
||||
@@ -1482,28 +1487,28 @@ class AVCDecoderConfiguration:
|
||||
def merge(self, config):
|
||||
# Check config compatibility
|
||||
if self.configurationVersion != config.configurationVersion:
|
||||
raise Exception('Configuration versions are different: %d vs %s' %\
|
||||
raise ValueError('Configuration versions are different: %d vs %s' %\
|
||||
(self.configurationVersion, config.configurationVersion))
|
||||
if self.AVCProfileIndication != config.AVCProfileIndication:
|
||||
raise Exception('AVC profiles are different: %d vs %s' %\
|
||||
raise ValueError('AVC profiles are different: %d vs %s' %\
|
||||
(self.AVCProfileIndication, config.AVCProfileIndication))
|
||||
if self.profile_compatibility != config.profile_compatibility:
|
||||
raise Exception('Profile compatilities are different: %d vs %s' %\
|
||||
raise ValueError('Profile compatilities are different: %d vs %s' %\
|
||||
(self.profile_compatibility, config.profile_compatibility))
|
||||
if self.AVCLevelIndication != config.AVCLevelIndication:
|
||||
raise Exception('Level indications are different: %d vs %s' %\
|
||||
raise ValueError('Level indications are different: %d vs %s' %\
|
||||
(self.AVCLevelIndication, config.AVCLevelIndication))
|
||||
if self.lengthSizeMinusOne != config.lengthSizeMinusOne:
|
||||
raise Exception('Length units are different: %d vs %s' %\
|
||||
raise ValueError('Length units are different: %d vs %s' %\
|
||||
(self.lengthSizeMinusOne, config.lengthSizeMinusOne))
|
||||
if self.chroma_format != config.chroma_format:
|
||||
raise Exception('Colour format are different: %d vs %s' %\
|
||||
raise ValueError('Colour format are different: %d vs %s' %\
|
||||
(self.chroma_format, config.chroma_format))
|
||||
if self.bit_depth_luma_minus8 != config.bit_depth_luma_minus8:
|
||||
raise Exception('Depth of luminance are different: %d vs %s' %\
|
||||
raise ValueError('Depth of luminance are different: %d vs %s' %\
|
||||
(self.bit_depth_luma_minus8, config.bit_depth_luma_minus8))
|
||||
if self.bit_depth_chroma_minus8 != config.bit_depth_chroma_minus8:
|
||||
raise Exception('Depth of chromaticity are different: %d vs %s' %\
|
||||
raise ValueError('Depth of chromaticity are different: %d vs %s' %\
|
||||
(self.bit_depth_chroma_minus8, config.bit_depth_luma_minus8))
|
||||
|
||||
for spsid in config.sps:
|
||||
@@ -1511,7 +1516,7 @@ class AVCDecoderConfiguration:
|
||||
if spsid in self.sps:
|
||||
localsps = self.sps[spsid]
|
||||
if sps!=localsps:
|
||||
raise Exception(f'Profile are not compatible. They contain two different SPS\
|
||||
raise ValueError(f'Profile are not compatible. They contain two different SPS\
|
||||
with the same identifier ({spsid:d}): {localsps}\n{sps}\n')
|
||||
self.sps[spsid] = sps
|
||||
|
||||
@@ -1522,7 +1527,7 @@ class AVCDecoderConfiguration:
|
||||
if ppsid in self.pps:
|
||||
localpps = self.pps[ppsid]
|
||||
if pps!=localpps:
|
||||
raise Exception(f'Profile are not compatible. They contain two different PPS\
|
||||
raise ValueError(f'Profile are not compatible. They contain two different PPS\
|
||||
with the same identifier ({ppsid:d}): {localpps}\n{pps}\n')
|
||||
self.pps[ppsid] = pps
|
||||
|
||||
@@ -1532,12 +1537,12 @@ class AVCDecoderConfiguration:
|
||||
|
||||
def parseCodecPrivate(codecPrivateData):
|
||||
if codecPrivateData[0] != 0x63:
|
||||
raise Exception(f'Matroska header is wrong: {codecPrivateData[0]:x}')
|
||||
raise ValueError(f'Matroska header is wrong: {codecPrivateData[0]:x}')
|
||||
if codecPrivateData[1] != 0xA2:
|
||||
raise Exception(f'Matroska header is wrong: {codecPrivateData[1]:x}')
|
||||
raise ValueError(f'Matroska header is wrong: {codecPrivateData[1]:x}')
|
||||
length = codecPrivateData[2]
|
||||
if length == 0:
|
||||
raise Exception('Matroska length cannot start with zero byte.')
|
||||
raise ValueError('Matroska length cannot start with zero byte.')
|
||||
for nb_zeroes in range(0,8):
|
||||
b = readBit(codecPrivateData[2:], nb_zeroes)
|
||||
if b != 0:
|
||||
@@ -1563,14 +1568,14 @@ def getAvcConfigFromH264(inputFile):
|
||||
bit_position = 0
|
||||
bit_position, start_code = readLong(sodb, bit_position)
|
||||
if start_code != 1:
|
||||
raise Exception(f'Starting code not detected: {start_code:x}')
|
||||
raise ValueError(f'Starting code not detected: {start_code:x}')
|
||||
sps = SPS()
|
||||
bit_length = sps.fromBytes(sodb[4:])
|
||||
bit_position+=bit_length
|
||||
|
||||
bit_position, start_code = readLong(sodb, bit_position)
|
||||
if start_code != 1:
|
||||
raise Exception('Starting code not detected: {start_code:x}')
|
||||
raise ValueError(f'Starting code not detected: {start_code:x}')
|
||||
pps = PPS()
|
||||
bit_length = pps.fromBytes(sodb[floor(bit_position/8):], sps.chroma_format_idc)
|
||||
logger.debug(pps)
|
||||
@@ -1625,7 +1630,7 @@ def parseMKVTree(mkvinfo, inputFile):
|
||||
else:
|
||||
position = int(m.group('position'))
|
||||
size = int(m.group('size'))
|
||||
root = m.group('root')!=None
|
||||
root = m.group('root') is not None
|
||||
if root:
|
||||
depth = 0
|
||||
else:
|
||||
@@ -2490,18 +2495,17 @@ def dumpPPM(pictures, prefix, temporaries):
|
||||
|
||||
header_len=2+1+ceil(log(width, 10))+1+ceil(log(height, 10))+1+3+1
|
||||
try:
|
||||
out = open(filename, 'w', encoding='utf8')
|
||||
outfd = out.fileno()
|
||||
with open(filename, 'w', encoding='utf8') as out:
|
||||
temporaries.append(out)
|
||||
outfd = out.fileno()
|
||||
length=header_len+3*width*height
|
||||
nb_bytes = 0
|
||||
while nb_bytes < length:
|
||||
nb_bytes+=write(outfd, pictures[pos+nb_bytes:pos+length])
|
||||
pos+=length
|
||||
picture+=1
|
||||
except IOError:
|
||||
logger.error('Impossible to create file: %s', filename)
|
||||
temporaries.append(out)
|
||||
|
||||
length=header_len+3*width*height
|
||||
nb_bytes = 0
|
||||
while nb_bytes < length:
|
||||
nb_bytes+=write(outfd, pictures[pos+nb_bytes:pos+length])
|
||||
pos+=length
|
||||
picture+=1
|
||||
|
||||
|
||||
def extractAllStreams(ffmpeg, ffprobe, inputFile, begin, end, streams, filesPrefix, nbFrames,
|
||||
@@ -2629,17 +2633,16 @@ def extractAllStreams(ffmpeg, ffprobe, inputFile, begin, end, streams, filesPref
|
||||
|
||||
if dumpMemFD:
|
||||
try:
|
||||
output = open(tmpname,'w', encoding='utf8')
|
||||
with open(tmpname,'w', encoding='utf8') as output:
|
||||
temporaries.append(output)
|
||||
outfd = output.fileno()
|
||||
pos = 0
|
||||
while pos < len(sound_bytes):
|
||||
pos+=write(outfd, sound_bytes[pos:])
|
||||
except IOError:
|
||||
logger.error('Impossible to create file: %s', tmpname)
|
||||
return None
|
||||
|
||||
outfd = output.fileno()
|
||||
pos = 0
|
||||
while pos < len(sound_bytes):
|
||||
pos+=write(outfd, sound_bytes[pos:])
|
||||
temporaries.append(output)
|
||||
|
||||
# We rewind to zero the memory file descriptor
|
||||
lseek(memfd, 0, SEEK_SET)
|
||||
set_inheritable(memfd, True)
|
||||
@@ -3351,65 +3354,65 @@ def main():
|
||||
|
||||
# Creating MKV file that corresponds to current part between I-frames
|
||||
# Internal video with all streams (video, audio and subtitles)
|
||||
internalMKVName = f'part-{partnum:d}-internal.mkv'
|
||||
internal_mkv_name = f'part-{partnum:d}-internal.mkv'
|
||||
# Internal video stream as a raw H264 stream
|
||||
internalH264Name = f'part-{partnum:d}-internal.h264'
|
||||
internal_h264_name = f'part-{partnum:d}-internal.h264'
|
||||
# Internal video timestamps
|
||||
internalH264TSName = f'part-{partnum:d}-internal-ts.txt'
|
||||
internal_h264_ts_name = f'part-{partnum:d}-internal-ts.txt'
|
||||
# Internal video with only audio and subtitles streams
|
||||
internalNoVideoMKVName = f'part-{partnum:d}-internal-novideo.mkv'
|
||||
internal_novideo_mkv_name = f'part-{partnum:d}-internal-novideo.mkv'
|
||||
|
||||
try:
|
||||
internalMKV = open(internalMKVName, 'w+', encoding='utf8')
|
||||
internal_mkv = open(internal_mkv_name, 'w+', encoding='utf8')
|
||||
except IOError:
|
||||
logger.error('Impossible to create file: %s', internalMKVName)
|
||||
logger.error('Impossible to create file: %s', internal_mkv_name)
|
||||
exit(-1)
|
||||
|
||||
try:
|
||||
internalNoVideoMKV = open(internalNoVideoMKVName, 'w+', encoding='utf8')
|
||||
internal_novideo_mkv = open(internal_novideo_mkv_name, 'w+', encoding='utf8')
|
||||
except IOError:
|
||||
logger.error('Impossible to create file: %s', internalNoVideoMKVName)
|
||||
logger.error('Impossible to create file: %s', internal_novideo_mkv_name)
|
||||
exit(-1)
|
||||
|
||||
try:
|
||||
internalH264 = open(internalH264Name, 'w+', encoding='utf8')
|
||||
internal_h264 = open(internal_h264_name, 'w+', encoding='utf8')
|
||||
except IOError:
|
||||
logger.error('Impossible to create file: %s', internalH264Name)
|
||||
logger.error('Impossible to create file: %s', internal_h264_name)
|
||||
exit(-1)
|
||||
|
||||
try:
|
||||
internalH264TS = open(internalH264TSName, 'w+', encoding='utf8')
|
||||
internal_h264_ts = open(internal_h264_ts_name, 'w+', encoding='utf8')
|
||||
except IOError:
|
||||
logger.error('Impossible to create file: %s', internalH264TSName)
|
||||
logger.error('Impossible to create file: %s', internal_h264_ts_name)
|
||||
exit(-1)
|
||||
|
||||
# logger.info('Merge header, middle and trailer subpart into: %s' % internalMKVName)
|
||||
# logger.info('Merge header, middle and trailer subpart into: %s' % internal_mkv_name)
|
||||
# Extract internal part of MKV
|
||||
extractMKVPart(mkvmerge=paths['mkvmerge'], inputFile=mkv, outputFile=internalMKV,
|
||||
extractMKVPart(mkvmerge=paths['mkvmerge'], inputFile=mkv, outputFile=internal_mkv,
|
||||
begin=head_iframe_ts, end=tail_iframe_ts)
|
||||
|
||||
# Extract video stream of internal part as a raw H264 and its timestamps.
|
||||
logger.info('Extract video track as raw H264 file.')
|
||||
extractTrackFromMKV(mkvextract=paths['mkvextract'], inputFile=internalMKV, index=0,
|
||||
outputFile=internalH264, timestamps=internalH264TS)
|
||||
extractTrackFromMKV(mkvextract=paths['mkvextract'], inputFile=internal_mkv, index=0,
|
||||
outputFile=internal_h264, timestamps=internal_h264_ts)
|
||||
|
||||
# Remove video track from internal part of MKV
|
||||
logger.info('Remove video track from %s', internalMKVName)
|
||||
removeVideoTracksFromMKV(mkvmerge=paths['mkvmerge'], inputFile=internalMKV,
|
||||
outputFile=internalNoVideoMKV)
|
||||
logger.info('Remove video track from %s', internal_mkv_name)
|
||||
removeVideoTracksFromMKV(mkvmerge=paths['mkvmerge'], inputFile=internal_mkv,
|
||||
outputFile=internal_novideo_mkv)
|
||||
|
||||
temporaries.append(internalMKV)
|
||||
temporaries.append(internalH264)
|
||||
temporaries.append(internalH264TS)
|
||||
temporaries.append(internalNoVideoMKV)
|
||||
temporaries.append(internal_mkv)
|
||||
temporaries.append(internal_h264)
|
||||
temporaries.append(internal_h264_ts)
|
||||
temporaries.append(internal_novideo_mkv)
|
||||
|
||||
h264parts.append(internalH264)
|
||||
h264_ts.append(internalH264TS)
|
||||
subparts.append(internalNoVideoMKV)
|
||||
h264parts.append(internal_h264)
|
||||
h264_ts.append(internal_h264_ts)
|
||||
subparts.append(internal_novideo_mkv)
|
||||
|
||||
if (not args.coarse) and (nb_tail_frames > args.threshold):
|
||||
# We extract all frames between the I-frame (including it) upto the end.
|
||||
h264Tail, h264TailTS, mkvTail = extractAllStreams(ffmpeg=paths['ffmpeg'],
|
||||
h264_tail, h264_tail_ts, mkv_tail = extractAllStreams(ffmpeg=paths['ffmpeg'],
|
||||
ffprobe=paths['ffprobe'],
|
||||
inputFile=mkv, begin=tail_iframe_ts,
|
||||
end=ts2, nbFrames=nb_tail_frames,
|
||||
@@ -3420,14 +3423,14 @@ def main():
|
||||
temporaries=temporaries,
|
||||
dumpMemFD=args.dump)
|
||||
|
||||
if mkvTail is not None:
|
||||
subparts.append(mkvTail)
|
||||
if h264Tail is not None:
|
||||
avcconfig = getAvcConfigFromH264(h264Tail)
|
||||
if mkv_tail is not None:
|
||||
subparts.append(mkv_tail)
|
||||
if h264_tail is not None:
|
||||
avcconfig = getAvcConfigFromH264(h264_tail)
|
||||
other_avc_configs.append(avcconfig)
|
||||
h264parts.append(h264Tail)
|
||||
if h264TailTS is not None:
|
||||
h264_ts.append(h264TailTS)
|
||||
h264parts.append(h264_tail)
|
||||
if h264_tail_ts is not None:
|
||||
h264_ts.append(h264_tail_ts)
|
||||
|
||||
logger.info('Merging MKV: %s', subparts)
|
||||
part = mergeMKVs(mkvmerge=paths['mkvmerge'], inputs=subparts,
|
||||
@@ -3441,77 +3444,77 @@ def main():
|
||||
checks.append(pos)
|
||||
|
||||
# When using coarse option there is a single AVC configuration.
|
||||
for avcConfig in other_avc_configs:
|
||||
main_avc_config.merge(avcConfig)
|
||||
for avc_config in other_avc_configs:
|
||||
main_avc_config.merge(avc_config)
|
||||
logger.debug('Merged AVC configuration: %s', main_avc_config)
|
||||
|
||||
nbMKVParts = len(mkvparts)
|
||||
if nbMKVParts > 0:
|
||||
nb_mkv_parts = len(mkvparts)
|
||||
if nb_mkv_parts > 0:
|
||||
try:
|
||||
fullH264 = open(f'{basename}-full.h264', 'w+', encoding='utf8')
|
||||
full_h264 = open(f'{basename}-full.h264', 'w+', encoding='utf8')
|
||||
except IOError:
|
||||
logger.error('Impossible to create file full H264 stream.')
|
||||
exit(-1)
|
||||
|
||||
logger.info('Merging all H264 tracks')
|
||||
concatenateH264Parts(h264parts=h264parts, output=fullH264)
|
||||
temporaries.append(fullH264)
|
||||
concatenateH264Parts(h264parts=h264parts, output=full_h264)
|
||||
temporaries.append(full_h264)
|
||||
|
||||
try:
|
||||
fullH264TS = open(f'{basename}-ts.txt', 'w+', encoding='utf8')
|
||||
full_h264_ts = open(f'{basename}-ts.txt', 'w+', encoding='utf8')
|
||||
except IOError:
|
||||
logger.error('Impossible to create file containing all video timestamps.')
|
||||
exit(-1)
|
||||
|
||||
logger.info('Merging H264 timestamps')
|
||||
concatenateH264TSParts(h264TSParts=h264_ts, output=fullH264TS)
|
||||
temporaries.append(fullH264TS)
|
||||
concatenateH264TSParts(h264TSParts=h264_ts, output=full_h264_ts)
|
||||
temporaries.append(full_h264_ts)
|
||||
|
||||
finalNoVideoName = f'{basename}-novideo.mkv'
|
||||
finalWithVideoName = f'{basename}-video.mkv'
|
||||
final_novideo_name = f'{basename}-novideo.mkv'
|
||||
final_with_video_name = f'{basename}-video.mkv'
|
||||
|
||||
if nbMKVParts > 1:
|
||||
if nb_mkv_parts > 1:
|
||||
logger.info('Merging all audio and subtitles parts: %s', mkvparts)
|
||||
mergeMKVs(mkvmerge=paths['mkvmerge'], inputs=mkvparts, outputName=finalNoVideoName,
|
||||
mergeMKVs(mkvmerge=paths['mkvmerge'], inputs=mkvparts, outputName=final_novideo_name,
|
||||
concatenate=True)
|
||||
elif nbMKVParts == 1:
|
||||
copyfile('part-1.mkv', finalNoVideoName)
|
||||
elif nb_mkv_parts == 1:
|
||||
copyfile('part-1.mkv', final_novideo_name)
|
||||
else:
|
||||
logger.info("Nothing else to do.")
|
||||
copyfile(mkvfilename, finalWithVideoName)
|
||||
copyfile(mkvfilename, final_with_video_name)
|
||||
|
||||
if nbMKVParts >=1 :
|
||||
if nb_mkv_parts >=1 :
|
||||
try:
|
||||
finalNoVideo = open(finalNoVideoName, 'r', encoding='utf8')
|
||||
final_novideo = open(final_novideo_name, 'r', encoding='utf8')
|
||||
except IOError:
|
||||
logger.error('Impossible to open file: %s.', finalNoVideoName)
|
||||
logger.error('Impossible to open file: %s.', final_novideo_name)
|
||||
exit(-1)
|
||||
|
||||
temporaries.append(finalNoVideo)
|
||||
temporaries.append(final_novideo)
|
||||
|
||||
fullH264TS.seek(0)
|
||||
full_h264_ts.seek(0)
|
||||
|
||||
logger.info('Merging final video track and all other tracks together')
|
||||
finalWithVideo = mergeMKVs(mkvmerge=paths['mkvmerge'], inputs=[fullH264, finalNoVideo],
|
||||
outputName=finalWithVideoName, concatenate=False,
|
||||
timestamps={0: fullH264TS})
|
||||
finalCodecPrivateData = dumpCodecPrivateData(main_avc_config)
|
||||
logger.debug('Final codec private data: %s', hexdump.dump(finalCodecPrivateData, sep=':'))
|
||||
final_with_video = mergeMKVs(mkvmerge=paths['mkvmerge'], inputs=[full_h264, final_novideo],
|
||||
outputName=final_with_video_name, concatenate=False,
|
||||
timestamps={0: full_h264_ts})
|
||||
final_codec_private_data = dumpCodecPrivateData(main_avc_config)
|
||||
logger.debug('Final codec private data: %s', hexdump.dump(final_codec_private_data, sep=':'))
|
||||
logger.info('Changing codec private data with the new one.')
|
||||
changeCodecPrivateData(paths['mkvinfo'], finalWithVideo, finalCodecPrivateData)
|
||||
changeCodecPrivateData(paths['mkvinfo'], final_with_video, final_codec_private_data)
|
||||
|
||||
if args.srt:
|
||||
if not all_optional_tools:
|
||||
logger.warning("Missing tools for extracting subtitles.")
|
||||
move(finalWithVideoName, args.outputFile)
|
||||
move(final_with_video_name, args.outputFile)
|
||||
else:
|
||||
# Final cut is not any more the final step.
|
||||
temporaries.append(finalWithVideo)
|
||||
duration = getMovieDuration(paths['ffprobe'], finalWithVideo)
|
||||
supportedLangs = getTesseractSupportedLang(paths['tesseract'])
|
||||
logger.info('Supported lang: %s', supportedLangs)
|
||||
temporaries.append(final_with_video)
|
||||
duration = getMovieDuration(paths['ffprobe'], final_with_video)
|
||||
supported_langs = getTesseractSupportedLang(paths['tesseract'])
|
||||
logger.info('Supported lang: %s', supported_langs)
|
||||
logger.info('Find subtitles tracks and language.')
|
||||
subtitles = findSubtitlesTracks(paths['ffprobe'], finalWithVideo)
|
||||
subtitles = findSubtitlesTracks(paths['ffprobe'], final_with_video)
|
||||
logger.info(subtitles)
|
||||
sts = {}
|
||||
for subtitle in subtitles:
|
||||
@@ -3532,10 +3535,10 @@ def main():
|
||||
|
||||
logger.info(sts)
|
||||
if len(sts) > 0:
|
||||
listOfSubtitles = extractSRT(paths['mkvextract'], finalWithVideoName, sts,
|
||||
supportedLangs)
|
||||
logger.info(listOfSubtitles)
|
||||
for idx_name, sub_name, _, _ in listOfSubtitles:
|
||||
list_of_subtitles = extractSRT(paths['mkvextract'], final_with_video_name, sts,
|
||||
supported_langs)
|
||||
logger.info(list_of_subtitles)
|
||||
for idx_name, sub_name, _, _ in list_of_subtitles:
|
||||
try:
|
||||
idx = open(idx_name,'r', encoding='utf8')
|
||||
except IOError:
|
||||
@@ -3550,15 +3553,15 @@ def main():
|
||||
temporaries.append(idx)
|
||||
temporaries.append(sub)
|
||||
|
||||
ocr = doOCR(paths['vobsubocr'], listOfSubtitles, duration, temporaries, args.dump)
|
||||
ocr = doOCR(paths['vobsubocr'], list_of_subtitles, duration, temporaries, args.dump)
|
||||
logger.info(ocr)
|
||||
|
||||
# Remux SRT subtitles
|
||||
remuxSRTSubtitles(paths['mkvmerge'], finalWithVideo, args.outputFile, ocr)
|
||||
remuxSRTSubtitles(paths['mkvmerge'], final_with_video, args.outputFile, ocr)
|
||||
else:
|
||||
copyfile(finalWithVideoName, args.outputFile)
|
||||
copyfile(final_with_video_name, args.outputFile)
|
||||
else:
|
||||
move(finalWithVideoName, args.outputFile)
|
||||
move(final_with_video_name, args.outputFile)
|
||||
|
||||
if not args.keep:
|
||||
logger.info("Cleaning temporary files")
|
||||
|
||||
Reference in New Issue
Block a user