mirror of
https://github.com/ytdl-org/youtube-dl.git
synced 2025-02-03 08:39:49 +00:00
do similar stuff as for output template
This commit is contained in:
parent
0b4a957f28
commit
2e45a51464
@ -5,7 +5,23 @@ import os
|
||||
import subprocess
|
||||
import time
|
||||
import re
|
||||
|
||||
import collections
|
||||
from string import ascii_letters
|
||||
import random
|
||||
from ..utils import expand_path
|
||||
# from youtube_dl import YoutubeDL
|
||||
# todo fail to import youtubedl class for _NUMERIC_FIELDS
|
||||
# http://python-notes.curiousefficiency.org/en/latest/python_concepts/import_traps.html
|
||||
_NUMERIC_FIELDS = set((
|
||||
'width', 'height', 'tbr', 'abr', 'asr', 'vbr', 'fps', 'filesize', 'filesize_approx',
|
||||
'timestamp', 'upload_year', 'upload_month', 'upload_day',
|
||||
'duration', 'view_count', 'like_count', 'dislike_count', 'repost_count',
|
||||
'average_rating', 'comment_count', 'age_limit',
|
||||
'start_time', 'end_time',
|
||||
'chapter_number', 'season_number', 'episode_number',
|
||||
'track_number', 'disc_number', 'release_year',
|
||||
'playlist_index',
|
||||
))
|
||||
|
||||
from .common import AudioConversionError, PostProcessor
|
||||
|
||||
@ -181,7 +197,7 @@ class FFmpegPostProcessor(PostProcessor):
|
||||
oldest_mtime = min(
|
||||
os.stat(encodeFilename(path)).st_mtime for path in input_paths)
|
||||
|
||||
opts += map(lambda s: s % info, self._configuration_args())
|
||||
opts += map(lambda s: self._resolve_postprocessor_arg_var(s, info), self._configuration_args())
|
||||
|
||||
files_cmd = []
|
||||
for path in input_paths:
|
||||
@ -214,6 +230,83 @@ class FFmpegPostProcessor(PostProcessor):
|
||||
# Also leave '-' intact in order not to break streaming to stdout.
|
||||
return 'file:' + fn if fn != '-' else fn
|
||||
|
||||
def _resolve_postprocessor_arg_var(self, arg, info):
|
||||
# map(lambda s: s % info, args)
|
||||
if "%(" not in arg:
|
||||
return arg
|
||||
|
||||
template_dict = dict(info)
|
||||
template_dict['epoch'] = int(time.time())
|
||||
# autonumber_size = self.params.get('autonumber_size')
|
||||
# if autonumber_size is None:
|
||||
autonumber_size = 5
|
||||
#
|
||||
# template_dict['autonumber'] = self.params.get('autonumber_start', 1) - 1 + self._num_downloads
|
||||
# if template_dict.get('resolution') is None:
|
||||
# if template_dict.get('width') and template_dict.get('height'):
|
||||
# template_dict['resolution'] = '%dx%d' % (template_dict['width'], template_dict['height'])
|
||||
# elif template_dict.get('height'):
|
||||
# template_dict['resolution'] = '%sp' % template_dict['height']
|
||||
# elif template_dict.get('width'):
|
||||
# template_dict['resolution'] = '%dx?' % template_dict['width']
|
||||
# sanitize = lambda k, v: sanitize_filename(
|
||||
# compat_str(v),
|
||||
# restricted=self.params.get('restrictfilenames'),
|
||||
# is_id=(k == 'id' or k.endswith('_id')))
|
||||
# template_dict = dict((k, v if isinstance(v, compat_numeric_types) else sanitize(k, v))
|
||||
# for k, v in template_dict.items()
|
||||
# if v is not None and not isinstance(v, (list, tuple, dict)))
|
||||
template_dict = collections.defaultdict(lambda: 'NA', template_dict)
|
||||
outtmpl = arg
|
||||
|
||||
# For fields playlist_index and autonumber convert all occurrences
|
||||
# of %(field)s to %(field)0Nd for backward compatibility
|
||||
field_size_compat_map = {
|
||||
'playlist_index': len(str(template_dict['n_entries'])),
|
||||
'autonumber': autonumber_size,
|
||||
}
|
||||
FIELD_SIZE_COMPAT_RE = r'(?<!%)%\((?P<field>autonumber|playlist_index)\)s'
|
||||
mobj = re.search(FIELD_SIZE_COMPAT_RE, outtmpl)
|
||||
if mobj:
|
||||
outtmpl = re.sub(
|
||||
FIELD_SIZE_COMPAT_RE,
|
||||
r'%%(\1)0%dd' % field_size_compat_map[mobj.group('field')],
|
||||
outtmpl)
|
||||
# Missing numeric fields used together with integer presentation types
|
||||
# in format specification will break the argument substitution since
|
||||
# string 'NA' is returned for missing fields. We will patch output
|
||||
# template for missing fields to meet string presentation type.
|
||||
for numeric_field in _NUMERIC_FIELDS:
|
||||
if numeric_field not in template_dict:
|
||||
# As of [1] format syntax is:
|
||||
# %[mapping_key][conversion_flags][minimum_width][.precision][length_modifier]type
|
||||
# 1. https://docs.python.org/2/library/stdtypes.html#string-formatting
|
||||
FORMAT_RE = r'''(?x)
|
||||
(?<!%)
|
||||
%
|
||||
\({0}\) # mapping key
|
||||
(?:[#0\-+ ]+)? # conversion flags (optional)
|
||||
(?:\d+)? # minimum field width (optional)
|
||||
(?:\.\d+)? # precision (optional)
|
||||
[hlL]? # length modifier (optional)
|
||||
[diouxXeEfFgGcrs%] # conversion type
|
||||
'''
|
||||
outtmpl = re.sub(
|
||||
FORMAT_RE.format(numeric_field),
|
||||
r'%({0})s'.format(numeric_field), outtmpl)
|
||||
# expand_path translates '%%' into '%' and '$$' into '$'
|
||||
# correspondingly that is not what we want since we need to keep
|
||||
# '%%' intact for template dict substitution step. Working around
|
||||
# with boundary-alike separator hack.
|
||||
sep = ''.join([random.choice(ascii_letters) for _ in range(32)])
|
||||
outtmpl = outtmpl.replace('%%', '%{0}%'.format(sep)).replace('$$', '${0}$'.format(sep))
|
||||
# outtmpl should be expand_path'ed before template dict substitution
|
||||
# because meta fields may contain env variables we don't want to
|
||||
# be expanded. For example, for outtmpl "%(title)s.%(ext)s" and
|
||||
# title "Hello $PATH", we don't want `$PATH` to be expanded.
|
||||
# todo need encoding & sanitize_path ?
|
||||
return expand_path(outtmpl).replace(sep, '') % template_dict
|
||||
|
||||
|
||||
class FFmpegExtractAudioPP(FFmpegPostProcessor):
|
||||
def __init__(self, downloader=None, preferredcodec=None, preferredquality=None, nopostoverwrites=False):
|
||||
|
Loading…
Reference in New Issue
Block a user