Improve pylint score and fix most errors.
This commit is contained in:
191
removeads.py
191
removeads.py
@@ -1,9 +1,10 @@
|
||||
#!/usr/bin/env python3
|
||||
'''A module to remove parts of video (.e.g advertisements) with single frame precision.'''
|
||||
|
||||
import argparse
|
||||
import re
|
||||
from sys import exit
|
||||
from datetime import datetime,timedelta,time
|
||||
from datetime import datetime,timedelta
|
||||
import coloredlogs, logging
|
||||
from functools import cmp_to_key
|
||||
from subprocess import Popen, PIPE
|
||||
@@ -35,7 +36,7 @@ from dataclasses import dataclass, field
|
||||
# Concatenate all raw H264 in a giant one (like cat), and the same for timestamps of video frames (to keep
|
||||
# sound and video synchronized).
|
||||
# Then use mkvmerge to remux the H264 track and the rest of tracks.
|
||||
# MKVmerge concatenate is able to concatenate different SPS/PPS data into a bigger Private Codec Data.
|
||||
# MKVmerge "concatenate" subcommand is able to concatenate different SPS/PPS data into a bigger Private Codec Data.
|
||||
# However, this is proved to be not reliable. Sometimes it results in a AVC context containing a single SPS/PPS.
|
||||
# So we have to rely on a manual parsing of the H264 AVC context of original movie
|
||||
# and the ones produced for headers and trailers, and then merging them into a bigger AVC context.
|
||||
@@ -50,15 +51,15 @@ def checkRequiredTools():
|
||||
optional = ['mkvextract', 'vobsubocr','tesseract']
|
||||
for tool in required:
|
||||
path = which(tool)
|
||||
if path == None:
|
||||
logger.error('Required tool: %s is missing.' % tool)
|
||||
if path is None:
|
||||
logger.error('Required tool: %s is missing.',tool)
|
||||
exit(-1)
|
||||
else:
|
||||
paths[tool] = path
|
||||
paths[tool] = path
|
||||
for tool in optional:
|
||||
path = which(tool)
|
||||
if path == None:
|
||||
logger.info('Optional tool: %s is missing.' % tool)
|
||||
if path is None:
|
||||
logger.info('Optional tool: %s is missing.',tool)
|
||||
allOptionalTools = False
|
||||
else:
|
||||
paths[tool] = path
|
||||
@@ -83,9 +84,9 @@ def getTesseractSupportedLang(tesseract):
|
||||
pass
|
||||
|
||||
tesseract.wait()
|
||||
|
||||
|
||||
if tesseract.returncode != 0:
|
||||
logger.error("Tesseract returns an error code: %d" % tesseract.returncode)
|
||||
logger.error("Tesseract returns an error code: %d",tesseract.returncode)
|
||||
return None
|
||||
|
||||
return res
|
||||
@@ -105,7 +106,8 @@ def getFrameRate(ffprobe, inputFile):
|
||||
maxTs = None
|
||||
interlaced = False
|
||||
|
||||
params = [ffprobe, '-loglevel', 'quiet', '-select_streams', 'v', '-show_frames', '-read_intervals', '00%+30', '-of', 'json', '/proc/self/fd/%d' % infd]
|
||||
params = [ffprobe, '-loglevel', 'quiet', '-select_streams', 'v', '-show_frames',
|
||||
'-read_intervals', '00%+30', '-of', 'json', '/proc/self/fd/%d' % infd]
|
||||
env = {**os.environ, 'LANG': 'C'}
|
||||
with Popen(params, stdout=PIPE, close_fds=False, env=env) as ffprobe:
|
||||
out, _ = ffprobe.communicate()
|
||||
@@ -117,9 +119,9 @@ def getFrameRate(ffprobe, inputFile):
|
||||
interlaced = True
|
||||
if 'pts_time' in frame:
|
||||
ts = float(frame['pts_time'])
|
||||
if minTs == None:
|
||||
if minTs is None:
|
||||
minTs = ts
|
||||
if maxTs == None:
|
||||
if maxTs is None:
|
||||
maxTs = ts
|
||||
if ts < minTs:
|
||||
minTs = ts
|
||||
@@ -135,7 +137,7 @@ def getFrameRate(ffprobe, inputFile):
|
||||
ffprobe.wait()
|
||||
|
||||
if ffprobe.returncode != 0:
|
||||
logger.error("ffprobe returns an error code: %d" % ffprobe.returncode)
|
||||
logger.error("ffprobe returns an error code: %d", ffprobe.returncode)
|
||||
return None
|
||||
|
||||
frameRate1 = nbFrames1/(maxTs-minTs)
|
||||
@@ -143,12 +145,12 @@ def getFrameRate(ffprobe, inputFile):
|
||||
|
||||
if abs(frameRate1 - frameRate2) > 0.2:
|
||||
if not interlaced:
|
||||
logger.error('Video is not interlaced and the disperancy between frame rates is too big: %f / %f' % (frameRate1, frameRate2))
|
||||
logger.error('Video is not interlaced and the disperancy between frame rates is too big: %f / %f', frameRate1, frameRate2)
|
||||
return None
|
||||
if abs(frameRate1*2 - frameRate2) < 0.2:
|
||||
return frameRate2/2
|
||||
else:
|
||||
logger.error('Video is interlaced and the disperancy between frame rates is too big: %f / %f' % (frameRate1, frameRate2))
|
||||
logger.error('Video is interlaced and the disperancy between frame rates is too big: %f / %f', frameRate1, frameRate2)
|
||||
return None
|
||||
else:
|
||||
return frameRate2
|
||||
@@ -160,7 +162,8 @@ def getSubTitlesTracks(ffprobe, mkvPath):
|
||||
tracks={}
|
||||
|
||||
nbSubTitles = 0
|
||||
with Popen([ffprobe, '-loglevel', 'quiet', '-select_streams', 's', '-show_entries', 'stream=index,codec_name:stream_tags=language', '-of', 'json', mkvPath], stdout=PIPE) as ffprobe:
|
||||
with Popen([ffprobe, '-loglevel', 'quiet', '-select_streams', 's', '-show_entries',
|
||||
'stream=index,codec_name:stream_tags=language', '-of', 'json', mkvPath], stdout=PIPE) as ffprobe:
|
||||
out, _ = ffprobe.communicate()
|
||||
out = json.load(BytesIO(out))
|
||||
if 'streams' in out:
|
||||
@@ -170,10 +173,10 @@ def getSubTitlesTracks(ffprobe, mkvPath):
|
||||
lang = stream['tags']['language']
|
||||
if codec == 'dvd_subtitle':
|
||||
if lang not in tracks:
|
||||
tracks[lang] = [track]
|
||||
tracks[lang] = [index]
|
||||
else:
|
||||
l = tracks[lang]
|
||||
l.append(track)
|
||||
l.append(index)
|
||||
tracks[lang] = l
|
||||
else:
|
||||
return None
|
||||
@@ -181,7 +184,7 @@ def getSubTitlesTracks(ffprobe, mkvPath):
|
||||
ffprobe.wait()
|
||||
|
||||
if ffprobe.returncode != 0:
|
||||
logger.error("ffprobe returns an error code: %d" % ffprobe.returncode)
|
||||
logger.error("ffprobe returns an error code: %d", ffprobe.returncode)
|
||||
return None
|
||||
|
||||
return tracks
|
||||
@@ -199,7 +202,7 @@ def extractSRT(mkvextract, fileName, subtitles, langs):
|
||||
if iso in langs:
|
||||
ocrlang = langs[iso]
|
||||
else:
|
||||
logger.warning("Language not supported by Tesseract: %s" % iso.name)
|
||||
logger.warning("Language not supported by Tesseract: %s", iso.name)
|
||||
ocrlang ='osd'
|
||||
|
||||
if len(subtitles[lang]) == 1:
|
||||
@@ -221,7 +224,7 @@ def extractSRT(mkvextract, fileName, subtitles, langs):
|
||||
if line.startswith('Progress :'):
|
||||
p = re.compile('^Progress : (?P<progress>[0-9]{1,3})%$')
|
||||
m = p.match(line)
|
||||
if m == None:
|
||||
if m is None:
|
||||
logger.error('Impossible to parse progress')
|
||||
pb.update(int(m['progress'])-pb.n)
|
||||
pb.update(100-pb.n)
|
||||
@@ -238,7 +241,7 @@ def extractSRT(mkvextract, fileName, subtitles, langs):
|
||||
logger.warning('Mkvextract returns warning')
|
||||
return res
|
||||
else:
|
||||
logger.error('Mkvextract returns an error code: %d' % extract.returncode)
|
||||
logger.error('Mkvextract returns an error code: %d', extract.returncode)
|
||||
return None
|
||||
|
||||
def doOCR(vobsubocr, idxs, duration, temporaries, dumpMemFD=False):
|
||||
@@ -273,13 +276,13 @@ def doOCR(vobsubocr, idxs, duration, temporaries, dumpMemFD=False):
|
||||
status = ocr.wait()
|
||||
|
||||
if status != 0:
|
||||
logger.error('OCR failed with status code: %d' % status)
|
||||
logger.error('OCR failed with status code: %d', status)
|
||||
|
||||
if dumpMemFD:
|
||||
try:
|
||||
dumpSrt = open(srtname,'w')
|
||||
except IOError:
|
||||
logger.error('Impossible to create file: %s' % srtname)
|
||||
logger.error('Impossible to create file: %s', srtname)
|
||||
return None
|
||||
|
||||
lseek(srtfd, 0, SEEK_SET)
|
||||
@@ -342,7 +345,7 @@ def getCodecPrivateDataFromMKV(mkvinfo, inputFile):
|
||||
if m != None:
|
||||
size = int(m.group('size'))
|
||||
position = int(m.group('position'))
|
||||
logger.debug("Found codec private data at position: %s, size: %d" % (position, size))
|
||||
logger.debug("Found codec private data at position: %s, size: %d", position, size)
|
||||
found = True
|
||||
mkvinfo.wait()
|
||||
break
|
||||
@@ -569,7 +572,7 @@ def parseScalingList(buf, bitPosition, size):
|
||||
# The ISO/IEC H.264-201602 seems to take into account the case where the end of the deltas list is full of zeroes.
|
||||
def writeScalingList(buf, bitPosition, size, matrix, optimized=False):
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.debug('Dumping matrix: %s of size: %d, size parameter: %d.' % (matrix, len(matrix), size))
|
||||
logger.debug('Dumping matrix: %s of size: %d, size parameter: %d.', matrix, len(matrix), size)
|
||||
|
||||
prev = 8
|
||||
deltas = []
|
||||
@@ -846,9 +849,13 @@ class SPS:
|
||||
self.scaling_list={}
|
||||
self.offset_for_ref_frame={}
|
||||
|
||||
# Compute options to pass to ffmpeg so as to reproduce the same SPS.
|
||||
# TODO: ...
|
||||
# Compute options to pass to ffmpeg so as to reproduce the same SPS.
|
||||
# Very complex since some codec configuration are not provided by ffmpeg and/or libx264.
|
||||
# This is only an attempt.
|
||||
|
||||
def ffmpegOptions(self, videoID=0):
|
||||
logger = logging.getLogger(__name__)
|
||||
x264opts = []
|
||||
|
||||
if self.profile_idc in [ 0x42, 0x4D, 0x64, 0x6E, 0x7A, 0xF4, 0x2C]:
|
||||
@@ -865,14 +872,14 @@ class SPS:
|
||||
elif self.profile_idc == 0xF4:
|
||||
profile = 'high444'
|
||||
else:
|
||||
logger.error('Unknow profile: %x' % self.profile)
|
||||
logger.error('Unknow profile: %x', self.profile_idc)
|
||||
return []
|
||||
|
||||
level = '%d.%d' % (floor(self.level/10), self.level % 10)
|
||||
level = '%d.%d' % (floor(self.level_idc/10), self.level_idc % 10)
|
||||
x264opts.extend(['sps-id=%d' % self.seq_parameter_set_id] )
|
||||
|
||||
if self.bit_depth_chroma_minus8 not in [0,1,2,4,6,8]:
|
||||
logger.error('Bit depth of chrominance is not supported: %d' % (self.bit_depth_chroma_minus8+8))
|
||||
logger.error('Bit depth of chrominance is not supported: %d', self.bit_depth_chroma_minus8+8)
|
||||
return []
|
||||
|
||||
if self.chroma_format_idc in range(0,4):
|
||||
@@ -889,7 +896,7 @@ class SPS:
|
||||
# YUV:4:4:4
|
||||
pass
|
||||
else:
|
||||
logger.error('Unknow chrominance format: %x' % self.profile)
|
||||
logger.error('Unknow chrominance format: %x', self.chroma_format_idc)
|
||||
return []
|
||||
|
||||
res = ['-profile:v:%d' % videoID, self.profile_idc, '-level:v:%d' % videoID, level]
|
||||
@@ -978,7 +985,7 @@ class SPS:
|
||||
if self.vui_parameters_present_flag:
|
||||
self.vui = VUI()
|
||||
bitPosition = self.vui.fromBytes(buf,bitPosition)
|
||||
logger.debug('VUI present: %s' % self.vui)
|
||||
logger.debug('VUI present: %s', self.vui)
|
||||
|
||||
|
||||
logger.debug('Parse end of SPS. Bit position: %d. Remaining bytes: %s.' % (bitPosition, hexdump.dump(buf[floor(bitPosition/8):], sep=':')))
|
||||
@@ -1035,7 +1042,7 @@ class SPS:
|
||||
bitPosition = writeUnsignedExpGolomb(buf, bitPosition, self.num_ref_frames_in_pic_order_cnt_cycle)
|
||||
for i in range(0, self.num_ref_frames_in_pic_order_cnt_cycle):
|
||||
v = self.offset_for_ref_frame[i]
|
||||
bitPosition, v = writeUnsignedExpGolomb(buf, bitPosition)
|
||||
bitPosition = writeUnsignedExpGolomb(buf, bitPosition, v)
|
||||
bitPosition = writeUnsignedExpGolomb(buf, bitPosition, self.max_num_ref_frames)
|
||||
bitPosition = writeBoolean(buf, bitPosition, self.gaps_in_frame_num_value_allowed_flag)
|
||||
bitPosition = writeUnsignedExpGolomb(buf, bitPosition, self.pic_width_in_mbs_minus1)
|
||||
@@ -1052,9 +1059,9 @@ class SPS:
|
||||
bitPosition = writeUnsignedExpGolomb(buf, bitPosition, self.frame_crop_bottom_offset)
|
||||
bitPosition = writeBoolean(buf, bitPosition, self.vui_parameters_present_flag)
|
||||
if self.vui_parameters_present_flag:
|
||||
logger.debug('SPS has VUI. Writing VUI at position: %d' % bitPosition)
|
||||
logger.debug('SPS has VUI. Writing VUI at position: %d', bitPosition)
|
||||
bitPosition = self.vui.toBytes(buf, bitPosition)
|
||||
logger.debug('VUI written. New bit position: %d' % bitPosition)
|
||||
logger.debug('VUI written. New bit position: %d', bitPosition)
|
||||
|
||||
bitPosition = writeRBSPTrailingBits(buf, bitPosition)
|
||||
|
||||
@@ -1129,7 +1136,7 @@ class PPS:
|
||||
elif self.slice_group_map_type == 2:
|
||||
for i in range(0, self.num_slice_groups_minus1):
|
||||
bitPosition, v = readUnsignedExpGolomb(buf, bitPosition)
|
||||
self.top_left.append[i] = v
|
||||
self.top_left[i] = v
|
||||
bitPosition, v = readUnsignedExpGolomb(buf, bitPosition)
|
||||
self.bottom_right[i] = v
|
||||
elif self.slice_group_map_type in [3,4,5]:
|
||||
@@ -1204,7 +1211,7 @@ class PPS:
|
||||
bitPosition = writeUnsignedExpGolomb(buf, bitPosition, v)
|
||||
elif self.slice_group_map_type == 2:
|
||||
for i in range(0, self.num_slice_groups_minus1):
|
||||
v = self.top_left.append[i]
|
||||
v = self.top_left[i]
|
||||
bitPosition = writeUnsignedExpGolomb(buf, bitPosition, v)
|
||||
v = self.bottom_right[i]
|
||||
bitPosition = writeUnsignedExpGolomb(buf, bitPosition, v)
|
||||
@@ -1545,7 +1552,7 @@ def parseMKVTree(mkvinfo, inputFile):
|
||||
prevDepth = -1
|
||||
for line in out.splitlines():
|
||||
m = p.match(line)
|
||||
if m == None:
|
||||
if m is None:
|
||||
logger.error("Impossible to match line: %s" % line)
|
||||
else:
|
||||
position = int(m.group('position'))
|
||||
@@ -1668,7 +1675,7 @@ def changeEBMLElementSize(inputFile, position, addendum):
|
||||
mask = mask>>1
|
||||
|
||||
if not found:
|
||||
logger.error('Size of element type cannot be determined: %b' % elementType)
|
||||
logger.error('Size of element type cannot be determined: %d', elementType)
|
||||
exit(-1)
|
||||
|
||||
# We seek to size
|
||||
@@ -1689,10 +1696,10 @@ def changeEBMLElementSize(inputFile, position, addendum):
|
||||
mask = mask>>1
|
||||
|
||||
if not found:
|
||||
logger.error('Size of data size cannot be determined: %b' % sizeHead)
|
||||
logger.error('Size of data size cannot be determined: %d', sizeHead)
|
||||
exit(-1)
|
||||
else:
|
||||
logger.info('Size of data size: %d.' % sizeOfDataSize)
|
||||
logger.info('Size of data size: %d.', sizeOfDataSize)
|
||||
|
||||
lseek(infd, position, SEEK_SET)
|
||||
oldSizeBuf = read(infd, sizeOfDataSize)
|
||||
@@ -1842,7 +1849,7 @@ def getMovieDuration(ffprobe, inputFile):
|
||||
|
||||
return None
|
||||
|
||||
# ffprobe -loglevel quiet -select_streams v:0 -show_entries stream=width,height -of json ./talons.ts
|
||||
# ffprobe -loglevel quiet -select_streams v:0 -show_entries stream=width,height -of json ./example.ts
|
||||
def getVideoDimensions(ffprobe, inputFile):
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -1902,7 +1909,7 @@ def parseTimestamp(ts):
|
||||
tsRegExp = r'^(?P<hour>[0-9]{1,2}):(?P<minute>[0-9]{1,2}):(?P<second>[0-9]{1,2})(\.(?P<us>[0-9]{1,6}))?$'
|
||||
p = re.compile(tsRegExp)
|
||||
m = p.match(ts)
|
||||
if m == None:
|
||||
if m is None:
|
||||
logger.warning("Impossible to parse timestamp: %s" % ts)
|
||||
return None
|
||||
|
||||
@@ -1943,7 +1950,7 @@ def parseTimeInterval(interval):
|
||||
intervalRegExp = r'^(?P<hour1>[0-9]{1,2}):(?P<minute1>[0-9]{1,2}):(?P<second1>[0-9]{1,2})(\.(?P<ms1>[0-9]{1,3}))?-(?P<hour2>[0-9]{1,2}):(?P<minute2>[0-9]{1,2}):(?P<second2>[0-9]{1,2})(\.(?P<ms2>[0-9]{1,3}))?$'
|
||||
p = re.compile(intervalRegExp)
|
||||
m = p.match(interval)
|
||||
if m == None:
|
||||
if m is None:
|
||||
logger.error("Impossible to parse time interval")
|
||||
return None
|
||||
|
||||
@@ -2046,7 +2053,7 @@ def ffmpegConvert(ffmpeg, ffprobe, inputFile, inputFormat, outputFile, outputFor
|
||||
params.extend(['-r:0', '25', '-f', outputFormat, '/proc/self/fd/%d' % outfd])
|
||||
|
||||
logger.debug('Executing %s' % params)
|
||||
|
||||
|
||||
with Popen(params, stdout=PIPE, close_fds=False) as ffmpeg:
|
||||
pb = tqdm(TextIOWrapper(ffmpeg.stdout, encoding="utf-8"), total=int(duration/timedelta(seconds=1)), unit='s', desc='Conversion')
|
||||
for line in pb:
|
||||
@@ -2058,27 +2065,31 @@ def ffmpegConvert(ffmpeg, ffprobe, inputFile, inputFormat, outputFile, outputFor
|
||||
pb.update()
|
||||
status = ffmpeg.wait()
|
||||
if status != 0:
|
||||
logger.error('Conversion failed with status code: %d' % status)
|
||||
logger.error('Conversion failed with status code: %d', status)
|
||||
|
||||
def getTSFrame(frame):
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
if 'pts_time' in frame:
|
||||
pts_time = float(frame['pts_time'])
|
||||
elif 'pkt_pts_time' in frame:
|
||||
pts_time = float(frame['pkt_pts_time'])
|
||||
else:
|
||||
logger.error('Impossible to find timestamp of frame %s' % frame)
|
||||
logger.error('Impossible to find timestamp of frame %s', frame)
|
||||
return None
|
||||
|
||||
ts = timedelta(seconds=pts_time)
|
||||
return ts
|
||||
|
||||
def getPacketDuration(packet):
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
if 'duration' in packet:
|
||||
duration = int(packet['duration'])
|
||||
elif 'pkt_duration' in packet:
|
||||
duration = int(packet['pkt_duration'])
|
||||
else:
|
||||
logger.error('Impossible to find duration of packet %s' % packet)
|
||||
logger.error('Impossible to find duration of packet %s', packet)
|
||||
return None
|
||||
|
||||
return duration
|
||||
@@ -2107,7 +2118,7 @@ def getFramesInStream(ffprobe, inputFile, begin, end, streamKind, subStreamId=0)
|
||||
frames = frames['frames']
|
||||
for frame in frames:
|
||||
ts = getTSFrame(frame)
|
||||
if ts == None:
|
||||
if ts is None:
|
||||
return None
|
||||
if begin <= ts and ts <= end:
|
||||
tmp[ts]=frame
|
||||
@@ -2134,12 +2145,12 @@ def getNearestIDRFrame(ffprobe, inputFile, timestamp, before=True, delta=timedel
|
||||
infd = inputFile.fileno()
|
||||
set_inheritable(infd, True)
|
||||
|
||||
logger.debug('Looking for IDR frame in [%s, %s]' % (tbegin, tend))
|
||||
logger.debug('Looking for IDR frame in [%s, %s]', tbegin, tend)
|
||||
|
||||
idrs = []
|
||||
|
||||
# Retains only IDR frame
|
||||
with Popen([ffprobe, '-loglevel', 'quiet', '-read_intervals', ('%s%%%s' %(begin, end)), '-skip_frame', 'nokey', '-show_entries', 'frame', '-select_streams', 'v:0', '-of', 'json', '/proc/self/fd/%d' % infd], stdout=PIPE, close_fds=False) as ffprobe:
|
||||
with Popen([ffprobe, '-loglevel', 'quiet', '-read_intervals', ('%s%%%s' %(tbegin, tend)), '-skip_frame', 'nokey', '-show_entries', 'frame', '-select_streams', 'v:0', '-of', 'json', '/proc/self/fd/%d' % infd], stdout=PIPE, close_fds=False) as ffprobe:
|
||||
out, _ = ffprobe.communicate()
|
||||
frames = json.load(BytesIO(out))
|
||||
status = ffprobe.wait()
|
||||
@@ -2151,12 +2162,12 @@ def getNearestIDRFrame(ffprobe, inputFile, timestamp, before=True, delta=timedel
|
||||
frames = frames['frames']
|
||||
for frame in frames:
|
||||
ts = getTSFrame(frame)
|
||||
if ts == None:
|
||||
if ts is None:
|
||||
return None
|
||||
if begin <= ts and ts <= end:
|
||||
if tbegin <= ts and ts <= tend:
|
||||
idrs.append(frame)
|
||||
else:
|
||||
logger.error('Impossible to retrieve IDR frames inside file around [%s,%s]' % (begin, end))
|
||||
logger.error('Impossible to retrieve IDR frames inside file around [%s,%s]', tbegin, tend)
|
||||
return None
|
||||
|
||||
|
||||
@@ -2186,7 +2197,7 @@ def getNearestIFrame(ffprobe, inputFile, timestamp, before=True, deltaMax=timede
|
||||
logger.debug('Looking for an iframe in [%s, %s]' % (tbegin, tend))
|
||||
|
||||
frames = getFramesInStream(ffprobe, inputFile=inputFile, begin=tbegin, end=tend, streamKind='v')
|
||||
if frames == None:
|
||||
if frames is None:
|
||||
logger.debug('Found no frame in [%s, %s]' % (tbegin, tend))
|
||||
delta+=timedelta(seconds=1)
|
||||
continue
|
||||
@@ -2199,7 +2210,7 @@ def getNearestIFrame(ffprobe, inputFile, timestamp, before=True, deltaMax=timede
|
||||
found = False
|
||||
for frame in iframes:
|
||||
ts = getTSFrame(frame)
|
||||
if ts == None:
|
||||
if ts is None:
|
||||
logger.warning('I-frame with no timestamp: %s' % frame)
|
||||
continue
|
||||
|
||||
@@ -2223,7 +2234,7 @@ def getNearestIFrame(ffprobe, inputFile, timestamp, before=True, deltaMax=timede
|
||||
nbFrames = 0
|
||||
for frame in frames:
|
||||
ts = getTSFrame(frame)
|
||||
if ts == None:
|
||||
if ts is None:
|
||||
logger.warning('Frame without timestamp: %s' % frame)
|
||||
continue
|
||||
|
||||
@@ -2263,7 +2274,7 @@ def extractMKVPart(mkvmerge, inputFile, outputFile, begin, end):
|
||||
if line.startswith('Progress :'):
|
||||
p = re.compile('^Progress : (?P<progress>[0-9]{1,3})%$')
|
||||
m = p.match(line)
|
||||
if m == None:
|
||||
if m is None:
|
||||
logger.error('Impossible to parse progress')
|
||||
pb.update(int(m['progress'])-pb.n)
|
||||
elif line.startswith('Warning'):
|
||||
@@ -2424,7 +2435,8 @@ def extractAllStreams(ffmpeg, ffprobe, inputFile, begin, end, streams, filesPref
|
||||
level = int(stream['level'])
|
||||
level = '%d.%d' % (floor(level/10), level%10)
|
||||
chromaLocation = stream['chroma_location']
|
||||
fieldOrder = stream['field_order']
|
||||
fieldOrder = stream
|
||||
interlacedOptions = []
|
||||
if fieldOrder == 'progressive':
|
||||
interlacedOptions = ['-field_order', '0']
|
||||
elif fieldOrder == 'tt':
|
||||
@@ -2441,7 +2453,7 @@ def extractAllStreams(ffmpeg, ffprobe, inputFile, begin, end, streams, filesPref
|
||||
# https://superuser.com/questions/907933/correct-aspect-ratio-without-re-encoding-video-file
|
||||
codec = stream['codec_name']
|
||||
imagesBytes, memfd = extractPictures(ffmpeg, inputFile=inputFile, begin=begin, nbFrames=nbFrames, width=width, height=height)
|
||||
if imagesBytes == None:
|
||||
if imagesBytes is None:
|
||||
exit(-1)
|
||||
|
||||
memfds.append(memfd)
|
||||
@@ -2475,7 +2487,7 @@ def extractAllStreams(ffmpeg, ffprobe, inputFile, begin, end, streams, filesPref
|
||||
logger.debug("Found %d packets to be extracted from audio track." % nbPackets)
|
||||
if(nbPackets > 0):
|
||||
packetDuration = getPacketDuration(packets[0])
|
||||
if packetDuration == None:
|
||||
if packetDuration is None:
|
||||
return None
|
||||
else:
|
||||
packetDuration = 0
|
||||
@@ -2486,7 +2498,7 @@ def extractAllStreams(ffmpeg, ffprobe, inputFile, begin, end, streams, filesPref
|
||||
|
||||
soundBytes, memfd = extractSound(ffmpeg=ffmpeg, inputFile=inputFile, begin=begin, nbPackets=nbPackets, packetDuration=packetDuration, outputFileName=tmpname, sampleRate=sampleRate, nbChannels=nbChannels)
|
||||
|
||||
if soundBytes == None:
|
||||
if soundBytes is None:
|
||||
exit(-1)
|
||||
|
||||
memfds.append(memfd)
|
||||
@@ -2661,7 +2673,7 @@ def mergeMKVs(mkvmerge, inputs, outputName, concatenate=True, timestamps=None):
|
||||
if line.startswith('Progress :'):
|
||||
p = re.compile('^Progress : (?P<progress>[0-9]{1,3})%$')
|
||||
m = p.match(line)
|
||||
if m == None:
|
||||
if m is None:
|
||||
logger.error('Impossible to parse progress')
|
||||
pb.n = int(m['progress'])
|
||||
pb.update()
|
||||
@@ -2728,7 +2740,7 @@ def extractTrackFromMKV(mkvextract, inputFile, index, outputFile, timestamps):
|
||||
if line.startswith('Progress :'):
|
||||
p = re.compile('^Progress : (?P<progress>[0-9]{1,3})%$')
|
||||
m = p.match(line)
|
||||
if m == None:
|
||||
if m is None:
|
||||
logger.error('Impossible to parse progress')
|
||||
pb.update(int(m['progress'])-pb.n)
|
||||
pb.update(100-pb.n)
|
||||
@@ -2763,7 +2775,7 @@ def removeVideoTracksFromMKV(mkvmerge, inputFile, outputFile):
|
||||
if line.startswith('Progress :'):
|
||||
p = re.compile('^Progress : (?P<progress>[0-9]{1,3})%$')
|
||||
m = p.match(line)
|
||||
if m == None:
|
||||
if m is None:
|
||||
logger.error('Impossible to parse progress')
|
||||
pb.update(int(m['progress'])-pb.n)
|
||||
pb.update(100-pb.n)
|
||||
@@ -2810,7 +2822,7 @@ def remuxSRTSubtitles(mkvmerge, inputFile, outputFileName, subtitles):
|
||||
if line.startswith('Progress :'):
|
||||
p = re.compile('^Progress : (?P<progress>[0-9]{1,3})%$')
|
||||
m = p.match(line)
|
||||
if m == None:
|
||||
if m is None:
|
||||
logger.error('Impossible to parse progress')
|
||||
pb.n = int(m['progress'])
|
||||
pb.update()
|
||||
@@ -2844,7 +2856,7 @@ def concatenateH264Parts(h264parts, output):
|
||||
lseek(fd, 0, SEEK_SET)
|
||||
while True:
|
||||
buf = read(fd, 1000000)
|
||||
if buf == None or len(buf) == 0:
|
||||
if buf is None or len(buf) == 0:
|
||||
break
|
||||
pos = 0
|
||||
while pos < len(buf):
|
||||
@@ -2882,6 +2894,7 @@ def concatenateH264TSParts(h264TSParts, output):
|
||||
first = False
|
||||
|
||||
def doCoarseProcessing(ffmpeg, ffprobe, mkvmerge, inputFile, begin, end, nbFrames, frameRate, filesPrefix, streams, width, height, temporaries, dumpMemFD):
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Internal video with all streams (video, audio and subtitles)
|
||||
internalMKVName = '%s.mkv' % filesPrefix
|
||||
@@ -2889,7 +2902,7 @@ def doCoarseProcessing(ffmpeg, ffprobe, mkvmerge, inputFile, begin, end, nbFrame
|
||||
try:
|
||||
internalMKV = open(internalMKVName, 'w+')
|
||||
except IOError:
|
||||
logger.error('Impossible to create file: %s' % internalMKVName)
|
||||
logger.error('Impossible to create file: %s', internalMKVName)
|
||||
exit(-1)
|
||||
|
||||
# Extract internal part of MKV
|
||||
@@ -2927,7 +2940,7 @@ def main():
|
||||
logger.error('--coarse and threshold arguments are exclusive.')
|
||||
exit(-1)
|
||||
|
||||
if (not args.coarse) and args.threshold == None:
|
||||
if (not args.coarse) and args.threshold is None:
|
||||
args.threshold = 0
|
||||
|
||||
allOptionalTools, paths = checkRequiredTools()
|
||||
@@ -2943,7 +2956,7 @@ def main():
|
||||
# Parse each interval
|
||||
for interval in intervals:
|
||||
ts1, ts2 = parseTimeInterval(interval)
|
||||
if ts1 == None or ts2 == None:
|
||||
if ts1 is None or ts2 is None:
|
||||
logger.error("Illegal time interval: %s" % interval)
|
||||
exit(-1)
|
||||
parts.append((ts1,ts2))
|
||||
@@ -2975,15 +2988,15 @@ def main():
|
||||
|
||||
formatOfFile = getFormat(paths['ffprobe'], inputFile)
|
||||
|
||||
if formatOfFile == None:
|
||||
if formatOfFile is None:
|
||||
exit(-1)
|
||||
|
||||
duration = timedelta(seconds=float(formatOfFile['duration']))
|
||||
logger.info("Durée de l'enregistrement: %s" % duration)
|
||||
|
||||
if args.framerate == None:
|
||||
if args.framerate is None:
|
||||
frameRate = getFrameRate(paths['ffprobe'], inputFile)
|
||||
if frameRate == None:
|
||||
if frameRate is None:
|
||||
logger.error('Impossible to estimate frame rate !')
|
||||
exit(-1)
|
||||
else:
|
||||
@@ -3053,7 +3066,7 @@ def main():
|
||||
else:
|
||||
mainVideo = None
|
||||
|
||||
if mainVideo == None:
|
||||
if mainVideo is None:
|
||||
logger.error('Impossible to find main video stream.')
|
||||
exit(-1)
|
||||
|
||||
@@ -3106,26 +3119,26 @@ def main():
|
||||
|
||||
# Get the nearest I-frame whose timestamp is greater or equal to the beginning.
|
||||
headFrames = getNearestIFrame(paths['ffprobe'], mkv, ts1, before=False)
|
||||
if headFrames == None:
|
||||
if headFrames is None:
|
||||
exit(-1)
|
||||
|
||||
# Get the nearest I-frame whose timestamp ...
|
||||
# TODO: wrong here ...
|
||||
tailFrames = getNearestIFrame(paths['ffprobe'], mkv, ts2, before=True)
|
||||
if tailFrames == None:
|
||||
if tailFrames is None:
|
||||
exit(-1)
|
||||
|
||||
nbHeadFrames, headIFrame = headFrames
|
||||
nbTailFrames, tailIFrame = tailFrames
|
||||
|
||||
logger.info("Found %d frames between beginning of current part and first I-frame" % nbHeadFrames)
|
||||
logger.info("Found %d frames between last I-frame and end of current part" % nbTailFrames)
|
||||
logger.info("Found %d frames between beginning of current part and first I-frame", nbHeadFrames)
|
||||
logger.info("Found %d frames between last I-frame and end of current part", nbTailFrames)
|
||||
|
||||
headIFrameTS = getTSFrame(headIFrame)
|
||||
if headIFrameTS == None:
|
||||
if headIFrameTS is None:
|
||||
exit(-1)
|
||||
tailIFrameTS = getTSFrame(tailIFrame)
|
||||
if tailIFrameTS == None:
|
||||
if tailIFrameTS is None:
|
||||
exit(-1)
|
||||
|
||||
checks.append(pos+headIFrameTS-ts1)
|
||||
@@ -3168,25 +3181,25 @@ def main():
|
||||
try:
|
||||
internalMKV = open(internalMKVName, 'w+')
|
||||
except IOError:
|
||||
logger.error('Impossible to create file: %s' % internalMKVName)
|
||||
logger.error('Impossible to create file: %s', internalMKVName)
|
||||
exit(-1)
|
||||
|
||||
try:
|
||||
internalNoVideoMKV = open(internalNoVideoMKVName, 'w+')
|
||||
except IOError:
|
||||
logger.error('Impossible to create file: %s' % internalNoVideoMKVName)
|
||||
logger.error('Impossible to create file: %s', internalNoVideoMKVName)
|
||||
exit(-1)
|
||||
|
||||
try:
|
||||
internalH264 = open(internalH264Name, 'w+')
|
||||
except IOError:
|
||||
logger.error('Impossible to create file: %s' % internalH264Name)
|
||||
logger.error('Impossible to create file: %s', internalH264Name)
|
||||
exit(-1)
|
||||
|
||||
try:
|
||||
internalH264TS = open(internalH264TSName, 'w+')
|
||||
except IOError:
|
||||
logger.error('Impossible to create file: %s' % internalH264TSName)
|
||||
logger.error('Impossible to create file: %s', internalH264TSName)
|
||||
exit(-1)
|
||||
|
||||
# logger.info('Merge header, middle and trailer subpart into: %s' % internalMKVName)
|
||||
@@ -3199,7 +3212,7 @@ def main():
|
||||
extractTrackFromMKV(mkvextract=paths['mkvextract'], inputFile=internalMKV, index=0, outputFile=internalH264, timestamps=internalH264TS)
|
||||
|
||||
# Remove video track from internal part of MKV
|
||||
logger.info('Remove video track from %s' % internalMKVName)
|
||||
logger.info('Remove video track from %s', internalMKVName)
|
||||
removeVideoTracksFromMKV(mkvmerge=paths['mkvmerge'], inputFile=internalMKV, outputFile=internalNoVideoMKV)
|
||||
|
||||
temporaries.append(internalMKV)
|
||||
@@ -3224,7 +3237,7 @@ def main():
|
||||
if h264TailTS != None:
|
||||
h264TS.append(h264TailTS)
|
||||
|
||||
logger.info('Merging MKV: %s' % subparts)
|
||||
logger.info('Merging MKV: %s', subparts)
|
||||
part = mergeMKVs(mkvmerge=paths['mkvmerge'], inputs=subparts, outputName="part-%d.mkv" % partnum, concatenate=True)
|
||||
mkvparts.append(part)
|
||||
temporaries.append(part)
|
||||
@@ -3237,7 +3250,7 @@ def main():
|
||||
# When using coarse option there is a single AVC configuration.
|
||||
for avcConfig in otherAvcConfigs:
|
||||
mainAvcConfig.merge(avcConfig)
|
||||
logger.debug('Merged AVC configuration: %s' % mainAvcConfig)
|
||||
logger.debug('Merged AVC configuration: %s', mainAvcConfig)
|
||||
|
||||
nbMKVParts = len(mkvparts)
|
||||
if nbMKVParts > 0:
|
||||
@@ -3328,12 +3341,12 @@ def main():
|
||||
try:
|
||||
idx = open(idxName,'r')
|
||||
except IOError:
|
||||
logger.error("Impossible to open %s." % idxName)
|
||||
logger.error("Impossible to open %s.", idxName)
|
||||
exit(-1)
|
||||
try:
|
||||
sub = open(subName,'r')
|
||||
except IOError:
|
||||
logger.error("Impossible to open %s." % subName)
|
||||
logger.error("Impossible to open %s.", subName)
|
||||
exit(-1)
|
||||
|
||||
temporaries.append(idx)
|
||||
|
||||
Reference in New Issue
Block a user