1
0
mirror of https://github.com/ytdl-org/youtube-dl.git synced 2025-02-03 16:49:48 +00:00

do similar stuff as for output template

This commit is contained in:
Matthias Sweertvaegher 2018-12-04 21:20:54 +01:00
parent 0b4a957f28
commit 2e45a51464

View File

@ -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):