diff --git a/yt_dlp/YoutubeDL.py b/yt_dlp/YoutubeDL.py index bf3eef67b..37af2f3fb 100644 --- a/yt_dlp/YoutubeDL.py +++ b/yt_dlp/YoutubeDL.py @@ -570,14 +570,9 @@ class YoutubeDL(object): self.add_default_info_extractors() for pp_def_raw in self.params.get('postprocessors', []): - pp_class = get_postprocessor(pp_def_raw['key']) pp_def = dict(pp_def_raw) - del pp_def['key'] - if 'when' in pp_def: - when = pp_def['when'] - del pp_def['when'] - else: - when = 'post_process' + when = pp_def.pop('when', 'post_process') + pp_class = get_postprocessor(pp_def.pop('key')) pp = pp_class(self, **compat_kwargs(pp_def)) self.add_post_processor(pp, when=when) @@ -2685,65 +2680,48 @@ class YoutubeDL(object): return if success and full_filename != '-': - # Fixup content - fixup_policy = self.params.get('fixup') - if fixup_policy is None: - fixup_policy = 'detect_or_warn' - INSTALL_FFMPEG_MESSAGE = 'Install ffmpeg to fix this automatically.' + def fixup(): + do_fixup = True + fixup_policy = self.params.get('fixup') + vid = info_dict['id'] - stretched_ratio = info_dict.get('stretched_ratio') - if stretched_ratio is not None and stretched_ratio != 1: - if fixup_policy == 'warn': - self.report_warning('%s: Non-uniform pixel ratio (%s)' % ( - info_dict['id'], stretched_ratio)) - elif fixup_policy == 'detect_or_warn': - stretched_pp = FFmpegFixupStretchedPP(self) - if stretched_pp.available: - info_dict['__postprocessors'].append(stretched_pp) + if fixup_policy in ('ignore', 'never'): + return + elif fixup_policy == 'warn': + do_fixup = False + assert fixup_policy in ('detect_or_warn', None) + + def ffmpeg_fixup(cndn, msg, cls): + if not cndn: + return + if not do_fixup: + self.report_warning(f'{vid}: {msg}') + return + pp = cls(self) + if pp.available: + info_dict['__postprocessors'].append(pp) else: - self.report_warning( - '%s: Non-uniform pixel ratio (%s). %s' - % (info_dict['id'], stretched_ratio, INSTALL_FFMPEG_MESSAGE)) - else: - assert fixup_policy in ('ignore', 'never') + self.report_warning(f'{vid}: {msg}. Install ffmpeg to fix this automatically') - if (info_dict.get('requested_formats') is None - and info_dict.get('container') == 'm4a_dash' - and info_dict.get('ext') == 'm4a'): - if fixup_policy == 'warn': - self.report_warning( - '%s: writing DASH m4a. ' - 'Only some players support this container.' - % info_dict['id']) - elif fixup_policy == 'detect_or_warn': - fixup_pp = FFmpegFixupM4aPP(self) - if fixup_pp.available: - info_dict['__postprocessors'].append(fixup_pp) - else: - self.report_warning( - '%s: writing DASH m4a. ' - 'Only some players support this container. %s' - % (info_dict['id'], INSTALL_FFMPEG_MESSAGE)) - else: - assert fixup_policy in ('ignore', 'never') + stretched_ratio = info_dict.get('stretched_ratio') + ffmpeg_fixup( + stretched_ratio not in (1, None), + f'Non-uniform pixel ratio {stretched_ratio}', + FFmpegFixupStretchedPP) - if ('protocol' in info_dict - and get_suitable_downloader(info_dict, self.params).__name__ == 'HlsFD'): - if fixup_policy == 'warn': - self.report_warning('%s: malformed AAC bitstream detected.' % ( - info_dict['id'])) - elif fixup_policy == 'detect_or_warn': - fixup_pp = FFmpegFixupM3u8PP(self) - if fixup_pp.available: - info_dict['__postprocessors'].append(fixup_pp) - else: - self.report_warning( - '%s: malformed AAC bitstream detected. %s' - % (info_dict['id'], INSTALL_FFMPEG_MESSAGE)) - else: - assert fixup_policy in ('ignore', 'never') + ffmpeg_fixup( + (info_dict.get('requested_formats') is None + and info_dict.get('container') == 'm4a_dash' + and info_dict.get('ext') == 'm4a'), + 'writing DASH m4a. Only some players support this container', + FFmpegFixupM4aPP) + downloader = (get_suitable_downloader(info_dict, self.params).__name__ + if 'protocol' in info_dict else None) + ffmpeg_fixup(downloader == 'HlsFD', 'malformed AAC bitstream detected', FFmpegFixupM3u8PP) + + fixup() try: info_dict = self.post_process(dl_filename, info_dict, files_to_move) except PostProcessingError as err: diff --git a/yt_dlp/options.py b/yt_dlp/options.py index eb137ac47..0d1960d9f 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1230,6 +1230,7 @@ def parseOpts(overrideArguments=None): postproc.add_option( '--fixup', metavar='POLICY', dest='fixup', default=None, + choices=('never', 'ignore', 'warn', 'detect_or_warn'), help=( 'Automatically correct known faults of the file. ' 'One of never (do nothing), warn (only emit a warning), ' diff --git a/yt_dlp/postprocessor/ffmpeg.py b/yt_dlp/postprocessor/ffmpeg.py index 273f1b763..49685951e 100644 --- a/yt_dlp/postprocessor/ffmpeg.py +++ b/yt_dlp/postprocessor/ffmpeg.py @@ -661,58 +661,42 @@ class FFmpegMergerPP(FFmpegPostProcessor): return True -class FFmpegFixupStretchedPP(FFmpegPostProcessor): +class FFmpegFixupPostProcessor(FFmpegPostProcessor): + def _fixup(self, msg, filename, options): + temp_filename = prepend_extension(filename, 'temp') + + self.to_screen('{msg} of "{filename}"') + self.run_ffmpeg(filename, temp_filename, options) + + os.remove(encodeFilename(filename)) + os.rename(encodeFilename(temp_filename), encodeFilename(filename)) + + +class FFmpegFixupStretchedPP(FFmpegFixupPostProcessor): @PostProcessor._restrict_to(images=False, audio=False) def run(self, info): stretched_ratio = info.get('stretched_ratio') - if stretched_ratio is None or stretched_ratio == 1: - return [], info - - filename = info['filepath'] - temp_filename = prepend_extension(filename, 'temp') - - options = ['-c', 'copy', '-map', '0', '-dn', '-aspect', '%f' % stretched_ratio] - self.to_screen('Fixing aspect ratio in "%s"' % filename) - self.run_ffmpeg(filename, temp_filename, options) - - os.remove(encodeFilename(filename)) - os.rename(encodeFilename(temp_filename), encodeFilename(filename)) - + if stretched_ratio not in (None, 1): + self._fixup('Fixing aspect ratio', info['filepath'], [ + '-c', 'copy', '-map', '0', '-dn', '-aspect', '%f' % stretched_ratio]) return [], info -class FFmpegFixupM4aPP(FFmpegPostProcessor): +class FFmpegFixupM4aPP(FFmpegFixupPostProcessor): @PostProcessor._restrict_to(images=False, video=False) def run(self, info): - if info.get('container') != 'm4a_dash': - return [], info - - filename = info['filepath'] - temp_filename = prepend_extension(filename, 'temp') - - options = ['-c', 'copy', '-map', '0', '-dn', '-f', 'mp4'] - self.to_screen('Correcting container in "%s"' % filename) - self.run_ffmpeg(filename, temp_filename, options) - - os.remove(encodeFilename(filename)) - os.rename(encodeFilename(temp_filename), encodeFilename(filename)) - + if info.get('container') == 'm4a_dash': + self._fixup('Correcting container', info['filepath'], [ + '-c', 'copy', '-map', '0', '-dn', '-f', 'mp4']) return [], info -class FFmpegFixupM3u8PP(FFmpegPostProcessor): +class FFmpegFixupM3u8PP(FFmpegFixupPostProcessor): @PostProcessor._restrict_to(images=False) def run(self, info): - filename = info['filepath'] - if self.get_audio_codec(filename) == 'aac': - temp_filename = prepend_extension(filename, 'temp') - - options = ['-c', 'copy', '-map', '0', '-dn', '-f', 'mp4', '-bsf:a', 'aac_adtstoasc'] - self.to_screen('Fixing malformed AAC bitstream in "%s"' % filename) - self.run_ffmpeg(filename, temp_filename, options) - - os.remove(encodeFilename(filename)) - os.rename(encodeFilename(temp_filename), encodeFilename(filename)) + if self.get_audio_codec(info['filepath']) == 'aac': + self._fixup('Fixing malformed AAC bitstream', info['filepath'], [ + '-c', 'copy', '-map', '0', '-dn', '-f', 'mp4', '-bsf:a', 'aac_adtstoasc']) return [], info