aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpukkandan <pukkandan.ytdlp@gmail.com>2021-11-06 06:35:24 +0530
committerpukkandan <pukkandan.ytdlp@gmail.com>2021-11-06 07:53:55 +0530
commit34921b43451a23d8cd7350f8511269bdfd35cf61 (patch)
tree4cc0f567f0b159299b41de0b2b372e066936be3f
parenta331949df396d69e648fad61a80ada5da3279704 (diff)
downloadhypervideo-pre-34921b43451a23d8cd7350f8511269bdfd35cf61.tar.lz
hypervideo-pre-34921b43451a23d8cd7350f8511269bdfd35cf61.tar.xz
hypervideo-pre-34921b43451a23d8cd7350f8511269bdfd35cf61.zip
[utils] Add `join_nonempty`
-rw-r--r--yt_dlp/YoutubeDL.py9
-rw-r--r--yt_dlp/extractor/adobetv.py3
-rw-r--r--yt_dlp/extractor/animeondemand.py22
-rw-r--r--yt_dlp/extractor/anvato.py7
-rw-r--r--yt_dlp/extractor/common.py22
-rw-r--r--yt_dlp/extractor/disney.py9
-rw-r--r--yt_dlp/extractor/dvtv.py7
-rw-r--r--yt_dlp/extractor/funimation.py8
-rw-r--r--yt_dlp/extractor/lego.py7
-rw-r--r--yt_dlp/extractor/mdr.py12
-rw-r--r--yt_dlp/extractor/mtv.py5
-rw-r--r--yt_dlp/extractor/orf.py8
-rw-r--r--yt_dlp/extractor/piksel.py8
-rw-r--r--yt_dlp/extractor/srgssr.py7
-rw-r--r--yt_dlp/extractor/threeqsdn.py13
-rw-r--r--yt_dlp/extractor/tiktok.py5
-rw-r--r--yt_dlp/extractor/tonline.py9
-rw-r--r--yt_dlp/extractor/ustream.py5
-rw-r--r--yt_dlp/extractor/vrv.py13
-rw-r--r--yt_dlp/extractor/webcaster.py8
-rw-r--r--yt_dlp/extractor/youtube.py5
-rw-r--r--yt_dlp/extractor/zattoo.py9
-rw-r--r--yt_dlp/extractor/zdf.py6
-rw-r--r--yt_dlp/utils.py6
24 files changed, 82 insertions, 131 deletions
diff --git a/yt_dlp/YoutubeDL.py b/yt_dlp/YoutubeDL.py
index 872bd5e11..0fbb3baa7 100644
--- a/yt_dlp/YoutubeDL.py
+++ b/yt_dlp/YoutubeDL.py
@@ -74,6 +74,7 @@ from .utils import (
int_or_none,
iri_to_uri,
ISO3166Utils,
+ join_nonempty,
LazyList,
LINK_TEMPLATES,
locked_file,
@@ -1169,7 +1170,7 @@ class YoutubeDL(object):
sub_ext = ''
if len(fn_groups) > 2:
sub_ext = fn_groups[-2]
- filename = '.'.join(filter(None, [fn_groups[0][:trim_file_name], sub_ext, ext]))
+ filename = join_nonempty(fn_groups[0][:trim_file_name], sub_ext, ext, delim='.')
return filename
except ValueError as err:
@@ -3221,12 +3222,12 @@ class YoutubeDL(object):
format_field(f, 'acodec', default='unknown').replace('none', ''),
format_field(f, 'abr', f'%{abr_digits}dk'),
format_field(f, 'asr', '%5dHz'),
- ', '.join(filter(None, (
- self._format_screen('UNSUPPORTED', 'light red') if f.get('ext') in ('f4f', 'f4m') else '',
+ join_nonempty(
+ self._format_screen('UNSUPPORTED', 'light red') if f.get('ext') in ('f4f', 'f4m') else None,
format_field(f, 'language', '[%s]'),
format_field(f, 'format_note'),
format_field(f, 'container', ignore=(None, f.get('ext'))),
- ))),
+ delim=', '),
] for f in formats if f.get('preference') is None or f['preference'] >= -1000]
header_line = self._list_format_headers(
'ID', 'EXT', 'RESOLUTION', 'FPS', 'HDR', delim, ' FILESIZE', ' TBR', 'PROTO',
diff --git a/yt_dlp/extractor/adobetv.py b/yt_dlp/extractor/adobetv.py
index 12b819206..3cfa1ff55 100644
--- a/yt_dlp/extractor/adobetv.py
+++ b/yt_dlp/extractor/adobetv.py
@@ -9,6 +9,7 @@ from ..utils import (
float_or_none,
int_or_none,
ISO639Utils,
+ join_nonempty,
OnDemandPagedList,
parse_duration,
str_or_none,
@@ -263,7 +264,7 @@ class AdobeTVVideoIE(AdobeTVBaseIE):
continue
formats.append({
'filesize': int_or_none(source.get('kilobytes') or None, invscale=1000),
- 'format_id': '-'.join(filter(None, [source.get('format'), source.get('label')])),
+ 'format_id': join_nonempty(source.get('format'), source.get('label')),
'height': int_or_none(source.get('height') or None),
'tbr': int_or_none(source.get('bitrate') or None),
'width': int_or_none(source.get('width') or None),
diff --git a/yt_dlp/extractor/animeondemand.py b/yt_dlp/extractor/animeondemand.py
index 54e097d2f..5694f7240 100644
--- a/yt_dlp/extractor/animeondemand.py
+++ b/yt_dlp/extractor/animeondemand.py
@@ -8,6 +8,7 @@ from ..utils import (
determine_ext,
extract_attributes,
ExtractorError,
+ join_nonempty,
url_or_none,
urlencode_postdata,
urljoin,
@@ -140,15 +141,8 @@ class AnimeOnDemandIE(InfoExtractor):
kind = self._search_regex(
r'videomaterialurl/\d+/([^/]+)/',
playlist_url, 'media kind', default=None)
- format_id_list = []
- if lang:
- format_id_list.append(lang)
- if kind:
- format_id_list.append(kind)
- if not format_id_list and num is not None:
- format_id_list.append(compat_str(num))
- format_id = '-'.join(format_id_list)
- format_note = ', '.join(filter(None, (kind, lang_note)))
+ format_id = join_nonempty(lang, kind) if lang or kind else str(num)
+ format_note = join_nonempty(kind, lang_note, delim=', ')
item_id_list = []
if format_id:
item_id_list.append(format_id)
@@ -195,12 +189,10 @@ class AnimeOnDemandIE(InfoExtractor):
if not file_:
continue
ext = determine_ext(file_)
- format_id_list = [lang, kind]
- if ext == 'm3u8':
- format_id_list.append('hls')
- elif source.get('type') == 'video/dash' or ext == 'mpd':
- format_id_list.append('dash')
- format_id = '-'.join(filter(None, format_id_list))
+ format_id = join_nonempty(
+ lang, kind,
+ 'hls' if ext == 'm3u8' else None,
+ 'dash' if source.get('type') == 'video/dash' or ext == 'mpd' else None)
if ext == 'm3u8':
file_formats = self._extract_m3u8_formats(
file_, video_id, 'mp4',
diff --git a/yt_dlp/extractor/anvato.py b/yt_dlp/extractor/anvato.py
index d688e2c5b..0d444fc33 100644
--- a/yt_dlp/extractor/anvato.py
+++ b/yt_dlp/extractor/anvato.py
@@ -16,6 +16,7 @@ from ..utils import (
determine_ext,
intlist_to_bytes,
int_or_none,
+ join_nonempty,
strip_jsonp,
unescapeHTML,
unsmuggle_url,
@@ -303,13 +304,13 @@ class AnvatoIE(InfoExtractor):
tbr = int_or_none(published_url.get('kbps'))
a_format = {
'url': video_url,
- 'format_id': ('-'.join(filter(None, ['http', published_url.get('cdn_name')]))).lower(),
- 'tbr': tbr if tbr != 0 else None,
+ 'format_id': join_nonempty('http', published_url.get('cdn_name')).lower(),
+ 'tbr': tbr or None,
}
if media_format == 'm3u8' and tbr is not None:
a_format.update({
- 'format_id': '-'.join(filter(None, ['hls', compat_str(tbr)])),
+ 'format_id': join_nonempty('hls', tbr),
'ext': 'mp4',
})
elif media_format == 'm3u8-variant' or ext == 'm3u8':
diff --git a/yt_dlp/extractor/common.py b/yt_dlp/extractor/common.py
index ffecc4263..7500402fa 100644
--- a/yt_dlp/extractor/common.py
+++ b/yt_dlp/extractor/common.py
@@ -54,6 +54,7 @@ from ..utils import (
GeoRestrictedError,
GeoUtils,
int_or_none,
+ join_nonempty,
js_to_json,
JSON_LD_RE,
mimetype2ext,
@@ -1911,7 +1912,7 @@ class InfoExtractor(object):
tbr = int_or_none(media_el.attrib.get('bitrate'))
width = int_or_none(media_el.attrib.get('width'))
height = int_or_none(media_el.attrib.get('height'))
- format_id = '-'.join(filter(None, [f4m_id, compat_str(i if tbr is None else tbr)]))
+ format_id = join_nonempty(f4m_id, tbr or i)
# If <bootstrapInfo> is present, the specified f4m is a
# stream-level manifest, and only set-level manifests may refer to
# external resources. See section 11.4 and section 4 of F4M spec
@@ -1973,7 +1974,7 @@ class InfoExtractor(object):
def _m3u8_meta_format(self, m3u8_url, ext=None, preference=None, quality=None, m3u8_id=None):
return {
- 'format_id': '-'.join(filter(None, [m3u8_id, 'meta'])),
+ 'format_id': join_nonempty(m3u8_id, 'meta'),
'url': m3u8_url,
'ext': ext,
'protocol': 'm3u8',
@@ -2068,7 +2069,7 @@ class InfoExtractor(object):
if '#EXT-X-TARGETDURATION' in m3u8_doc: # media playlist, return as is
formats = [{
- 'format_id': '-'.join(map(str, filter(None, [m3u8_id, idx]))),
+ 'format_id': join_nonempty(m3u8_id, idx),
'format_index': idx,
'url': m3u8_url,
'ext': ext,
@@ -2117,7 +2118,7 @@ class InfoExtractor(object):
if media_url:
manifest_url = format_url(media_url)
formats.extend({
- 'format_id': '-'.join(map(str, filter(None, (m3u8_id, group_id, name, idx)))),
+ 'format_id': join_nonempty(m3u8_id, group_id, name, idx),
'format_note': name,
'format_index': idx,
'url': manifest_url,
@@ -2174,9 +2175,9 @@ class InfoExtractor(object):
# format_id intact.
if not live:
stream_name = build_stream_name()
- format_id[1] = stream_name if stream_name else '%d' % (tbr if tbr else len(formats))
+ format_id[1] = stream_name or '%d' % (tbr or len(formats))
f = {
- 'format_id': '-'.join(map(str, filter(None, format_id))),
+ 'format_id': join_nonempty(*format_id),
'format_index': idx,
'url': manifest_url,
'manifest_url': m3u8_url,
@@ -2965,13 +2966,6 @@ class InfoExtractor(object):
})
fragment_ctx['time'] += fragment_ctx['duration']
- format_id = []
- if ism_id:
- format_id.append(ism_id)
- if stream_name:
- format_id.append(stream_name)
- format_id.append(compat_str(tbr))
-
if stream_type == 'text':
subtitles.setdefault(stream_language, []).append({
'ext': 'ismt',
@@ -2990,7 +2984,7 @@ class InfoExtractor(object):
})
elif stream_type in ('video', 'audio'):
formats.append({
- 'format_id': '-'.join(format_id),
+ 'format_id': join_nonempty(ism_id, stream_name, tbr),
'url': ism_url,
'manifest_url': ism_url,
'ext': 'ismv' if stream_type == 'video' else 'isma',
diff --git a/yt_dlp/extractor/disney.py b/yt_dlp/extractor/disney.py
index f018cbe9d..0ad7b1f46 100644
--- a/yt_dlp/extractor/disney.py
+++ b/yt_dlp/extractor/disney.py
@@ -7,8 +7,8 @@ from .common import InfoExtractor
from ..utils import (
int_or_none,
unified_strdate,
- compat_str,
determine_ext,
+ join_nonempty,
update_url_query,
)
@@ -119,18 +119,13 @@ class DisneyIE(InfoExtractor):
continue
formats.append(f)
continue
- format_id = []
- if flavor_format:
- format_id.append(flavor_format)
- if tbr:
- format_id.append(compat_str(tbr))
ext = determine_ext(flavor_url)
if flavor_format == 'applehttp' or ext == 'm3u8':
ext = 'mp4'
width = int_or_none(flavor.get('width'))
height = int_or_none(flavor.get('height'))
formats.append({
- 'format_id': '-'.join(format_id),
+ 'format_id': join_nonempty(flavor_format, tbr),
'url': flavor_url,
'width': width,
'height': height,
diff --git a/yt_dlp/extractor/dvtv.py b/yt_dlp/extractor/dvtv.py
index de7f6d670..08663cffb 100644
--- a/yt_dlp/extractor/dvtv.py
+++ b/yt_dlp/extractor/dvtv.py
@@ -8,6 +8,7 @@ from ..utils import (
determine_ext,
ExtractorError,
int_or_none,
+ join_nonempty,
js_to_json,
mimetype2ext,
try_get,
@@ -139,13 +140,9 @@ class DVTVIE(InfoExtractor):
label = video.get('label')
height = self._search_regex(
r'^(\d+)[pP]', label or '', 'height', default=None)
- format_id = ['http']
- for f in (ext, label):
- if f:
- format_id.append(f)
formats.append({
'url': video_url,
- 'format_id': '-'.join(format_id),
+ 'format_id': join_nonempty('http', ext, label),
'height': int_or_none(height),
})
self._sort_formats(formats)
diff --git a/yt_dlp/extractor/funimation.py b/yt_dlp/extractor/funimation.py
index 382cbe159..42711083e 100644
--- a/yt_dlp/extractor/funimation.py
+++ b/yt_dlp/extractor/funimation.py
@@ -10,6 +10,7 @@ from ..compat import compat_HTTPError
from ..utils import (
determine_ext,
int_or_none,
+ join_nonempty,
js_to_json,
orderedSet,
qualities,
@@ -288,10 +289,11 @@ class FunimationIE(FunimationBaseIE):
sub_type = sub_type if sub_type != 'FULL' else None
current_sub = {
'url': text_track['src'],
- 'name': ' '.join(filter(None, (version, text_track.get('label'), sub_type)))
+ 'name': join_nonempty(version, text_track.get('label'), sub_type, delim=' ')
}
- lang = '_'.join(filter(None, (
- text_track.get('language', 'und'), version if version != 'Simulcast' else None, sub_type)))
+ lang = join_nonempty(text_track.get('language', 'und'),
+ version if version != 'Simulcast' else None,
+ sub_type, delim='_')
if current_sub not in subtitles.get(lang, []):
subtitles.setdefault(lang, []).append(current_sub)
return subtitles
diff --git a/yt_dlp/extractor/lego.py b/yt_dlp/extractor/lego.py
index b9d8b167c..901f43bcf 100644
--- a/yt_dlp/extractor/lego.py
+++ b/yt_dlp/extractor/lego.py
@@ -8,6 +8,7 @@ from ..compat import compat_HTTPError
from ..utils import (
ExtractorError,
int_or_none,
+ join_nonempty,
qualities,
)
@@ -102,12 +103,8 @@ class LEGOIE(InfoExtractor):
m3u8_id=video_source_format, fatal=False))
else:
video_source_quality = video_source.get('Quality')
- format_id = []
- for v in (video_source_format, video_source_quality):
- if v:
- format_id.append(v)
f = {
- 'format_id': '-'.join(format_id),
+ 'format_id': join_nonempty(video_source_format, video_source_quality),
'quality': q(video_source_quality),
'url': video_source_url,
}
diff --git a/yt_dlp/extractor/mdr.py b/yt_dlp/extractor/mdr.py
index 0bdd62693..3ca174c2b 100644
--- a/yt_dlp/extractor/mdr.py
+++ b/yt_dlp/extractor/mdr.py
@@ -2,13 +2,11 @@
from __future__ import unicode_literals
from .common import InfoExtractor
-from ..compat import (
- compat_str,
- compat_urlparse,
-)
+from ..compat import compat_urlparse
from ..utils import (
determine_ext,
int_or_none,
+ join_nonempty,
parse_duration,
parse_iso8601,
url_or_none,
@@ -148,13 +146,9 @@ class MDRIE(InfoExtractor):
abr = int_or_none(xpath_text(asset, './bitrateAudio', 'abr'), 1000)
filesize = int_or_none(xpath_text(asset, './fileSize', 'file size'))
- format_id = [media_type]
- if vbr or abr:
- format_id.append(compat_str(vbr or abr))
-
f = {
'url': video_url,
- 'format_id': '-'.join(format_id),
+ 'format_id': join_nonempty(media_type, vbr or abr),
'filesize': filesize,
'abr': abr,
'vbr': vbr,
diff --git a/yt_dlp/extractor/mtv.py b/yt_dlp/extractor/mtv.py
index 141dd7deb..4812f11cc 100644
--- a/yt_dlp/extractor/mtv.py
+++ b/yt_dlp/extractor/mtv.py
@@ -15,6 +15,7 @@ from ..utils import (
float_or_none,
HEADRequest,
int_or_none,
+ join_nonempty,
RegexNotFoundError,
sanitized_Request,
strip_or_none,
@@ -99,9 +100,9 @@ class MTVServicesInfoExtractor(InfoExtractor):
formats.extend([{
'ext': 'flv' if rtmp_video_url.startswith('rtmp') else ext,
'url': rtmp_video_url,
- 'format_id': '-'.join(filter(None, [
+ 'format_id': join_nonempty(
'rtmp' if rtmp_video_url.startswith('rtmp') else None,
- rendition.get('bitrate')])),
+ rendition.get('bitrate')),
'width': int(rendition.get('width')),
'height': int(rendition.get('height')),
}])
diff --git a/yt_dlp/extractor/orf.py b/yt_dlp/extractor/orf.py
index 428ec97e4..e2b703880 100644
--- a/yt_dlp/extractor/orf.py
+++ b/yt_dlp/extractor/orf.py
@@ -11,6 +11,7 @@ from ..utils import (
float_or_none,
HEADRequest,
int_or_none,
+ join_nonempty,
orderedSet,
remove_end,
str_or_none,
@@ -82,12 +83,7 @@ class ORFTVthekIE(InfoExtractor):
src = url_or_none(fd.get('src'))
if not src:
continue
- format_id_list = []
- for key in ('delivery', 'quality', 'quality_string'):
- value = fd.get(key)
- if value:
- format_id_list.append(value)
- format_id = '-'.join(format_id_list)
+ format_id = join_nonempty('delivery', 'quality', 'quality_string', from_dict=fd)
ext = determine_ext(src)
if ext == 'm3u8':
m3u8_formats = self._extract_m3u8_formats(
diff --git a/yt_dlp/extractor/piksel.py b/yt_dlp/extractor/piksel.py
index 5cc99a44e..84c3de2f0 100644
--- a/yt_dlp/extractor/piksel.py
+++ b/yt_dlp/extractor/piksel.py
@@ -4,11 +4,11 @@ from __future__ import unicode_literals
import re
from .common import InfoExtractor
-from ..compat import compat_str
from ..utils import (
dict_get,
ExtractorError,
int_or_none,
+ join_nonempty,
parse_iso8601,
try_get,
unescapeHTML,
@@ -116,12 +116,8 @@ class PikselIE(InfoExtractor):
elif asset_type == 'audio':
tbr = abr
- format_id = ['http']
- if tbr:
- format_id.append(compat_str(tbr))
-
formats.append({
- 'format_id': '-'.join(format_id),
+ 'format_id': join_nonempty('http', tbr),
'url': unescapeHTML(http_url),
'vbr': vbr,
'abr': abr,
diff --git a/yt_dlp/extractor/srgssr.py b/yt_dlp/extractor/srgssr.py
index cbc1c47d2..f9919816d 100644
--- a/yt_dlp/extractor/srgssr.py
+++ b/yt_dlp/extractor/srgssr.py
@@ -7,6 +7,7 @@ from ..utils import (
ExtractorError,
float_or_none,
int_or_none,
+ join_nonempty,
parse_iso8601,
qualities,
try_get,
@@ -94,11 +95,7 @@ class SRGSSRIE(InfoExtractor):
continue
protocol = source.get('protocol')
quality = source.get('quality')
- format_id = []
- for e in (protocol, source.get('encoding'), quality):
- if e:
- format_id.append(e)
- format_id = '-'.join(format_id)
+ format_id = join_nonempty(protocol, source.get('encoding'), quality)
if protocol in ('HDS', 'HLS'):
if source.get('tokenType') == 'AKAMAI':
diff --git a/yt_dlp/extractor/threeqsdn.py b/yt_dlp/extractor/threeqsdn.py
index bb7610352..e5c6a6de1 100644
--- a/yt_dlp/extractor/threeqsdn.py
+++ b/yt_dlp/extractor/threeqsdn.py
@@ -9,6 +9,7 @@ from ..utils import (
ExtractorError,
float_or_none,
int_or_none,
+ join_nonempty,
parse_iso8601,
)
@@ -119,24 +120,16 @@ class ThreeQSDNIE(InfoExtractor):
src = s.get('src')
if not (src and self._is_valid_url(src, video_id)):
continue
- width = None
- format_id = ['http']
ext = determine_ext(src)
- if ext:
- format_id.append(ext)
height = int_or_none(s.get('height'))
- if height:
- format_id.append('%dp' % height)
- if aspect:
- width = int(height * aspect)
formats.append({
'ext': ext,
- 'format_id': '-'.join(format_id),
+ 'format_id': join_nonempty('http', ext, height and '%dp' % height),
'height': height,
'source_preference': 0,
'url': src,
'vcodec': 'none' if height == 0 else None,
- 'width': width,
+ 'width': int(height * aspect) if height and aspect else None,
})
# It seems like this would be correctly handled by default
# However, unless someone can confirm this, the old
diff --git a/yt_dlp/extractor/tiktok.py b/yt_dlp/extractor/tiktok.py
index 859951637..8ec28f053 100644
--- a/yt_dlp/extractor/tiktok.py
+++ b/yt_dlp/extractor/tiktok.py
@@ -12,6 +12,7 @@ from ..compat import compat_urllib_parse_unquote
from ..utils import (
ExtractorError,
int_or_none,
+ join_nonempty,
str_or_none,
traverse_obj,
try_get,
@@ -107,8 +108,8 @@ class TikTokBaseIE(InfoExtractor):
'acodec': 'aac',
'source_preference': -2 if 'aweme/v1' in url else -1, # Downloads from API might get blocked
**add_meta, **parsed_meta,
- 'format_note': ' '.join(filter(None, (
- add_meta.get('format_note'), '(API)' if 'aweme/v1' in url else '')))
+ 'format_note': join_nonempty(
+ add_meta.get('format_note'), '(API)' if 'aweme/v1' in url else None, delim=' ')
} for url in addr.get('url_list') or []]
# Hack: Add direct video links first to prioritize them when removing duplicate formats
diff --git a/yt_dlp/extractor/tonline.py b/yt_dlp/extractor/tonline.py
index cc11eae2a..9b6a40db5 100644
--- a/yt_dlp/extractor/tonline.py
+++ b/yt_dlp/extractor/tonline.py
@@ -2,7 +2,7 @@
from __future__ import unicode_literals
from .common import InfoExtractor
-from ..utils import int_or_none
+from ..utils import int_or_none, join_nonempty
class TOnlineIE(InfoExtractor):
@@ -30,13 +30,8 @@ class TOnlineIE(InfoExtractor):
asset_source = asset.get('source') or asset.get('source2')
if not asset_source:
continue
- formats_id = []
- for field_key in ('type', 'profile'):
- field_value = asset.get(field_key)
- if field_value:
- formats_id.append(field_value)
formats.append({
- 'format_id': '-'.join(formats_id),
+ 'format_id': join_nonempty('type', 'profile', from_dict=asset),
'url': asset_source,
})
diff --git a/yt_dlp/extractor/ustream.py b/yt_dlp/extractor/ustream.py
index 8b758795f..4a7a8f879 100644
--- a/yt_dlp/extractor/ustream.py
+++ b/yt_dlp/extractor/ustream.py
@@ -13,6 +13,7 @@ from ..utils import (
ExtractorError,
int_or_none,
float_or_none,
+ join_nonempty,
mimetype2ext,
str_or_none,
)
@@ -139,8 +140,8 @@ class UstreamIE(InfoExtractor):
content_type = stream['contentType']
kind = content_type.split('/')[0]
f = {
- 'format_id': '-'.join(filter(None, [
- 'dash', kind, str_or_none(stream.get('bitrate'))])),
+ 'format_id': join_nonempty(
+ 'dash', kind, str_or_none(stream.get('bitrate'))),
'protocol': 'http_dash_segments',
# TODO: generate a MPD doc for external players?
'url': encode_data_uri(b'<MPD/>', 'text/xml'),
diff --git a/yt_dlp/extractor/vrv.py b/yt_dlp/extractor/vrv.py
index 419602148..7bc55f333 100644
--- a/yt_dlp/extractor/vrv.py
+++ b/yt_dlp/extractor/vrv.py
@@ -19,6 +19,7 @@ from ..utils import (
ExtractorError,
float_or_none,
int_or_none,
+ join_nonempty,
traverse_obj,
)
@@ -141,14 +142,10 @@ class VRVIE(VRVBaseIE):
def _extract_vrv_formats(self, url, video_id, stream_format, audio_lang, hardsub_lang):
if not url or stream_format not in ('hls', 'dash', 'adaptive_hls'):
return []
- stream_id_list = []
- if audio_lang:
- stream_id_list.append('audio-%s' % audio_lang)
- if hardsub_lang:
- stream_id_list.append('hardsub-%s' % hardsub_lang)
- format_id = stream_format
- if stream_id_list:
- format_id += '-' + '-'.join(stream_id_list)
+ format_id = join_nonempty(
+ stream_format,
+ audio_lang and 'audio-%s' % audio_lang,
+ hardsub_lang and 'hardsub-%s' % hardsub_lang)
if 'hls' in stream_format:
adaptive_formats = self._extract_m3u8_formats(
url, video_id, 'mp4', m3u8_id=format_id,
diff --git a/yt_dlp/extractor/webcaster.py b/yt_dlp/extractor/webcaster.py
index e4b65f54f..a858e992c 100644
--- a/yt_dlp/extractor/webcaster.py
+++ b/yt_dlp/extractor/webcaster.py
@@ -6,6 +6,7 @@ import re
from .common import InfoExtractor
from ..utils import (
determine_ext,
+ join_nonempty,
xpath_text,
)
@@ -34,12 +35,9 @@ class WebcasterIE(InfoExtractor):
title = xpath_text(video, './/event_name', 'event name', fatal=True)
- def make_id(parts, separator):
- return separator.join(filter(None, parts))
-
formats = []
for format_id in (None, 'noise'):
- track_tag = make_id(('track', format_id), '_')
+ track_tag = join_nonempty('track', format_id, delim='_')
for track in video.findall('.//iphone/%s' % track_tag):
track_url = track.text
if not track_url:
@@ -48,7 +46,7 @@ class WebcasterIE(InfoExtractor):
m3u8_formats = self._extract_m3u8_formats(
track_url, video_id, 'mp4',
entry_protocol='m3u8_native',
- m3u8_id=make_id(('hls', format_id), '-'), fatal=False)
+ m3u8_id=join_nonempty('hls', format_id, delim='-'), fatal=False)
for f in m3u8_formats:
f.update({
'source_preference': 0 if format_id == 'noise' else 1,
diff --git a/yt_dlp/extractor/youtube.py b/yt_dlp/extractor/youtube.py
index 28bb2fbdf..11dba5598 100644
--- a/yt_dlp/extractor/youtube.py
+++ b/yt_dlp/extractor/youtube.py
@@ -39,6 +39,7 @@ from ..utils import (
int_or_none,
intlist_to_bytes,
is_html,
+ join_nonempty,
mimetype2ext,
network_exceptions,
orderedSet,
@@ -2507,11 +2508,11 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
'asr': int_or_none(fmt.get('audioSampleRate')),
'filesize': int_or_none(fmt.get('contentLength')),
'format_id': itag,
- 'format_note': ', '.join(filter(None, (
+ 'format_note': join_nonempty(
'%s%s' % (audio_track.get('displayName') or '',
' (default)' if audio_track.get('audioIsDefault') else ''),
fmt.get('qualityLabel') or quality.replace('audio_quality_', ''),
- throttled and 'THROTTLED'))),
+ throttled and 'THROTTLED', delim=', '),
'source_preference': -10 if throttled else -1,
'fps': int_or_none(fmt.get('fps')) or None,
'height': height,
diff --git a/yt_dlp/extractor/zattoo.py b/yt_dlp/extractor/zattoo.py
index a13d12436..98d15604d 100644
--- a/yt_dlp/extractor/zattoo.py
+++ b/yt_dlp/extractor/zattoo.py
@@ -12,6 +12,7 @@ from ..compat import (
from ..utils import (
ExtractorError,
int_or_none,
+ join_nonempty,
try_get,
url_or_none,
urlencode_postdata,
@@ -156,15 +157,9 @@ class ZattooPlatformBaseIE(InfoExtractor):
watch_url = url_or_none(watch.get('url'))
if not watch_url:
continue
- format_id_list = [stream_type]
- maxrate = watch.get('maxrate')
- if maxrate:
- format_id_list.append(compat_str(maxrate))
audio_channel = watch.get('audio_channel')
- if audio_channel:
- format_id_list.append(compat_str(audio_channel))
preference = 1 if audio_channel == 'A' else None
- format_id = '-'.join(format_id_list)
+ format_id = join_nonempty(stream_type, watch.get('maxrate'), audio_channel)
if stream_type in ('dash', 'dash_widevine', 'dash_playready'):
this_formats = self._extract_mpd_formats(
watch_url, video_id, mpd_id=format_id, fatal=False)
diff --git a/yt_dlp/extractor/zdf.py b/yt_dlp/extractor/zdf.py
index 8c279c5ab..df236c050 100644
--- a/yt_dlp/extractor/zdf.py
+++ b/yt_dlp/extractor/zdf.py
@@ -9,12 +9,12 @@ from ..utils import (
determine_ext,
float_or_none,
int_or_none,
+ join_nonempty,
merge_dicts,
NO_DEFAULT,
orderedSet,
parse_codecs,
qualities,
- str_or_none,
try_get,
unified_timestamp,
update_url_query,
@@ -70,11 +70,11 @@ class ZDFBaseIE(InfoExtractor):
f = {'vcodec': data[0], 'acodec': data[1]}
f.update({
'url': format_url,
- 'format_id': '-'.join(filter(str_or_none, ('http', meta.get('type'), meta.get('quality')))),
+ 'format_id': join_nonempty('http', meta.get('type'), meta.get('quality')),
})
new_formats = [f]
formats.extend(merge_dicts(f, {
- 'format_note': ', '.join(filter(None, (meta.get('quality'), meta.get('class')))),
+ 'format_note': join_nonempty('quality', 'class', from_dict=meta, delim=', '),
'language': meta.get('language'),
'language_preference': 10 if meta.get('class') == 'main' else -10 if meta.get('class') == 'ad' else -1,
'quality': qualities(self._QUALITIES)(meta.get('quality')),
diff --git a/yt_dlp/utils.py b/yt_dlp/utils.py
index 17f34a853..75b4ed61b 100644
--- a/yt_dlp/utils.py
+++ b/yt_dlp/utils.py
@@ -6570,3 +6570,9 @@ def remove_terminal_sequences(string):
def number_of_digits(number):
return len('%d' % number)
+
+
+def join_nonempty(*values, delim='-', from_dict=None):
+ if from_dict is not None:
+ values = operator.itemgetter(values)(from_dict)
+ return delim.join(map(str, filter(None, values)))