From 1b77b347d422ed70fd833a9f0327ea418ba4919c Mon Sep 17 00:00:00 2001 From: pukkandan Date: Fri, 8 Jan 2021 00:58:41 +0530 Subject: [PATCH] Allow passing different arguments to different postprocessors * Also deprecated --sponskrub-args Closes: https://github.com/ytdl-org/youtube-dl/issues/27593 Eg: `--postprocessor-args "VideoConvertor:-c:v h264_nvenc -preset slow"` Eg: `--postprocessor-args "SponsKrub:-include-selfpromo"` For backward compatibility, `--postprocessor-args args` is equivalent to: `--post-processor-args "sponskrub:" --post-processor-args "default:args"` --- README.md | 13 ++++- youtube_dlc/YoutubeDL.py | 5 +- youtube_dlc/__init__.py | 20 ++++++-- youtube_dlc/options.py | 13 +++-- youtube_dlc/postprocessor/common.py | 10 +++- youtube_dlc/postprocessor/embedthumbnail.py | 15 +++--- .../postprocessor/execafterdownload.py | 4 +- youtube_dlc/postprocessor/ffmpeg.py | 49 ++++++++++--------- .../postprocessor/metadatafromtitle.py | 8 +-- youtube_dlc/postprocessor/sponskrub.py | 14 +++--- youtube_dlc/postprocessor/xattrpp.py | 3 +- 11 files changed, 96 insertions(+), 58 deletions(-) diff --git a/README.md b/README.md index 8a7e1b6db0..0e2225d5ac 100644 --- a/README.md +++ b/README.md @@ -550,7 +550,18 @@ ## Post-Processing Options: --recode-video FORMAT Re-encode the video into another format if re-encoding is necessary (currently supported: mp4|flv|ogg|webm|mkv|avi) - --postprocessor-args ARGS Give these arguments to the postprocessor + --postprocessor-args NAME:ARGS Give these arguments to the postprocessors. + Specify the postprocessor name and the + arguments separated by a colon ':' to give + the argument to only the specified + postprocessor. Supported names are + ExtractAudio, VideoRemuxer, VideoConvertor, + EmbedSubtitle, Metadata, Merger, + FixupStretched, FixupM4a, FixupM3u8, + SubtitlesConvertor, SponSkrub and Default. + You can use this option multiple times to + give different arguments to different + postprocessors -k, --keep-video Keep the intermediate video file on disk after post-processing --no-keep-video Delete the intermediate video file after diff --git a/youtube_dlc/YoutubeDL.py b/youtube_dlc/YoutubeDL.py index 01d26cff2c..fbd40cf734 100644 --- a/youtube_dlc/YoutubeDL.py +++ b/youtube_dlc/YoutubeDL.py @@ -333,8 +333,9 @@ class YoutubeDL(object): otherwise prefer ffmpeg. ffmpeg_location: Location of the ffmpeg/avconv binary; either the path to the binary or its containing directory. - postprocessor_args: A list of additional command-line arguments for the - postprocessor. + postprocessor_args: A dictionary of postprocessor names (in lower case) and a list + of additional command-line arguments for the postprocessor. + Use 'default' as the name for arguments to passed to all PP. The following options are used by the Youtube extractor: youtube_include_dash_manifest: If True (default), DASH manifests and related diff --git a/youtube_dlc/__init__.py b/youtube_dlc/__init__.py index dd8925d68d..e68942187c 100644 --- a/youtube_dlc/__init__.py +++ b/youtube_dlc/__init__.py @@ -331,9 +331,23 @@ def parse_retries(retries): external_downloader_args = None if opts.external_downloader_args: external_downloader_args = compat_shlex_split(opts.external_downloader_args) - postprocessor_args = None - if opts.postprocessor_args: - postprocessor_args = compat_shlex_split(opts.postprocessor_args) + + postprocessor_args = {} + if opts.postprocessor_args is not None: + for string in opts.postprocessor_args: + mobj = re.match(r'(?P\w+):(?P.*)$', string) + if mobj is None: + if 'sponskrub' not in postprocessor_args: # for backward compatibility + postprocessor_args['sponskrub'] = [] + if opts.verbose: + write_string('[debug] Adding postprocessor args from command line option sponskrub:\n') + pp_name, pp_args = 'default', string + else: + pp_name, pp_args = mobj.group('pp').lower(), mobj.group('args') + if opts.verbose: + write_string('[debug] Adding postprocessor args from command line option %s:%s\n' % (pp_name, pp_args)) + postprocessor_args[pp_name] = compat_shlex_split(pp_args) + match_filter = ( None if opts.match_filter is None else match_filter_func(opts.match_filter)) diff --git a/youtube_dlc/options.py b/youtube_dlc/options.py index 3a7249ee64..b00db519aa 100644 --- a/youtube_dlc/options.py +++ b/youtube_dlc/options.py @@ -970,9 +970,14 @@ def _comma_separated_values_options_callback(option, opt_str, value, parser): metavar='FORMAT', dest='recodevideo', default=None, help='Re-encode the video into another format if re-encoding is necessary (currently supported: mp4|flv|ogg|webm|mkv|avi)') postproc.add_option( - '--postprocessor-args', - dest='postprocessor_args', metavar='ARGS', - help='Give these arguments to the postprocessor') + '--postprocessor-args', metavar='NAME:ARGS', + dest='postprocessor_args', action='append', + help=( + 'Give these arguments to the postprocessors. ' + "Specify the postprocessor name and the arguments separated by a colon ':' " + 'to give the argument to only the specified postprocessor. Supported names are ' + 'ExtractAudio, VideoRemuxer, VideoConvertor, EmbedSubtitle, Metadata, Merger, FixupStretched, FixupM4a, FixupM3u8, SubtitlesConvertor, SponSkrub and Default' + '. You can use this option multiple times to give different arguments to different postprocessors')) postproc.add_option( '-k', '--keep-video', action='store_true', dest='keepvideo', default=False, @@ -1089,7 +1094,7 @@ def _comma_separated_values_options_callback(option, opt_str, value, parser): help='Location of the sponskrub binary; either the path to the binary or its containing directory.') sponskrub.add_option( '--sponskrub-args', dest='sponskrub_args', metavar='ARGS', - help='Give these arguments to sponskrub') + help=optparse.SUPPRESS_HELP) extractor = optparse.OptionGroup(parser, 'Extractor Options') extractor.add_option( diff --git a/youtube_dlc/postprocessor/common.py b/youtube_dlc/postprocessor/common.py index 599dd1df2b..6e84ff592a 100644 --- a/youtube_dlc/postprocessor/common.py +++ b/youtube_dlc/postprocessor/common.py @@ -33,6 +33,11 @@ class PostProcessor(object): def __init__(self, downloader=None): self._downloader = downloader + if not hasattr(self, 'PP_NAME'): + self.PP_NAME = self.__class__.__name__[:-2] + + def to_screen(self, text, *args, **kwargs): + return self._downloader.to_screen('[%s] %s' % (self.PP_NAME, text), *args, **kwargs) def set_downloader(self, downloader): """Sets the downloader for this PP.""" @@ -62,7 +67,10 @@ def try_utime(self, path, atime, mtime, errnote='Cannot update utime of file'): self._downloader.report_warning(errnote) def _configuration_args(self, default=[]): - return cli_configuration_args(self._downloader.params, 'postprocessor_args', default) + args = self._downloader.params.get('postprocessor_args', {}) + if isinstance(args, list): # for backward compatibility + args = {'default': args, 'sponskrub': []} + return cli_configuration_args(args, self.PP_NAME.lower(), args.get('default', [])) class AudioConversionError(PostProcessingError): diff --git a/youtube_dlc/postprocessor/embedthumbnail.py b/youtube_dlc/postprocessor/embedthumbnail.py index 50678669f5..aaf58e0a01 100644 --- a/youtube_dlc/postprocessor/embedthumbnail.py +++ b/youtube_dlc/postprocessor/embedthumbnail.py @@ -23,6 +23,8 @@ class EmbedThumbnailPPError(PostProcessingError): class EmbedThumbnailPP(FFmpegPostProcessor): + PP_NAME = 'EmbedThumbnail' + def __init__(self, downloader=None, already_have_thumbnail=False): super(EmbedThumbnailPP, self).__init__(downloader) self._already_have_thumbnail = already_have_thumbnail @@ -32,7 +34,7 @@ def run(self, info): temp_filename = prepend_extension(filename, 'temp') if not info.get('thumbnails'): - self._downloader.to_screen('[embedthumbnail] There aren\'t any thumbnails to embed') + self.to_screen('There aren\'t any thumbnails to embed') return [], info thumbnail_filename = info['thumbnails'][-1]['filename'] @@ -52,8 +54,7 @@ def is_webp(path): if thumbnail_ext: thumbnail_ext = thumbnail_ext[1:].lower() if thumbnail_ext != 'webp' and is_webp(thumbnail_filename): - self._downloader.to_screen( - '[ffmpeg] Correcting extension to webp and escaping path for thumbnail "%s"' % thumbnail_filename) + self.to_screen('Correcting extension to webp and escaping path for thumbnail "%s"' % thumbnail_filename) thumbnail_webp_filename = replace_extension(thumbnail_filename, 'webp') os.rename(encodeFilename(thumbnail_filename), encodeFilename(thumbnail_webp_filename)) thumbnail_filename = thumbnail_webp_filename @@ -66,7 +67,7 @@ def is_webp(path): escaped_thumbnail_filename = thumbnail_filename.replace('%', '#') os.rename(encodeFilename(thumbnail_filename), encodeFilename(escaped_thumbnail_filename)) escaped_thumbnail_jpg_filename = replace_extension(escaped_thumbnail_filename, 'jpg') - self._downloader.to_screen('[ffmpeg] Converting thumbnail "%s" to JPEG' % escaped_thumbnail_filename) + self.to_screen('Converting thumbnail "%s" to JPEG' % escaped_thumbnail_filename) self.run_ffmpeg(escaped_thumbnail_filename, escaped_thumbnail_jpg_filename, ['-bsf:v', 'mjpeg2jpeg']) os.remove(encodeFilename(escaped_thumbnail_filename)) thumbnail_jpg_filename = replace_extension(thumbnail_filename, 'jpg') @@ -79,7 +80,7 @@ def is_webp(path): '-c', 'copy', '-map', '0:0', '-map', '1:0', '-id3v2_version', '3', '-metadata:s:v', 'title="Album cover"', '-metadata:s:v', 'comment="Cover (front)"'] - self._downloader.to_screen('[ffmpeg] Adding thumbnail to "%s"' % filename) + self.to_screen('Adding thumbnail to "%s"' % filename) self.run_ffmpeg_multiple_files([filename, thumbnail_filename], temp_filename, options) @@ -99,7 +100,7 @@ def is_webp(path): '-c', 'copy', '-map', '0', '-dn', '-attach', thumbnail_filename, '-metadata:s:t', 'mimetype=image/jpeg'] - self._downloader.to_screen('[ffmpeg] Adding thumbnail to "%s"' % filename) + self.to_screen('Adding thumbnail to "%s"' % filename) self.run_ffmpeg_multiple_files([filename], temp_filename, options) @@ -121,7 +122,7 @@ def is_webp(path): encodeArgument('-o'), encodeFilename(temp_filename, True)] - self._downloader.to_screen('[atomicparsley] Adding thumbnail to "%s"' % filename) + self.to_screen('Adding thumbnail to "%s"' % filename) if self._downloader.params.get('verbose', False): self._downloader.to_screen('[debug] AtomicParsley command line: %s' % shell_quote(cmd)) diff --git a/youtube_dlc/postprocessor/execafterdownload.py b/youtube_dlc/postprocessor/execafterdownload.py index 64dabe790b..4083cea3e4 100644 --- a/youtube_dlc/postprocessor/execafterdownload.py +++ b/youtube_dlc/postprocessor/execafterdownload.py @@ -11,6 +11,8 @@ class ExecAfterDownloadPP(PostProcessor): + PP_NAME = 'Exec' + def __init__(self, downloader, exec_cmd): super(ExecAfterDownloadPP, self).__init__(downloader) self.exec_cmd = exec_cmd @@ -22,7 +24,7 @@ def run(self, information): cmd = cmd.replace('{}', compat_shlex_quote(information['filepath'])) - self._downloader.to_screen('[exec] Executing command: %s' % cmd) + self.to_screen('Executing command: %s' % cmd) retCode = subprocess.call(encodeArgument(cmd), shell=True) if retCode != 0: raise PostProcessingError( diff --git a/youtube_dlc/postprocessor/ffmpeg.py b/youtube_dlc/postprocessor/ffmpeg.py index 35939dbb05..2141d6311f 100644 --- a/youtube_dlc/postprocessor/ffmpeg.py +++ b/youtube_dlc/postprocessor/ffmpeg.py @@ -53,6 +53,8 @@ class FFmpegPostProcessorError(PostProcessingError): class FFmpegPostProcessor(PostProcessor): def __init__(self, downloader=None): + if not hasattr(self, 'PP_NAME'): + self.PP_NAME = self.__class__.__name__[6:-2] # Remove ffmpeg from the front PostProcessor.__init__(self, downloader) self._determine_executables() @@ -328,11 +330,11 @@ def run(self, information): # If we download foo.mp3 and convert it to... foo.mp3, then don't delete foo.mp3, silly. if (new_path == path or (self._nopostoverwrites and os.path.exists(encodeFilename(new_path)))): - self._downloader.to_screen('[ffmpeg] Post-process file %s exists, skipping' % new_path) + self.to_screen('Post-process file %s exists, skipping' % new_path) return [], information try: - self._downloader.to_screen('[ffmpeg] Destination: ' + new_path) + self.to_screen('Destination: ' + new_path) self.run_ffmpeg(path, new_path, acodec, more_opts) except AudioConversionError as e: raise PostProcessingError( @@ -357,12 +359,12 @@ def __init__(self, downloader=None, preferedformat=None): def run(self, information): path = information['filepath'] if information['ext'] == self._preferedformat: - self._downloader.to_screen('[ffmpeg] Not remuxing video file %s - already is in target format %s' % (path, self._preferedformat)) + self.to_screen('Not remuxing video file %s - already is in target format %s' % (path, self._preferedformat)) return [], information options = ['-c', 'copy', '-map', '0', '-dn'] prefix, sep, ext = path.rpartition('.') outpath = prefix + sep + self._preferedformat - self._downloader.to_screen('[' + 'ffmpeg' + '] Remuxing video from %s to %s, Destination: ' % (information['ext'], self._preferedformat) + outpath) + self.to_screen('Remuxing video from %s to %s, Destination: ' % (information['ext'], self._preferedformat) + outpath) self.run_ffmpeg(path, outpath, options) information['filepath'] = outpath information['format'] = self._preferedformat @@ -378,14 +380,14 @@ def __init__(self, downloader=None, preferedformat=None): def run(self, information): path = information['filepath'] if information['ext'] == self._preferedformat: - self._downloader.to_screen('[ffmpeg] Not converting video file %s - already is in target format %s' % (path, self._preferedformat)) + self.to_screen('Not converting video file %s - already is in target format %s' % (path, self._preferedformat)) 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._downloader.to_screen('[' + 'ffmpeg' + '] Converting video from %s to %s, Destination: ' % (information['ext'], self._preferedformat) + outpath) + self.to_screen('Converting video from %s to %s, Destination: ' % (information['ext'], self._preferedformat) + outpath) self.run_ffmpeg(path, outpath, options) information['filepath'] = outpath information['format'] = self._preferedformat @@ -396,11 +398,11 @@ def run(self, information): class FFmpegEmbedSubtitlePP(FFmpegPostProcessor): def run(self, information): if information['ext'] not in ('mp4', 'webm', 'mkv'): - self._downloader.to_screen('[ffmpeg] Subtitles can only be embedded in mp4, webm or mkv files') + self.to_screen('Subtitles can only be embedded in mp4, webm or mkv files') return [], information subtitles = information.get('requested_subtitles') if not subtitles: - self._downloader.to_screen('[ffmpeg] There aren\'t any subtitles to embed') + self.to_screen('There aren\'t any subtitles to embed') return [], information filename = information['filepath'] @@ -413,14 +415,14 @@ def run(self, information): for lang, sub_info in subtitles.items(): sub_ext = sub_info['ext'] if sub_ext == 'json': - self._downloader.to_screen('[ffmpeg] JSON subtitles cannot be embedded') + self.to_screen('JSON subtitles cannot be embedded') elif ext != 'webm' or ext == 'webm' and sub_ext == 'vtt': sub_langs.append(lang) sub_filenames.append(subtitles_filename(filename, lang, sub_ext, ext)) else: if not webm_vtt_warn and ext == 'webm' and sub_ext != 'vtt': webm_vtt_warn = True - self._downloader.to_screen('[ffmpeg] Only WebVTT subtitles can be embedded in webm files') + self.to_screen('Only WebVTT subtitles can be embedded in webm files') if not sub_langs: return [], information @@ -444,7 +446,7 @@ def run(self, information): opts.extend(['-metadata:s:s:%d' % i, 'language=%s' % lang_code]) temp_filename = prepend_extension(filename, 'temp') - self._downloader.to_screen('[ffmpeg] Embedding subtitles in \'%s\'' % filename) + self.to_screen('Embedding subtitles in \'%s\'' % filename) self.run_ffmpeg_multiple_files(input_files, temp_filename, opts) os.remove(encodeFilename(filename)) os.rename(encodeFilename(temp_filename), encodeFilename(filename)) @@ -492,7 +494,7 @@ def add(meta_list, info_list=None): add('episode_sort', 'episode_number') if not metadata: - self._downloader.to_screen('[ffmpeg] There isn\'t any metadata to add') + self.to_screen('There isn\'t any metadata to add') return [], info filename = info['filepath'] @@ -527,7 +529,7 @@ def ffmpeg_escape(text): in_filenames.append(metadata_filename) options.extend(['-map_metadata', '1']) - self._downloader.to_screen('[ffmpeg] Adding metadata to \'%s\'' % filename) + self.to_screen('Adding metadata to \'%s\'' % filename) self.run_ffmpeg_multiple_files(in_filenames, temp_filename, options) if chapters: os.remove(metadata_filename) @@ -546,7 +548,7 @@ def run(self, info): args.extend(['-map', '%u:a:0' % (i)]) if fmt.get('vcodec') != 'none': args.extend(['-map', '%u:v:0' % (i)]) - self._downloader.to_screen('[ffmpeg] Merging formats into "%s"' % filename) + self.to_screen('Merging formats into "%s"' % filename) self.run_ffmpeg_multiple_files(info['__files_to_merge'], temp_filename, args) os.rename(encodeFilename(temp_filename), encodeFilename(filename)) return info['__files_to_merge'], info @@ -579,7 +581,7 @@ def run(self, info): temp_filename = prepend_extension(filename, 'temp') options = ['-c', 'copy', '-map', '0', '-dn', '-aspect', '%f' % stretched_ratio] - self._downloader.to_screen('[ffmpeg] Fixing aspect ratio in "%s"' % filename) + self.to_screen('Fixing aspect ratio in "%s"' % filename) self.run_ffmpeg(filename, temp_filename, options) os.remove(encodeFilename(filename)) @@ -597,7 +599,7 @@ def run(self, info): temp_filename = prepend_extension(filename, 'temp') options = ['-c', 'copy', '-map', '0', '-dn', '-f', 'mp4'] - self._downloader.to_screen('[ffmpeg] Correcting container in "%s"' % filename) + self.to_screen('Correcting container in "%s"' % filename) self.run_ffmpeg(filename, temp_filename, options) os.remove(encodeFilename(filename)) @@ -613,7 +615,7 @@ def run(self, info): temp_filename = prepend_extension(filename, 'temp') options = ['-c', 'copy', '-map', '0', '-dn', '-f', 'mp4', '-bsf:a', 'aac_adtstoasc'] - self._downloader.to_screen('[ffmpeg] Fixing malformed AAC bitstream in "%s"' % filename) + self.to_screen('Fixing malformed AAC bitstream in "%s"' % filename) self.run_ffmpeg(filename, temp_filename, options) os.remove(encodeFilename(filename)) @@ -634,19 +636,18 @@ def run(self, info): if new_format == 'vtt': new_format = 'webvtt' if subs is None: - self._downloader.to_screen('[ffmpeg] There aren\'t any subtitles to convert') + self.to_screen('There aren\'t any subtitles to convert') return [], info - self._downloader.to_screen('[ffmpeg] Converting subtitles') + self.to_screen('Converting subtitles') sub_filenames = [] for lang, sub in subs.items(): ext = sub['ext'] if ext == new_ext: - self._downloader.to_screen( - '[ffmpeg] Subtitle file for %s is already in the requested format' % new_ext) + self.to_screen('Subtitle file for %s is already in the requested format' % new_ext) continue elif ext == 'json': - self._downloader.to_screen( - '[ffmpeg] You have requested to convert json subtitles into another format, ' + self.to_screen( + 'You have requested to convert json subtitles into another format, ' 'which is currently not possible') continue old_file = subtitles_filename(filename, lang, ext, info.get('ext')) @@ -655,7 +656,7 @@ def run(self, info): if ext in ('dfxp', 'ttml', 'tt'): self._downloader.report_warning( - '[ffmpeg] You have requested to convert dfxp (TTML) subtitles into another format, ' + 'You have requested to convert dfxp (TTML) subtitles into another format, ' 'which results in style information loss') dfxp_file = old_file diff --git a/youtube_dlc/postprocessor/metadatafromtitle.py b/youtube_dlc/postprocessor/metadatafromtitle.py index f5c14d974f..86df3b4f06 100644 --- a/youtube_dlc/postprocessor/metadatafromtitle.py +++ b/youtube_dlc/postprocessor/metadatafromtitle.py @@ -35,14 +35,10 @@ def run(self, info): title = info['title'] match = re.match(self._titleregex, title) if match is None: - self._downloader.to_screen( - '[fromtitle] Could not interpret title of video as "%s"' - % self._titleformat) + self.to_screen('Could not interpret title of video as "%s"' % self._titleformat) return [], info for attribute, value in match.groupdict().items(): info[attribute] = value - self._downloader.to_screen( - '[fromtitle] parsed %s: %s' - % (attribute, value if value is not None else 'NA')) + self.to_screen('parsed %s: %s' % (attribute, value if value is not None else 'NA')) return [], info diff --git a/youtube_dlc/postprocessor/sponskrub.py b/youtube_dlc/postprocessor/sponskrub.py index 8ef6120501..37f6c02908 100644 --- a/youtube_dlc/postprocessor/sponskrub.py +++ b/youtube_dlc/postprocessor/sponskrub.py @@ -22,7 +22,7 @@ def __init__(self, downloader, path='', args=None, ignoreerror=False, cut=False, self.force = force self.cutout = cut self.args = ['-chapter'] if not cut else [] - self.args += self._def_args if args is None else compat_shlex_split(args) + self.args += self._configuration_args(self._def_args) if args is None else compat_shlex_split(args) self.path = self.get_exe(path) if not ignoreerror and self.path is None: @@ -43,7 +43,7 @@ def run(self, information): return [], information if information['extractor_key'].lower() != 'youtube': - self._downloader.to_screen('[sponskrub] Skipping sponskrub since it is not a YouTube video') + self.to_screen('Skipping sponskrub since it is not a YouTube video') return [], information if self.cutout and not self.force and not information.get('__real_download', False): self._downloader.to_screen( @@ -51,7 +51,7 @@ def run(self, information): 'Use --sponskrub-force to run sponskrub anyway') return [], information - self._downloader.to_screen('[sponskrub] Trying to %s sponsor sections' % ('remove' if self.cutout else 'mark')) + self.to_screen('Trying to %s sponsor sections' % ('remove' if self.cutout else 'mark')) if self.cutout: self._downloader.to_screen('WARNING: Cutting out sponsor segments will cause the subtitles to go out of sync.') if not information.get('__real_download', False): @@ -76,11 +76,11 @@ def run(self, information): if p.returncode == 0: os.remove(filename) os.rename(temp_filename, filename) - self._downloader.to_screen('[sponskrub] Sponsor sections have been %s' % ('removed' if self.cutout else 'marked')) - elif p.returncode != 3: # error code 3 means there was no info about the video + self.to_screen('Sponsor sections have been %s' % ('removed' if self.cutout else 'marked')) + elif p.returncode == 3: + self.to_screen('No segments in the SponsorBlock database') + else: stderr = stderr.decode('utf-8', 'replace') msg = stderr.strip().split('\n')[-1] raise PostProcessingError(msg if msg else 'sponskrub failed with error code %s!' % p.returncode) - else: - self._downloader.to_screen('[sponskrub] No segments in the SponsorBlock database') return [], information diff --git a/youtube_dlc/postprocessor/xattrpp.py b/youtube_dlc/postprocessor/xattrpp.py index 814dabecf7..85834db45a 100644 --- a/youtube_dlc/postprocessor/xattrpp.py +++ b/youtube_dlc/postprocessor/xattrpp.py @@ -11,7 +11,6 @@ class XAttrMetadataPP(PostProcessor): - # # More info about extended attributes for media: # http://freedesktop.org/wiki/CommonExtendedAttributes/ @@ -27,7 +26,7 @@ def run(self, info): """ Set extended attributes on downloaded file (if xattr support is found). """ # Write the metadata to the file's xattrs - self._downloader.to_screen('[metadata] Writing metadata to file\'s xattrs') + self.to_screen('Writing metadata to file\'s xattrs') filename = info['filepath']