[YoutubeDL] format spec: Fix handling of '+' with '/'
'bestvideo+bestaudio/best' was incorrectly interpreted as 'bestvideo+(bestaudio/best)', so it would fail if 'bestaudio' doesn't exist instead of falling back to 'best'.
This commit is contained in:
parent
0130afb76e
commit
cf2ac6df68
2 changed files with 23 additions and 10 deletions
|
@ -245,6 +245,14 @@ class TestFormatSelection(unittest.TestCase):
|
||||||
self.assertEqual(downloaded['format_id'], '137+141')
|
self.assertEqual(downloaded['format_id'], '137+141')
|
||||||
self.assertEqual(downloaded['ext'], 'mp4')
|
self.assertEqual(downloaded['ext'], 'mp4')
|
||||||
|
|
||||||
|
info_dict = _make_result(list(formats_order), extractor='youtube')
|
||||||
|
ydl = YDL({'format': 'bestvideo[height>=999999]+bestaudio/best'})
|
||||||
|
yie = YoutubeIE(ydl)
|
||||||
|
yie._sort_formats(info_dict['formats'])
|
||||||
|
ydl.process_ie_result(info_dict)
|
||||||
|
downloaded = ydl.downloaded_info_dicts[0]
|
||||||
|
self.assertEqual(downloaded['format_id'], '38')
|
||||||
|
|
||||||
info_dict = _make_result(list(formats_order), extractor='youtube')
|
info_dict = _make_result(list(formats_order), extractor='youtube')
|
||||||
ydl = YDL({'format': '(bestvideo[ext=mp4],bestvideo[ext=webm])+bestaudio'})
|
ydl = YDL({'format': '(bestvideo[ext=mp4],bestvideo[ext=webm])+bestaudio'})
|
||||||
yie = YoutubeIE(ydl)
|
yie = YoutubeIE(ydl)
|
||||||
|
|
|
@ -931,7 +931,7 @@ class YoutubeDL(object):
|
||||||
else:
|
else:
|
||||||
filter_parts.append(string)
|
filter_parts.append(string)
|
||||||
|
|
||||||
def _parse_format_selection(tokens, endwith=[]):
|
def _parse_format_selection(tokens, inside_merge=False, inside_choice=False, inside_group=False):
|
||||||
selectors = []
|
selectors = []
|
||||||
current_selector = None
|
current_selector = None
|
||||||
for type, string, start, _, _ in tokens:
|
for type, string, start, _, _ in tokens:
|
||||||
|
@ -941,18 +941,23 @@ class YoutubeDL(object):
|
||||||
elif type in [tokenize.NAME, tokenize.NUMBER]:
|
elif type in [tokenize.NAME, tokenize.NUMBER]:
|
||||||
current_selector = FormatSelector(SINGLE, string, [])
|
current_selector = FormatSelector(SINGLE, string, [])
|
||||||
elif type == tokenize.OP:
|
elif type == tokenize.OP:
|
||||||
if string in endwith:
|
if string == ')':
|
||||||
|
if not inside_group:
|
||||||
|
# ')' will be handled by the parentheses group
|
||||||
|
tokens.restore_last_token()
|
||||||
break
|
break
|
||||||
elif string == ')':
|
elif inside_merge and string in ['/', ',']:
|
||||||
# ')' will be handled by the parentheses group
|
|
||||||
tokens.restore_last_token()
|
tokens.restore_last_token()
|
||||||
break
|
break
|
||||||
if string == ',':
|
elif inside_choice and string == ',':
|
||||||
|
tokens.restore_last_token()
|
||||||
|
break
|
||||||
|
elif string == ',':
|
||||||
selectors.append(current_selector)
|
selectors.append(current_selector)
|
||||||
current_selector = None
|
current_selector = None
|
||||||
elif string == '/':
|
elif string == '/':
|
||||||
first_choice = current_selector
|
first_choice = current_selector
|
||||||
second_choice = _parse_format_selection(tokens, [','])
|
second_choice = _parse_format_selection(tokens, inside_choice=True)
|
||||||
current_selector = None
|
current_selector = None
|
||||||
selectors.append(FormatSelector(PICKFIRST, (first_choice, second_choice), []))
|
selectors.append(FormatSelector(PICKFIRST, (first_choice, second_choice), []))
|
||||||
elif string == '[':
|
elif string == '[':
|
||||||
|
@ -963,12 +968,12 @@ class YoutubeDL(object):
|
||||||
elif string == '(':
|
elif string == '(':
|
||||||
if current_selector:
|
if current_selector:
|
||||||
raise syntax_error('Unexpected "("', start)
|
raise syntax_error('Unexpected "("', start)
|
||||||
current_selector = FormatSelector(GROUP, _parse_format_selection(tokens, [')']), [])
|
group = _parse_format_selection(tokens, inside_group=True)
|
||||||
|
current_selector = FormatSelector(GROUP, group, [])
|
||||||
elif string == '+':
|
elif string == '+':
|
||||||
video_selector = current_selector
|
video_selector = current_selector
|
||||||
audio_selector = _parse_format_selection(tokens, [','])
|
audio_selector = _parse_format_selection(tokens, inside_merge=True)
|
||||||
current_selector = None
|
current_selector = FormatSelector(MERGE, (video_selector, audio_selector), [])
|
||||||
selectors.append(FormatSelector(MERGE, (video_selector, audio_selector), []))
|
|
||||||
else:
|
else:
|
||||||
raise syntax_error('Operator not recognized: "{0}"'.format(string), start)
|
raise syntax_error('Operator not recognized: "{0}"'.format(string), start)
|
||||||
elif type == tokenize.ENDMARKER:
|
elif type == tokenize.ENDMARKER:
|
||||||
|
|
Loading…
Reference in a new issue