From ddec8633e3de084fa887b2ee2a63290dd0b72f2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Tronel?= Date: Sat, 25 Oct 2025 16:45:20 +0200 Subject: [PATCH] Improve linting by remove trailing spaces. --- removeads.py | 161 +++++++++++++++++++++++++-------------------------- 1 file changed, 79 insertions(+), 82 deletions(-) diff --git a/removeads.py b/removeads.py index c011f71..9ae5cba 100755 --- a/removeads.py +++ b/removeads.py @@ -93,11 +93,11 @@ def getTesseractSupportedLang(tesseract): def getFrameRate(ffprobe, inputFile): logger = logging.getLogger(__name__) - + infd = inputFile.fileno() lseek(infd, 0, SEEK_SET) set_inheritable(infd, True) - + meanDuration = 0. nbFrames1 = 0 nbFrames2 = 0 @@ -105,7 +105,7 @@ def getFrameRate(ffprobe, inputFile): minTs = None maxTs = None interlaced = False - + 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'} @@ -133,13 +133,13 @@ def getFrameRate(ffprobe, inputFile): nbFrames2+=1 else: return None - + ffprobe.wait() - + if ffprobe.returncode != 0: logger.error("ffprobe returns an error code: %d", ffprobe.returncode) return None - + frameRate1 = nbFrames1/(maxTs-minTs) frameRate2 = nbFrames2 / meanDuration @@ -177,34 +177,34 @@ def getSubTitlesTracks(ffprobe, mkvPath): else: l = tracks[lang] l.append(index) - tracks[lang] = l + tracks[lang] = l else: return None - + ffprobe.wait() - + if ffprobe.returncode != 0: logger.error("ffprobe returns an error code: %d", ffprobe.returncode) return None - + return tracks def extractSRT(mkvextract, fileName, subtitles, langs): logger = logging.getLogger(__name__) - + params = [mkvextract, fileName, 'tracks'] - + res = [] for lang in subtitles: iso = Lang(lang) - + if iso in langs: ocrlang = langs[iso] else: logger.warning("Language not supported by Tesseract: %s", iso.name) ocrlang ='osd' - + if len(subtitles[lang]) == 1: params.append('%d:%s' % (subtitles[lang][0], lang)) res.append(('%s.idx' % lang, '%s.sub' % lang, lang, ocrlang)) @@ -230,9 +230,9 @@ def extractSRT(mkvextract, fileName, subtitles, langs): pb.update(100-pb.n) pb.refresh() pb.close() - + extract.wait() - + # mkvextract returns 0, 1 or 2 as error code. if extract.returncode == 0: logger.info('Subtitle tracks were succesfully extracted.') @@ -243,11 +243,11 @@ def extractSRT(mkvextract, fileName, subtitles, langs): else: logger.error('Mkvextract returns an error code: %d', extract.returncode) return None - + def doOCR(vobsubocr, idxs, duration, temporaries, dumpMemFD=False): logger = logging.getLogger(__name__) res = [] - + for idxName, subName, lang, iso in idxs: srtname = '%s.srt' % os.path.splitext(idxName)[0] # Tesseract seems to recognize the three dots ... as "su" @@ -263,7 +263,7 @@ def doOCR(vobsubocr, idxs, duration, temporaries, dumpMemFD=False): write(srtfd, '...'.encode(encoding='UTF-8')) else: write(srtfd, line.encode(encoding='UTF-8')) - + m = re.match(timestamps, line) if m!=None: hours = int(m.group('hours')) @@ -274,7 +274,7 @@ def doOCR(vobsubocr, idxs, duration, temporaries, dumpMemFD=False): pb.update() status = ocr.wait() - + if status != 0: logger.error('OCR failed with status code: %d', status) @@ -286,7 +286,7 @@ def doOCR(vobsubocr, idxs, duration, temporaries, dumpMemFD=False): return None lseek(srtfd, 0, SEEK_SET) - srtLength = fstat(srtfd).st_size + srtLength = fstat(srtfd).st_size buf = read(srtfd, srtLength) outfd = dumpSrt.fileno() pos = 0 @@ -319,14 +319,14 @@ class SupportedFormat(IntEnum): else: return 'Unsupported format' -# Extract SPS/PPS +# Extract SPS/PPS # https://gitlab.com/mbunkus/mkvtoolnix/-/issues/2390 # ffmpeg -i -c:v copy -an -sn -bsf:v trace_headers -t 0.01 -report -loglevel 0 -f null - # Found codec private data using mkvinfo def getCodecPrivateDataFromMKV(mkvinfo, inputFile): logger = logging.getLogger(__name__) - + infd = inputFile.fileno() lseek(infd, 0, SEEK_SET) set_inheritable(infd, True) @@ -334,7 +334,7 @@ def getCodecPrivateDataFromMKV(mkvinfo, inputFile): env = {**os.environ, 'LANG': 'C'} # Output example # Codec's private data: size 48 (H.264 profile: High @L4.0) hexdump 01 64 00 28 ff e1 00 1b 67 64 00 28 ac d9 40 78 04 4f dc d4 04 04 05 00 00 92 ef 00 1d ad a6 1f 16 2d 96 01 00 06 68 fb a3 cb 22 c0 fd f8 f8 00 at 406 size 51 data size 48 - + with Popen([mkvinfo, '-z', '-X', '-P', '/proc/self/fd/%d' % infd ], stdout=PIPE, close_fds=False, env=env) as mkvinfo: out, _ = mkvinfo.communicate() out = out.decode('utf8') @@ -349,7 +349,7 @@ def getCodecPrivateDataFromMKV(mkvinfo, inputFile): found = True mkvinfo.wait() break - + if found: lseek(infd, position, SEEK_SET) data = read(infd, size) @@ -601,7 +601,7 @@ def writeScalingList(buf, bitPosition, size, matrix, optimized=False): # deltas.append(0) # for delta in deltas: # bitPosition = writeSignedExpGolomb(buf, bitPosition, delta) - + return bitPosition @dataclass @@ -1209,7 +1209,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[i] + v = self.top_left[i] bitPosition = writeUnsignedExpGolomb(buf, bitPosition, v) v = self.bottom_right[i] bitPosition = writeUnsignedExpGolomb(buf, bitPosition, v) @@ -1255,7 +1255,7 @@ class PPS: else: logger.info("Writing matrix: %s" % matrix) bitPosition = writeScalingList(buf, bitPosition, 64, matrix) - bitPosition = writeSignedExpGolomb(buf, bitPosition, self.second_chroma_qp_index_offset) + bitPosition = writeSignedExpGolomb(buf, bitPosition, self.second_chroma_qp_index_offset) bitPosition = writeRBSPTrailingBits(buf, bitPosition) @@ -1267,7 +1267,7 @@ class AVCDecoderConfiguration: AVCProfileIndication:int=0 # u(8) profile_compatibility:int=0 # u(8) AVCLevelIndication:int=0 # u(8) - lengthSizeMinusOne:int=0 # u(2) (0,1 or 3) + lengthSizeMinusOne:int=0 # u(2) (0,1 or 3) numOfSequenceParameterSets:int=0 # u(5) sps:dict = field(default_factory=dict) numOfPictureParameterSets:int=0 #u(8) @@ -1413,7 +1413,7 @@ class AVCDecoderConfiguration: bitPosition = writeBits(buf, bitPosition, self.bit_depth_chroma_minus8, 3) bitPosition = writeByte(buf, bitPosition, self.numOfSequenceParameterSetExt) for i in range(0, self.numOfSequenceParameterSetExt): - # TODO: dump SPSextended + # TODO: dump SPSextended logger.error('Dumping SPS extended not yet implemented') pass @@ -1477,7 +1477,7 @@ def parseCodecPrivate(codecPrivateData): for i in range(0, nbZeroes): length*=256 length+=(codecPrivateData[3+i]) - bytePosition = 3+nbZeroes + bytePosition = 3+nbZeroes avcconfig = AVCDecoderConfiguration() avcconfig.fromBytes(codecPrivateData[bytePosition:]) @@ -1586,10 +1586,10 @@ def parseMKVTree(mkvinfo, inputFile): # cf http://matroska-org.github.io/libebml/specs.html # It is a Type, Length, Value (TLV) kind of binary file. # Types are encoded as follows: -# 1xxx xxxx - Class A IDs (2^7 -1 possible values) +# 1xxx xxxx - Class A IDs (2^7 -1 possible values) # 01xx xxxx xxxx xxxx - Class B IDs (2^14-1 possible values) -# 001x xxxx xxxx xxxx xxxx xxxx - Class C IDs (2^21-1 possible values) -# 0001 xxxx xxxx xxxx xxxx xxxx xxxx xxxx - Class D IDs (2^28-1 possible values) +# 001x xxxx xxxx xxxx xxxx xxxx - Class C IDs (2^21-1 possible values) +# 0001 xxxx xxxx xxxx xxxx xxxx xxxx xxxx - Class D IDs (2^28-1 possible values) # Lengths are encoded as follows: # 1xxx xxxx - value 0 to 2^7-2 # 01xx xxxx xxxx xxxx - value 0 to 2^14-2 @@ -1609,7 +1609,7 @@ def getEBMLLength(length): elif length <= 2**14-2: size = 2 elif length <= 2**21-2: - size = 3 + size = 3 elif length <= 2**28-2: size = 4 elif length <= 2**35-2: @@ -1639,7 +1639,7 @@ def dumpCodecPrivateData(AVCDecoderConfiguration): # Code private element res.extend(b'\x63\xA2') buf = AVCDecoderConfiguration.toBytes() - logger.debug('AVC configuration bitstream: %s (length: %d))' % (hexdump.dump(buf, sep=':'), len(buf))) + logger.debug('AVC configuration bitstream: %s (length: %d))' % (hexdump.dump(buf, sep=':'), len(buf))) EMBLlength = getEBMLLength(len(buf)) logger.debug('EMBL encoded length: %s' % (hexdump.dump(EMBLlength, sep=':'))) @@ -1672,13 +1672,13 @@ def changeEBMLElementSize(inputFile, position, addendum): logger.error('Size of element type cannot be determined: %d', elementType) exit(-1) - # We seek to size + # We seek to size position+=typeSize lseek(infd, position, SEEK_SET) buf = read(infd, 1) sizeHead = int.from_bytes(buf, byteorder='big') - logger.info('First byte of size: %x' % sizeHead) + logger.info('First byte of size: %x' % sizeHead) mask=128 found = False for i in range(1,9): @@ -1714,7 +1714,7 @@ def changeEBMLElementSize(inputFile, position, addendum): exit(-1) # The difference of length between old size field and new one. delta = sizeOfNewEncodedSize - sizeOfDataSize - fileLength = fstat(infd).st_size + fileLength = fstat(infd).st_size # We seek after actual length field lseek(infd, position+sizeOfDataSize, SEEK_SET) # We read the rest of file @@ -1796,7 +1796,7 @@ def changeCodecPrivateData(mkvinfo, inputFile, codecData): logger.info(keys) delta = futureLength-currentLength - # if there is no modification of the private codec data, no need to change anything. + # if there is no modification of the private codec data, no need to change anything. if delta != 0: for i in range(0, len(keys)-1): keys.pop() @@ -2034,9 +2034,9 @@ def ffmpegConvert(ffmpeg, ffprobe, inputFile, inputFormat, outputFile, outputFor else: log = [ '-loglevel', 'quiet' ] - params = [ffmpeg, '-y',]+log+['-progress', '/dev/stdout', '-canvas_size', '%dx%d' % (width, height), '-f', inputFormat, '-i', '/proc/self/fd/%d' % infd, + params = [ffmpeg, '-y',]+log+['-progress', '/dev/stdout', '-canvas_size', '%dx%d' % (width, height), '-f', inputFormat, '-i', '/proc/self/fd/%d' % infd, '-map', '0:v', '-map', '0:a'] - if subtitles: + if subtitles: params.extend(['-map', '0:s']) params.extend(['-bsf:v', 'h264_mp4toannexb,dump_extra=freq=keyframe', '-vcodec', 'copy', '-acodec', 'copy']) if subtitles: @@ -2089,11 +2089,11 @@ def getFramesInStream(ffprobe, inputFile, begin, end, streamKind, subStreamId=0) logger = logging.getLogger(__name__) infd = inputFile.fileno() set_inheritable(infd, True) - - command = [ffprobe, '-loglevel', 'quiet', '-read_intervals', ('%s%%%s' %(begin, end)), '-show_entries', 'frame', + + command = [ffprobe, '-loglevel', 'quiet', '-read_intervals', ('%s%%%s' %(begin, end)), '-show_entries', 'frame', '-select_streams', '%s:%d' % (streamKind, subStreamId), '-of', 'json', '/proc/self/fd/%d' % infd] - logger.debug('Executing: %s' % command) - + logger.debug('Executing: %s', command) + with Popen(command, stdout=PIPE, close_fds=False) as ffprobe: out, _ = ffprobe.communicate() frames = json.load(BytesIO(out)) @@ -2101,7 +2101,7 @@ def getFramesInStream(ffprobe, inputFile, begin, end, streamKind, subStreamId=0) if status != 0: logger.error('ffprobe failed with status code: %d' % status) return None - + # Sort frames by timestamp tmp = {} if 'frames' in frames: @@ -2112,33 +2112,33 @@ def getFramesInStream(ffprobe, inputFile, begin, end, streamKind, subStreamId=0) return None if begin <= ts and ts <= end: tmp[ts]=frame - + res = [] for ts in sorted(tmp): res.append(tmp[ts]) - + return res else: logger.error('Impossible to retrieve frames inside file around [%s,%s]' % (begin, end)) return None -# TODO: +# TODO: def getNearestIDRFrame(ffprobe, inputFile, timestamp, before=True, delta=timedelta(seconds=2)): logger = logging.getLogger(__name__) - + zero = timedelta() tbegin = timestamp-delta tend = timestamp+delta if tbegin < zero: tbegin = zero - + infd = inputFile.fileno() set_inheritable(infd, True) - + 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' %(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() @@ -2159,16 +2159,13 @@ def getNearestIDRFrame(ffprobe, inputFile, timestamp, before=True, delta=timedel else: logger.error('Impossible to retrieve IDR frames inside file around [%s,%s]', tbegin, tend) return None - - - def getNearestIFrame(ffprobe, inputFile, timestamp, before=True, deltaMax=timedelta(seconds=15)): logger = logging.getLogger(__name__) - + infd = inputFile.fileno() set_inheritable(infd, True) - + delta = timedelta(seconds=1) iframe = None @@ -2184,26 +2181,26 @@ def getNearestIFrame(ffprobe, inputFile, timestamp, before=True, deltaMax=timede tend = timestamp if tbegin < zero: tbegin = zero - logger.debug('Looking for an iframe in [%s, %s]' % (tbegin, tend)) - + logger.debug('Looking for an iframe in [%s, %s]', tbegin, tend) + frames = getFramesInStream(ffprobe, inputFile=inputFile, begin=tbegin, end=tend, streamKind='v') if frames is None: - logger.debug('Found no frame in [%s, %s]' % (tbegin, tend)) + logger.debug('Found no frame in [%s, %s]', tbegin, tend) delta+=timedelta(seconds=1) continue - + iframes = [] for frame in frames: if frame['pict_type'] == 'I': iframes.append(frame) - + found = False for frame in iframes: ts = getTSFrame(frame) if ts is None: logger.warning('I-frame with no timestamp: %s' % frame) continue - + if before and ts <= timestamp: found = True iframe = frame @@ -2218,7 +2215,7 @@ def getNearestIFrame(ffprobe, inputFile, timestamp, before=True, deltaMax=timede else: delta+=timedelta(seconds=1) continue - + if iframe is not None: its = getTSFrame(iframe) nbFrames = 0 @@ -2296,7 +2293,7 @@ def extractPictures(ffmpeg, inputFile, begin, nbFrames, width=640, height=480): length = imageLength*nbFrames logger.debug("Estimated length: %d" % length) - command = [ffmpeg, '-loglevel', 'quiet' ,'-y', '-ss', '%s'%begin, '-i', '/proc/self/fd/%d' % infd, '-s', '%dx%d'%(width, height), + command = [ffmpeg, '-loglevel', 'quiet' ,'-y', '-ss', '%s'%begin, '-i', '/proc/self/fd/%d' % infd, '-s', '%dx%d'%(width, height), '-vframes', '%d'%nbFrames, '-c:v', 'ppm', '-f', 'image2pipe', '/proc/self/fd/%d' % outfd ] logger.debug('Executing: %s', command) @@ -2310,7 +2307,7 @@ def extractPictures(ffmpeg, inputFile, begin, nbFrames, width=640, height=480): lseek(outfd, 0, SEEK_SET) images = read(outfd,length) if len(images) != length: - logger.error("Received %d bytes but %d were expected." % (len(images), length)) + logger.error("Received %d bytes but %d were expected." % (len(images), length)) return None, None lseek(outfd, 0, SEEK_SET) @@ -2327,7 +2324,7 @@ def extractSound(ffmpeg, inputFile, begin, outputFileName, packetDuration, subCh sound = bytes() length = int(nbChannels*sampleRate*4*nbPackets*packetDuration/1000) - command = [ffmpeg, '-y', '-loglevel', 'quiet', '-ss', '%s'%begin, '-i', '/proc/self/fd/%d' % infd, '-frames:a:%d' % subChannel, '%d' % (nbPackets+1), + command = [ffmpeg, '-y', '-loglevel', 'quiet', '-ss', '%s'%begin, '-i', '/proc/self/fd/%d' % infd, '-frames:a:%d' % subChannel, '%d' % (nbPackets+1), '-c:a', 'pcm_s32le', '-sample_rate', '%d' % sampleRate, '-channels', '%d' % nbChannels, '-f', 's32le', '/proc/self/fd/%d' % outfd] logger.debug('Executing: %s', command) @@ -2349,7 +2346,7 @@ def extractSound(ffmpeg, inputFile, begin, outputFileName, packetDuration, subCh def dumpPPM(pictures, prefix, temporaries): logger = logging.getLogger(__name__) - # "P6\nWIDTH HEIGHT\n255\n" + # "P6\nWIDTH HEIGHT\n255\n" pos = 0 picture = 0 @@ -2362,7 +2359,7 @@ def dumpPPM(pictures, prefix, temporaries): dimensions = header.readline().decode('utf8') maxvalue = header.readline().decode('utf8') if magic == 'P6\n': - pattern = re.compile('^(?P[0-9]+) (?P[0-9]+)\n$') + pattern = re.compile('^(?P[0-9]+) (?P[0-9]+)\n$') m = pattern.match(dimensions) if m is not None: width = int(m['width']) @@ -2372,7 +2369,7 @@ def dumpPPM(pictures, prefix, temporaries): return else: logger.error('Not a PPM picture') - return + return headerLen=2+1+ceil(log(width, 10))+1+ceil(log(height, 10))+1+3+1 try: @@ -2394,7 +2391,7 @@ def extractAllStreams(ffmpeg, ffprobe, inputFile, begin, end, streams, filesPref logger = logging.getLogger(__name__) # The command line for encoding only video track - videoEncoderParams = [ ffmpeg, '-y', '-loglevel', 'quiet'] + videoEncoderParams = [ ffmpeg, '-y', '-loglevel', 'quiet'] videoInputParams = [] videoCodecParams = [] @@ -2419,7 +2416,7 @@ def extractAllStreams(ffmpeg, ffprobe, inputFile, begin, end, streams, filesPref colorTransfer = stream['color_transfer'] colorPrimaries = stream['color_primaries'] level = int(stream['level']) - level = '%d.%d' % (floor(level/10), level%10) + level = '%d.%d' % (floor(level/10), level%10) chromaLocation = stream['chroma_location'] fieldOrder = stream interlacedOptions = [] @@ -2627,7 +2624,7 @@ def mergeMKVs(mkvmerge, inputs, outputName, concatenate=True, timestamps=None): fd = mkv.fileno() fds.append(fd) set_inheritable(fd, True) - # If we pass a timestamps file associated with the considered track, use it. + # If we pass a timestamps file associated with the considered track, use it. if timestamps is not None and partNum in timestamps: tsfd = timestamps[partNum].fileno() lseek(tsfd, 0, SEEK_SET) @@ -2825,7 +2822,7 @@ def concatenateH264Parts(h264parts, output): totalLength = 0 for h264 in h264parts: fd = h264.fileno() - totalLength += fstat(fd).st_size + totalLength += fstat(fd).st_size logger.info('Total length: %d', totalLength) @@ -2843,7 +2840,7 @@ def concatenateH264Parts(h264parts, output): pos = 0 while pos < len(buf): nbBytes = write(outfd, buf[pos:]) - pb.update(nbBytes) + pb.update(nbBytes) pos += nbBytes def concatenateH264TSParts(h264TSParts, output): @@ -3001,7 +2998,7 @@ def main(): if formatOfFile == SupportedFormat.TS: logger.info("Converting TS to MP4 (to fix timestamps).") try: - with open(mp4filename, 'w+') as mp4: + with open(mp4filename, 'w+') as mp4: ffmpegConvert(paths['ffmpeg'], paths['ffprobe'], inputFile, 'mpegts', mp4, 'mp4', duration) temporaries.append(mp4) logger.info("Converting MP4 to MKV.") @@ -3094,7 +3091,7 @@ def main(): # Si la trame de début est déjà 'I', il n'y a rien à faire. # Sinon on extrait les trames 'B' ou 'P' depuis le début jusqu'à la trame 'I' non incluse. # Si la trame de fin précède une trame I, on n'a rien à faire. - # Sinon on extrait toutes les trames depuis la dernière trame I jusqu'à la trame de fin. + # Sinon on extrait toutes les trames depuis la dernière trame I jusqu'à la trame de fin. partnum = partnum + 1 @@ -3226,7 +3223,7 @@ def main(): checks.append(pos) # When using coarse option there is a single AVC configuration. - for avcConfig in otherAvcConfigs: + for avcConfig in otherAvcConfigs: mainAvcConfig.merge(avcConfig) logger.debug('Merged AVC configuration: %s', mainAvcConfig) @@ -3279,7 +3276,7 @@ def main(): finalWithVideo = mergeMKVs(mkvmerge=paths['mkvmerge'], inputs=[fullH264, finalNoVideo], outputName=finalWithVideoName, concatenate=False, timestamps={0: fullH264TS}) finalCodecPrivateData = dumpCodecPrivateData(mainAvcConfig) logger.debug('Final codec private data: %s' % hexdump.dump(finalCodecPrivateData, sep=':')) - logger.info('Changing codec private data with the new one.') + logger.info('Changing codec private data with the new one.') changeCodecPrivateData(paths['mkvinfo'], finalWithVideo, finalCodecPrivateData) if args.srt: