From 857f63136d4f46b18353f8e50b07ff1394b79695 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sat, 22 May 2021 13:08:12 +0530 Subject: [PATCH] [videoconvertor] Generalize with remuxer and allow conditional recoding --- yt_dlp/options.py | 3 +- yt_dlp/postprocessor/ffmpeg.py | 87 ++++++++++++++++------------------ 2 files changed, 42 insertions(+), 48 deletions(-) diff --git a/yt_dlp/options.py b/yt_dlp/options.py index c982dbb84..812bee572 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1141,7 +1141,8 @@ def parseOpts(overrideArguments=None): metavar='FORMAT', dest='recodevideo', default=None, help=( 'Re-encode the video into another format if re-encoding is necessary. ' - 'The supported formats are the same as --remux-video')) + 'You can specify multiple rules similar to --remux-video. ' + 'The supported formats are also the same as --remux-video')) postproc.add_option( '--postprocessor-args', '--ppa', metavar='NAME:ARGS', dest='postprocessor_args', default={}, type='str', diff --git a/yt_dlp/postprocessor/ffmpeg.py b/yt_dlp/postprocessor/ffmpeg.py index f2e3559a5..810c9cb86 100644 --- a/yt_dlp/postprocessor/ffmpeg.py +++ b/yt_dlp/postprocessor/ffmpeg.py @@ -399,64 +399,57 @@ class FFmpegExtractAudioPP(FFmpegPostProcessor): return [path], information -class FFmpegVideoRemuxerPP(FFmpegPostProcessor): - def __init__(self, downloader=None, preferedformat=None): - super(FFmpegVideoRemuxerPP, self).__init__(downloader) - self._preferedformats = preferedformat.lower().split('/') - - def run(self, information): - path = information['filepath'] - sourceext, targetext = information['ext'].lower(), None - for pair in self._preferedformats: - kv = pair.split('>') - if len(kv) == 1 or kv[0].strip() == sourceext: - targetext = kv[-1].strip() - break - - _skip_msg = ( - 'could not find a mapping for %s' if not targetext - else 'already is in target format %s' if sourceext == targetext - else None) - if _skip_msg: - self.to_screen('Not remuxing media file %s; %s' % (path, _skip_msg % sourceext)) - return [], information - - options = ['-c', 'copy', '-map', '0', '-dn'] - if targetext in ['mp4', 'm4a', 'mov']: - options.extend(['-movflags', '+faststart']) - prefix, sep, oldext = path.rpartition('.') - outpath = prefix + sep + targetext - self.to_screen('Remuxing video from %s to %s; Destination: %s' % (sourceext, targetext, outpath)) - self.run_ffmpeg(path, outpath, options) - information['filepath'] = outpath - information['format'] = targetext - information['ext'] = targetext - return [path], information - - class FFmpegVideoConvertorPP(FFmpegPostProcessor): + _action = 'converting' + def __init__(self, downloader=None, preferedformat=None): super(FFmpegVideoConvertorPP, self).__init__(downloader) - self._preferedformat = preferedformat + self._preferedformats = preferedformat.lower().split('/') + + def _target_ext(self, source_ext): + for pair in self._preferedformats: + kv = pair.split('>') + if len(kv) == 1 or kv[0].strip() == source_ext: + return kv[-1].strip() + + @staticmethod + def _options(target_ext): + if target_ext == 'avi': + return ['-c:v', 'libxvid', '-vtag', 'XVID'] + return [] def run(self, information): path = information['filepath'] - if information['ext'] == self._preferedformat: - self.to_screen('Not converting video file %s - already is in target format %s' % (path, self._preferedformat)) + target_ext = self._target_ext(information['ext'].lower()) + _skip_msg = ( + 'could not find a mapping for %s' if not target_ext + else 'already is in target format %s' if source_ext == target_ext + else None) + if _skip_msg: + self.to_screen('Not %s media file %s; %s' % (self._action, path, _skip_msg % source_ext)) return [], information - options = [] - if self._preferedformat == 'avi': - options.extend(['-c:v', 'libxvid', '-vtag', 'XVID']) - prefix, sep, ext = path.rpartition('.') - outpath = prefix + sep + self._preferedformat - self.to_screen('Converting video from %s to %s, Destination: ' % (information['ext'], self._preferedformat) + outpath) - self.run_ffmpeg(path, outpath, options) + + prefix, sep, oldext = path.rpartition('.') + outpath = prefix + sep + target_ext + self.to_screen('%s video from %s to %s; Destination: %s' % (self._action.title(), source_ext, target_ext, outpath)) + self.run_ffmpeg(path, outpath, self._options(target_ext)) + information['filepath'] = outpath - information['format'] = self._preferedformat - information['ext'] = self._preferedformat + information['format'] = information['ext'] = target_ext return [path], information +class FFmpegVideoRemuxerPP(FFmpegVideoConvertorPP): + _action = 'remuxing' + + @staticmethod + def _options(target_ext): + options = ['-c', 'copy', '-map', '0', '-dn'] + if target_ext in ['mp4', 'm4a', 'mov']: + options.extend(['-movflags', '+faststart']) + return options + + class FFmpegEmbedSubtitlePP(FFmpegPostProcessor): def __init__(self, downloader=None, already_have_subtitle=False): super(FFmpegEmbedSubtitlePP, self).__init__(downloader)