mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2024-11-25 02:45:12 +00:00
Better support HLS media discontinuity and fully support media initialization (#105)
* Added options: `--hls-split-discontinuity` and `--no-hls-split-discontinuity` Authored-by: shirtjs <2660574+shirtjs@users.noreply.github.com>
This commit is contained in:
parent
c8d83a22ef
commit
310c2ed2c6
13 changed files with 471 additions and 517 deletions
|
@ -439,361 +439,251 @@ def test_extract_jwplayer_data_realworld(self):
|
||||||
|
|
||||||
def test_parse_m3u8_formats(self):
|
def test_parse_m3u8_formats(self):
|
||||||
_TEST_CASES = [
|
_TEST_CASES = [
|
||||||
(
|
|
||||||
# https://github.com/ytdl-org/youtube-dl/issues/11507
|
|
||||||
# http://pluzz.francetv.fr/videos/le_ministere.html
|
|
||||||
'pluzz_francetv_11507',
|
|
||||||
'http://replayftv-vh.akamaihd.net/i/streaming-adaptatif_france-dom-tom/2017/S16/J2/156589847-58f59130c1f52-,standard1,standard2,standard3,standard4,standard5,.mp4.csmil/master.m3u8?caption=2017%2F16%2F156589847-1492488987.m3u8%3Afra%3AFrancais&audiotrack=0%3Afra%3AFrancais',
|
|
||||||
[{
|
|
||||||
'url': 'http://replayftv-vh.akamaihd.net/i/streaming-adaptatif_france-dom-tom/2017/S16/J2/156589847-58f59130c1f52-,standard1,standard2,standard3,standard4,standard5,.mp4.csmil/index_0_av.m3u8?null=0',
|
|
||||||
'manifest_url': 'http://replayftv-vh.akamaihd.net/i/streaming-adaptatif_france-dom-tom/2017/S16/J2/156589847-58f59130c1f52-,standard1,standard2,standard3,standard4,standard5,.mp4.csmil/master.m3u8?caption=2017%2F16%2F156589847-1492488987.m3u8%3Afra%3AFrancais&audiotrack=0%3Afra%3AFrancais',
|
|
||||||
'ext': 'mp4',
|
|
||||||
'format_id': '180',
|
|
||||||
'protocol': 'm3u8',
|
|
||||||
'acodec': 'mp4a.40.2',
|
|
||||||
'vcodec': 'avc1.66.30',
|
|
||||||
'tbr': 180,
|
|
||||||
'width': 256,
|
|
||||||
'height': 144,
|
|
||||||
}, {
|
|
||||||
'url': 'http://replayftv-vh.akamaihd.net/i/streaming-adaptatif_france-dom-tom/2017/S16/J2/156589847-58f59130c1f52-,standard1,standard2,standard3,standard4,standard5,.mp4.csmil/index_1_av.m3u8?null=0',
|
|
||||||
'manifest_url': 'http://replayftv-vh.akamaihd.net/i/streaming-adaptatif_france-dom-tom/2017/S16/J2/156589847-58f59130c1f52-,standard1,standard2,standard3,standard4,standard5,.mp4.csmil/master.m3u8?caption=2017%2F16%2F156589847-1492488987.m3u8%3Afra%3AFrancais&audiotrack=0%3Afra%3AFrancais',
|
|
||||||
'ext': 'mp4',
|
|
||||||
'format_id': '303',
|
|
||||||
'protocol': 'm3u8',
|
|
||||||
'acodec': 'mp4a.40.2',
|
|
||||||
'vcodec': 'avc1.66.30',
|
|
||||||
'tbr': 303,
|
|
||||||
'width': 320,
|
|
||||||
'height': 180,
|
|
||||||
}, {
|
|
||||||
'url': 'http://replayftv-vh.akamaihd.net/i/streaming-adaptatif_france-dom-tom/2017/S16/J2/156589847-58f59130c1f52-,standard1,standard2,standard3,standard4,standard5,.mp4.csmil/index_2_av.m3u8?null=0',
|
|
||||||
'manifest_url': 'http://replayftv-vh.akamaihd.net/i/streaming-adaptatif_france-dom-tom/2017/S16/J2/156589847-58f59130c1f52-,standard1,standard2,standard3,standard4,standard5,.mp4.csmil/master.m3u8?caption=2017%2F16%2F156589847-1492488987.m3u8%3Afra%3AFrancais&audiotrack=0%3Afra%3AFrancais',
|
|
||||||
'ext': 'mp4',
|
|
||||||
'format_id': '575',
|
|
||||||
'protocol': 'm3u8',
|
|
||||||
'acodec': 'mp4a.40.2',
|
|
||||||
'vcodec': 'avc1.66.30',
|
|
||||||
'tbr': 575,
|
|
||||||
'width': 512,
|
|
||||||
'height': 288,
|
|
||||||
}, {
|
|
||||||
'url': 'http://replayftv-vh.akamaihd.net/i/streaming-adaptatif_france-dom-tom/2017/S16/J2/156589847-58f59130c1f52-,standard1,standard2,standard3,standard4,standard5,.mp4.csmil/index_3_av.m3u8?null=0',
|
|
||||||
'manifest_url': 'http://replayftv-vh.akamaihd.net/i/streaming-adaptatif_france-dom-tom/2017/S16/J2/156589847-58f59130c1f52-,standard1,standard2,standard3,standard4,standard5,.mp4.csmil/master.m3u8?caption=2017%2F16%2F156589847-1492488987.m3u8%3Afra%3AFrancais&audiotrack=0%3Afra%3AFrancais',
|
|
||||||
'ext': 'mp4',
|
|
||||||
'format_id': '831',
|
|
||||||
'protocol': 'm3u8',
|
|
||||||
'acodec': 'mp4a.40.2',
|
|
||||||
'vcodec': 'avc1.77.30',
|
|
||||||
'tbr': 831,
|
|
||||||
'width': 704,
|
|
||||||
'height': 396,
|
|
||||||
}, {
|
|
||||||
'url': 'http://replayftv-vh.akamaihd.net/i/streaming-adaptatif_france-dom-tom/2017/S16/J2/156589847-58f59130c1f52-,standard1,standard2,standard3,standard4,standard5,.mp4.csmil/index_4_av.m3u8?null=0',
|
|
||||||
'manifest_url': 'http://replayftv-vh.akamaihd.net/i/streaming-adaptatif_france-dom-tom/2017/S16/J2/156589847-58f59130c1f52-,standard1,standard2,standard3,standard4,standard5,.mp4.csmil/master.m3u8?caption=2017%2F16%2F156589847-1492488987.m3u8%3Afra%3AFrancais&audiotrack=0%3Afra%3AFrancais',
|
|
||||||
'ext': 'mp4',
|
|
||||||
'protocol': 'm3u8',
|
|
||||||
'format_id': '1467',
|
|
||||||
'acodec': 'mp4a.40.2',
|
|
||||||
'vcodec': 'avc1.77.30',
|
|
||||||
'tbr': 1467,
|
|
||||||
'width': 1024,
|
|
||||||
'height': 576,
|
|
||||||
}]
|
|
||||||
),
|
|
||||||
(
|
(
|
||||||
# https://github.com/ytdl-org/youtube-dl/issues/11995
|
# https://github.com/ytdl-org/youtube-dl/issues/11995
|
||||||
# http://teamcoco.com/video/clueless-gamer-super-bowl-for-honor
|
# http://teamcoco.com/video/clueless-gamer-super-bowl-for-honor
|
||||||
'teamcoco_11995',
|
'img_bipbop_adv_example_fmp4',
|
||||||
'http://ak.storage-w.teamcococdn.com/cdn/2017-02/98599/ed8f/main.m3u8',
|
'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8',
|
||||||
[{
|
[{
|
||||||
'url': 'http://ak.storage-w.teamcococdn.com/cdn/2017-02/98599/ed8f/hls/CONAN_020217_Highlight_show-audio-160k_v4.m3u8',
|
'format_id': 'aud1-English',
|
||||||
'manifest_url': 'http://ak.storage-w.teamcococdn.com/cdn/2017-02/98599/ed8f/main.m3u8',
|
'url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/a1/prog_index.m3u8',
|
||||||
|
'manifest_url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8',
|
||||||
|
'language': 'en',
|
||||||
'ext': 'mp4',
|
'ext': 'mp4',
|
||||||
'format_id': 'audio-0-Default',
|
|
||||||
'protocol': 'm3u8',
|
'protocol': 'm3u8',
|
||||||
'vcodec': 'none',
|
'audio_ext': 'mp4',
|
||||||
}, {
|
}, {
|
||||||
'url': 'http://ak.storage-w.teamcococdn.com/cdn/2017-02/98599/ed8f/hls/CONAN_020217_Highlight_show-audio-64k_v4.m3u8',
|
'format_id': 'aud2-English',
|
||||||
'manifest_url': 'http://ak.storage-w.teamcococdn.com/cdn/2017-02/98599/ed8f/main.m3u8',
|
'url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/a2/prog_index.m3u8',
|
||||||
|
'manifest_url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8',
|
||||||
|
'language': 'en',
|
||||||
'ext': 'mp4',
|
'ext': 'mp4',
|
||||||
'format_id': 'audio-1-Default',
|
|
||||||
'protocol': 'm3u8',
|
'protocol': 'm3u8',
|
||||||
'vcodec': 'none',
|
'audio_ext': 'mp4',
|
||||||
}, {
|
}, {
|
||||||
'url': 'http://ak.storage-w.teamcococdn.com/cdn/2017-02/98599/ed8f/hls/CONAN_020217_Highlight_show-audio-64k_v4.m3u8',
|
'format_id': 'aud3-English',
|
||||||
'manifest_url': 'http://ak.storage-w.teamcococdn.com/cdn/2017-02/98599/ed8f/main.m3u8',
|
'url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/a3/prog_index.m3u8',
|
||||||
|
'manifest_url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8',
|
||||||
|
'language': 'en',
|
||||||
'ext': 'mp4',
|
'ext': 'mp4',
|
||||||
'format_id': '71',
|
|
||||||
'protocol': 'm3u8',
|
'protocol': 'm3u8',
|
||||||
'acodec': 'mp4a.40.5',
|
'audio_ext': 'mp4',
|
||||||
'vcodec': 'none',
|
|
||||||
'tbr': 71,
|
|
||||||
}, {
|
}, {
|
||||||
'url': 'http://ak.storage-w.teamcococdn.com/cdn/2017-02/98599/ed8f/hls/CONAN_020217_Highlight_show-400k_v4.m3u8',
|
'format_id': '530',
|
||||||
'manifest_url': 'http://ak.storage-w.teamcococdn.com/cdn/2017-02/98599/ed8f/main.m3u8',
|
'url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/v2/prog_index.m3u8',
|
||||||
|
'manifest_url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8',
|
||||||
'ext': 'mp4',
|
'ext': 'mp4',
|
||||||
'format_id': '413',
|
|
||||||
'protocol': 'm3u8',
|
'protocol': 'm3u8',
|
||||||
'acodec': 'none',
|
|
||||||
'vcodec': 'avc1.42001e',
|
|
||||||
'tbr': 413,
|
|
||||||
'width': 400,
|
|
||||||
'height': 224,
|
|
||||||
}, {
|
|
||||||
'url': 'http://ak.storage-w.teamcococdn.com/cdn/2017-02/98599/ed8f/hls/CONAN_020217_Highlight_show-400k_v4.m3u8',
|
|
||||||
'manifest_url': 'http://ak.storage-w.teamcococdn.com/cdn/2017-02/98599/ed8f/main.m3u8',
|
|
||||||
'ext': 'mp4',
|
|
||||||
'format_id': '522',
|
|
||||||
'protocol': 'm3u8',
|
|
||||||
'acodec': 'none',
|
|
||||||
'vcodec': 'avc1.42001e',
|
|
||||||
'tbr': 522,
|
|
||||||
'width': 400,
|
|
||||||
'height': 224,
|
|
||||||
}, {
|
|
||||||
'url': 'http://ak.storage-w.teamcococdn.com/cdn/2017-02/98599/ed8f/hls/CONAN_020217_Highlight_show-1m_v4.m3u8',
|
|
||||||
'manifest_url': 'http://ak.storage-w.teamcococdn.com/cdn/2017-02/98599/ed8f/main.m3u8',
|
|
||||||
'ext': 'mp4',
|
|
||||||
'format_id': '1205',
|
|
||||||
'protocol': 'm3u8',
|
|
||||||
'acodec': 'none',
|
|
||||||
'vcodec': 'avc1.4d001e',
|
|
||||||
'tbr': 1205,
|
|
||||||
'width': 640,
|
|
||||||
'height': 360,
|
|
||||||
}, {
|
|
||||||
'url': 'http://ak.storage-w.teamcococdn.com/cdn/2017-02/98599/ed8f/hls/CONAN_020217_Highlight_show-2m_v4.m3u8',
|
|
||||||
'manifest_url': 'http://ak.storage-w.teamcococdn.com/cdn/2017-02/98599/ed8f/main.m3u8',
|
|
||||||
'ext': 'mp4',
|
|
||||||
'format_id': '2374',
|
|
||||||
'protocol': 'm3u8',
|
|
||||||
'acodec': 'none',
|
|
||||||
'vcodec': 'avc1.4d001f',
|
|
||||||
'tbr': 2374,
|
|
||||||
'width': 1024,
|
|
||||||
'height': 576,
|
|
||||||
}]
|
|
||||||
),
|
|
||||||
(
|
|
||||||
# https://github.com/ytdl-org/youtube-dl/issues/12211
|
|
||||||
# http://video.toggle.sg/en/series/whoopie-s-world/ep3/478601
|
|
||||||
'toggle_mobile_12211',
|
|
||||||
'http://cdnapi.kaltura.com/p/2082311/sp/208231100/playManifest/protocol/http/entryId/0_89q6e8ku/format/applehttp/tags/mobile_sd/f/a.m3u8',
|
|
||||||
[{
|
|
||||||
'url': 'http://k.toggle.sg/fhls/p/2082311/sp/208231100/serveFlavor/entryId/0_89q6e8ku/v/2/pv/1/flavorId/0_sa2ntrdg/name/a.mp4/index.m3u8',
|
|
||||||
'manifest_url': 'http://cdnapi.kaltura.com/p/2082311/sp/208231100/playManifest/protocol/http/entryId/0_89q6e8ku/format/applehttp/tags/mobile_sd/f/a.m3u8',
|
|
||||||
'ext': 'mp4',
|
|
||||||
'format_id': 'audio-English',
|
|
||||||
'protocol': 'm3u8',
|
|
||||||
'language': 'eng',
|
|
||||||
'vcodec': 'none',
|
|
||||||
}, {
|
|
||||||
'url': 'http://k.toggle.sg/fhls/p/2082311/sp/208231100/serveFlavor/entryId/0_89q6e8ku/v/2/pv/1/flavorId/0_r7y0nitg/name/a.mp4/index.m3u8',
|
|
||||||
'manifest_url': 'http://cdnapi.kaltura.com/p/2082311/sp/208231100/playManifest/protocol/http/entryId/0_89q6e8ku/format/applehttp/tags/mobile_sd/f/a.m3u8',
|
|
||||||
'ext': 'mp4',
|
|
||||||
'format_id': 'audio-Undefined',
|
|
||||||
'protocol': 'm3u8',
|
|
||||||
'language': 'und',
|
|
||||||
'vcodec': 'none',
|
|
||||||
}, {
|
|
||||||
'url': 'http://k.toggle.sg/fhls/p/2082311/sp/208231100/serveFlavor/entryId/0_89q6e8ku/v/2/pv/1/flavorId/0_qlk9hlzr/name/a.mp4/index.m3u8',
|
|
||||||
'manifest_url': 'http://cdnapi.kaltura.com/p/2082311/sp/208231100/playManifest/protocol/http/entryId/0_89q6e8ku/format/applehttp/tags/mobile_sd/f/a.m3u8',
|
|
||||||
'ext': 'mp4',
|
|
||||||
'format_id': '155',
|
|
||||||
'protocol': 'm3u8',
|
|
||||||
'tbr': 155.648,
|
|
||||||
'width': 320,
|
|
||||||
'height': 180,
|
|
||||||
}, {
|
|
||||||
'url': 'http://k.toggle.sg/fhls/p/2082311/sp/208231100/serveFlavor/entryId/0_89q6e8ku/v/2/pv/1/flavorId/0_oefackmi/name/a.mp4/index.m3u8',
|
|
||||||
'manifest_url': 'http://cdnapi.kaltura.com/p/2082311/sp/208231100/playManifest/protocol/http/entryId/0_89q6e8ku/format/applehttp/tags/mobile_sd/f/a.m3u8',
|
|
||||||
'ext': 'mp4',
|
|
||||||
'format_id': '502',
|
|
||||||
'protocol': 'm3u8',
|
|
||||||
'tbr': 502.784,
|
|
||||||
'width': 480,
|
'width': 480,
|
||||||
'height': 270,
|
'height': 270,
|
||||||
|
'vcodec': 'avc1.640015',
|
||||||
}, {
|
}, {
|
||||||
'url': 'http://k.toggle.sg/fhls/p/2082311/sp/208231100/serveFlavor/entryId/0_89q6e8ku/v/12/pv/1/flavorId/0_vyg9pj7k/name/a.mp4/index.m3u8',
|
'format_id': '561',
|
||||||
'manifest_url': 'http://cdnapi.kaltura.com/p/2082311/sp/208231100/playManifest/protocol/http/entryId/0_89q6e8ku/format/applehttp/tags/mobile_sd/f/a.m3u8',
|
'url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/v2/prog_index.m3u8',
|
||||||
|
'manifest_url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8',
|
||||||
'ext': 'mp4',
|
'ext': 'mp4',
|
||||||
'format_id': '827',
|
|
||||||
'protocol': 'm3u8',
|
'protocol': 'm3u8',
|
||||||
'tbr': 827.392,
|
|
||||||
'width': 640,
|
|
||||||
'height': 360,
|
|
||||||
}, {
|
|
||||||
'url': 'http://k.toggle.sg/fhls/p/2082311/sp/208231100/serveFlavor/entryId/0_89q6e8ku/v/12/pv/1/flavorId/0_50n4psvx/name/a.mp4/index.m3u8',
|
|
||||||
'manifest_url': 'http://cdnapi.kaltura.com/p/2082311/sp/208231100/playManifest/protocol/http/entryId/0_89q6e8ku/format/applehttp/tags/mobile_sd/f/a.m3u8',
|
|
||||||
'ext': 'mp4',
|
|
||||||
'format_id': '1396',
|
|
||||||
'protocol': 'm3u8',
|
|
||||||
'tbr': 1396.736,
|
|
||||||
'width': 854,
|
|
||||||
'height': 480,
|
|
||||||
}]
|
|
||||||
),
|
|
||||||
(
|
|
||||||
# http://www.twitch.tv/riotgames/v/6528877
|
|
||||||
'twitch_vod',
|
|
||||||
'https://usher.ttvnw.net/vod/6528877?allow_source=true&allow_audio_only=true&allow_spectre=true&player=twitchweb&nauth=%7B%22user_id%22%3Anull%2C%22vod_id%22%3A6528877%2C%22expires%22%3A1492887874%2C%22chansub%22%3A%7B%22restricted_bitrates%22%3A%5B%5D%7D%2C%22privileged%22%3Afalse%2C%22https_required%22%3Afalse%7D&nauthsig=3e29296a6824a0f48f9e731383f77a614fc79bee',
|
|
||||||
[{
|
|
||||||
'url': 'https://vod.edgecast.hls.ttvnw.net/e5da31ab49_riotgames_15001215120_261543898/audio_only/index-muted-HM49I092CC.m3u8',
|
|
||||||
'manifest_url': 'https://usher.ttvnw.net/vod/6528877?allow_source=true&allow_audio_only=true&allow_spectre=true&player=twitchweb&nauth=%7B%22user_id%22%3Anull%2C%22vod_id%22%3A6528877%2C%22expires%22%3A1492887874%2C%22chansub%22%3A%7B%22restricted_bitrates%22%3A%5B%5D%7D%2C%22privileged%22%3Afalse%2C%22https_required%22%3Afalse%7D&nauthsig=3e29296a6824a0f48f9e731383f77a614fc79bee',
|
|
||||||
'ext': 'mp4',
|
|
||||||
'format_id': 'Audio Only',
|
|
||||||
'protocol': 'm3u8',
|
|
||||||
'acodec': 'mp4a.40.2',
|
|
||||||
'vcodec': 'none',
|
|
||||||
'tbr': 182.725,
|
|
||||||
}, {
|
|
||||||
'url': 'https://vod.edgecast.hls.ttvnw.net/e5da31ab49_riotgames_15001215120_261543898/mobile/index-muted-HM49I092CC.m3u8',
|
|
||||||
'manifest_url': 'https://usher.ttvnw.net/vod/6528877?allow_source=true&allow_audio_only=true&allow_spectre=true&player=twitchweb&nauth=%7B%22user_id%22%3Anull%2C%22vod_id%22%3A6528877%2C%22expires%22%3A1492887874%2C%22chansub%22%3A%7B%22restricted_bitrates%22%3A%5B%5D%7D%2C%22privileged%22%3Afalse%2C%22https_required%22%3Afalse%7D&nauthsig=3e29296a6824a0f48f9e731383f77a614fc79bee',
|
|
||||||
'ext': 'mp4',
|
|
||||||
'format_id': 'Mobile',
|
|
||||||
'protocol': 'm3u8',
|
|
||||||
'acodec': 'mp4a.40.2',
|
|
||||||
'vcodec': 'avc1.42C00D',
|
|
||||||
'tbr': 280.474,
|
|
||||||
'width': 400,
|
|
||||||
'height': 226,
|
|
||||||
}, {
|
|
||||||
'url': 'https://vod.edgecast.hls.ttvnw.net/e5da31ab49_riotgames_15001215120_261543898/low/index-muted-HM49I092CC.m3u8',
|
|
||||||
'manifest_url': 'https://usher.ttvnw.net/vod/6528877?allow_source=true&allow_audio_only=true&allow_spectre=true&player=twitchweb&nauth=%7B%22user_id%22%3Anull%2C%22vod_id%22%3A6528877%2C%22expires%22%3A1492887874%2C%22chansub%22%3A%7B%22restricted_bitrates%22%3A%5B%5D%7D%2C%22privileged%22%3Afalse%2C%22https_required%22%3Afalse%7D&nauthsig=3e29296a6824a0f48f9e731383f77a614fc79bee',
|
|
||||||
'ext': 'mp4',
|
|
||||||
'format_id': 'Low',
|
|
||||||
'protocol': 'm3u8',
|
|
||||||
'acodec': 'mp4a.40.2',
|
|
||||||
'vcodec': 'avc1.42C01E',
|
|
||||||
'tbr': 628.347,
|
|
||||||
'width': 640,
|
|
||||||
'height': 360,
|
|
||||||
}, {
|
|
||||||
'url': 'https://vod.edgecast.hls.ttvnw.net/e5da31ab49_riotgames_15001215120_261543898/medium/index-muted-HM49I092CC.m3u8',
|
|
||||||
'manifest_url': 'https://usher.ttvnw.net/vod/6528877?allow_source=true&allow_audio_only=true&allow_spectre=true&player=twitchweb&nauth=%7B%22user_id%22%3Anull%2C%22vod_id%22%3A6528877%2C%22expires%22%3A1492887874%2C%22chansub%22%3A%7B%22restricted_bitrates%22%3A%5B%5D%7D%2C%22privileged%22%3Afalse%2C%22https_required%22%3Afalse%7D&nauthsig=3e29296a6824a0f48f9e731383f77a614fc79bee',
|
|
||||||
'ext': 'mp4',
|
|
||||||
'format_id': 'Medium',
|
|
||||||
'protocol': 'm3u8',
|
|
||||||
'acodec': 'mp4a.40.2',
|
|
||||||
'vcodec': 'avc1.42C01E',
|
|
||||||
'tbr': 893.387,
|
|
||||||
'width': 852,
|
|
||||||
'height': 480,
|
|
||||||
}, {
|
|
||||||
'url': 'https://vod.edgecast.hls.ttvnw.net/e5da31ab49_riotgames_15001215120_261543898/high/index-muted-HM49I092CC.m3u8',
|
|
||||||
'manifest_url': 'https://usher.ttvnw.net/vod/6528877?allow_source=true&allow_audio_only=true&allow_spectre=true&player=twitchweb&nauth=%7B%22user_id%22%3Anull%2C%22vod_id%22%3A6528877%2C%22expires%22%3A1492887874%2C%22chansub%22%3A%7B%22restricted_bitrates%22%3A%5B%5D%7D%2C%22privileged%22%3Afalse%2C%22https_required%22%3Afalse%7D&nauthsig=3e29296a6824a0f48f9e731383f77a614fc79bee',
|
|
||||||
'ext': 'mp4',
|
|
||||||
'format_id': 'High',
|
|
||||||
'protocol': 'm3u8',
|
|
||||||
'acodec': 'mp4a.40.2',
|
|
||||||
'vcodec': 'avc1.42C01F',
|
|
||||||
'tbr': 1603.789,
|
|
||||||
'width': 1280,
|
|
||||||
'height': 720,
|
|
||||||
}, {
|
|
||||||
'url': 'https://vod.edgecast.hls.ttvnw.net/e5da31ab49_riotgames_15001215120_261543898/chunked/index-muted-HM49I092CC.m3u8',
|
|
||||||
'manifest_url': 'https://usher.ttvnw.net/vod/6528877?allow_source=true&allow_audio_only=true&allow_spectre=true&player=twitchweb&nauth=%7B%22user_id%22%3Anull%2C%22vod_id%22%3A6528877%2C%22expires%22%3A1492887874%2C%22chansub%22%3A%7B%22restricted_bitrates%22%3A%5B%5D%7D%2C%22privileged%22%3Afalse%2C%22https_required%22%3Afalse%7D&nauthsig=3e29296a6824a0f48f9e731383f77a614fc79bee',
|
|
||||||
'ext': 'mp4',
|
|
||||||
'format_id': 'Source',
|
|
||||||
'protocol': 'm3u8',
|
|
||||||
'acodec': 'mp4a.40.2',
|
|
||||||
'vcodec': 'avc1.100.31',
|
|
||||||
'tbr': 3214.134,
|
|
||||||
'width': 1280,
|
|
||||||
'height': 720,
|
|
||||||
}]
|
|
||||||
),
|
|
||||||
(
|
|
||||||
# http://www.vidio.com/watch/165683-dj_ambred-booyah-live-2015
|
|
||||||
# EXT-X-STREAM-INF tag with NAME attribute that is not defined
|
|
||||||
# in HLS specification
|
|
||||||
'vidio',
|
|
||||||
'https://www.vidio.com/videos/165683/playlist.m3u8',
|
|
||||||
[{
|
|
||||||
'url': 'https://cdn1-a.production.vidio.static6.com/uploads/165683/dj_ambred-4383-b300.mp4.m3u8',
|
|
||||||
'manifest_url': 'https://www.vidio.com/videos/165683/playlist.m3u8',
|
|
||||||
'ext': 'mp4',
|
|
||||||
'format_id': '270p 3G',
|
|
||||||
'protocol': 'm3u8',
|
|
||||||
'tbr': 300,
|
|
||||||
'width': 480,
|
'width': 480,
|
||||||
'height': 270,
|
'height': 270,
|
||||||
|
'vcodec': 'avc1.640015',
|
||||||
}, {
|
}, {
|
||||||
'url': 'https://cdn1-a.production.vidio.static6.com/uploads/165683/dj_ambred-4383-b600.mp4.m3u8',
|
'format_id': '753',
|
||||||
'manifest_url': 'https://www.vidio.com/videos/165683/playlist.m3u8',
|
'url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/v2/prog_index.m3u8',
|
||||||
|
'manifest_url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'protocol': 'm3u8',
|
||||||
|
'width': 480,
|
||||||
|
'height': 270,
|
||||||
|
'vcodec': 'avc1.640015',
|
||||||
|
}, {
|
||||||
|
'format_id': '895',
|
||||||
|
'url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/v3/prog_index.m3u8',
|
||||||
|
'manifest_url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8',
|
||||||
'ext': 'mp4',
|
'ext': 'mp4',
|
||||||
'format_id': '360p SD',
|
|
||||||
'protocol': 'm3u8',
|
'protocol': 'm3u8',
|
||||||
'tbr': 600,
|
|
||||||
'width': 640,
|
'width': 640,
|
||||||
'height': 360,
|
'height': 360,
|
||||||
|
'vcodec': 'avc1.64001e',
|
||||||
}, {
|
}, {
|
||||||
'url': 'https://cdn1-a.production.vidio.static6.com/uploads/165683/dj_ambred-4383-b1200.mp4.m3u8',
|
'format_id': '926',
|
||||||
'manifest_url': 'https://www.vidio.com/videos/165683/playlist.m3u8',
|
'url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/v3/prog_index.m3u8',
|
||||||
|
'manifest_url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8',
|
||||||
'ext': 'mp4',
|
'ext': 'mp4',
|
||||||
'format_id': '720p HD',
|
|
||||||
'protocol': 'm3u8',
|
'protocol': 'm3u8',
|
||||||
'tbr': 1200,
|
|
||||||
'width': 1280,
|
|
||||||
'height': 720,
|
|
||||||
}]
|
|
||||||
),
|
|
||||||
(
|
|
||||||
# https://github.com/ytdl-org/youtube-dl/issues/18923
|
|
||||||
# https://www.ted.com/talks/boris_hesser_a_grassroots_healthcare_revolution_in_africa
|
|
||||||
'ted_18923',
|
|
||||||
'http://hls.ted.com/talks/31241.m3u8',
|
|
||||||
[{
|
|
||||||
'url': 'http://hls.ted.com/videos/BorisHesser_2018S/audio/600k.m3u8?nobumpers=true&uniqueId=76011e2b',
|
|
||||||
'format_id': '600k-Audio',
|
|
||||||
'vcodec': 'none',
|
|
||||||
}, {
|
|
||||||
'url': 'http://hls.ted.com/videos/BorisHesser_2018S/audio/600k.m3u8?nobumpers=true&uniqueId=76011e2b',
|
|
||||||
'format_id': '68',
|
|
||||||
'vcodec': 'none',
|
|
||||||
}, {
|
|
||||||
'url': 'http://hls.ted.com/videos/BorisHesser_2018S/video/64k.m3u8?nobumpers=true&uniqueId=76011e2b',
|
|
||||||
'format_id': '163',
|
|
||||||
'acodec': 'none',
|
|
||||||
'width': 320,
|
|
||||||
'height': 180,
|
|
||||||
}, {
|
|
||||||
'url': 'http://hls.ted.com/videos/BorisHesser_2018S/video/180k.m3u8?nobumpers=true&uniqueId=76011e2b',
|
|
||||||
'format_id': '481',
|
|
||||||
'acodec': 'none',
|
|
||||||
'width': 512,
|
|
||||||
'height': 288,
|
|
||||||
}, {
|
|
||||||
'url': 'http://hls.ted.com/videos/BorisHesser_2018S/video/320k.m3u8?nobumpers=true&uniqueId=76011e2b',
|
|
||||||
'format_id': '769',
|
|
||||||
'acodec': 'none',
|
|
||||||
'width': 512,
|
|
||||||
'height': 288,
|
|
||||||
}, {
|
|
||||||
'url': 'http://hls.ted.com/videos/BorisHesser_2018S/video/450k.m3u8?nobumpers=true&uniqueId=76011e2b',
|
|
||||||
'format_id': '984',
|
|
||||||
'acodec': 'none',
|
|
||||||
'width': 512,
|
|
||||||
'height': 288,
|
|
||||||
}, {
|
|
||||||
'url': 'http://hls.ted.com/videos/BorisHesser_2018S/video/600k.m3u8?nobumpers=true&uniqueId=76011e2b',
|
|
||||||
'format_id': '1255',
|
|
||||||
'acodec': 'none',
|
|
||||||
'width': 640,
|
'width': 640,
|
||||||
'height': 360,
|
'height': 360,
|
||||||
|
'vcodec': 'avc1.64001e',
|
||||||
}, {
|
}, {
|
||||||
'url': 'http://hls.ted.com/videos/BorisHesser_2018S/video/950k.m3u8?nobumpers=true&uniqueId=76011e2b',
|
'format_id': '1118',
|
||||||
'format_id': '1693',
|
'url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/v3/prog_index.m3u8',
|
||||||
'acodec': 'none',
|
'manifest_url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8',
|
||||||
'width': 853,
|
'ext': 'mp4',
|
||||||
'height': 480,
|
'protocol': 'm3u8',
|
||||||
|
'width': 640,
|
||||||
|
'height': 360,
|
||||||
|
'vcodec': 'avc1.64001e',
|
||||||
}, {
|
}, {
|
||||||
'url': 'http://hls.ted.com/videos/BorisHesser_2018S/video/1500k.m3u8?nobumpers=true&uniqueId=76011e2b',
|
'format_id': '1265',
|
||||||
'format_id': '2462',
|
'url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/v4/prog_index.m3u8',
|
||||||
'acodec': 'none',
|
'manifest_url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'protocol': 'm3u8',
|
||||||
|
'width': 768,
|
||||||
|
'height': 432,
|
||||||
|
'vcodec': 'avc1.64001e',
|
||||||
|
}, {
|
||||||
|
'format_id': '1295',
|
||||||
|
'url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/v4/prog_index.m3u8',
|
||||||
|
'manifest_url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'protocol': 'm3u8',
|
||||||
|
'width': 768,
|
||||||
|
'height': 432,
|
||||||
|
'vcodec': 'avc1.64001e',
|
||||||
|
}, {
|
||||||
|
'format_id': '1487',
|
||||||
|
'url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/v4/prog_index.m3u8',
|
||||||
|
'manifest_url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'protocol': 'm3u8',
|
||||||
|
'width': 768,
|
||||||
|
'height': 432,
|
||||||
|
'vcodec': 'avc1.64001e',
|
||||||
|
}, {
|
||||||
|
'format_id': '2168',
|
||||||
|
'url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/v5/prog_index.m3u8',
|
||||||
|
'manifest_url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'protocol': 'm3u8',
|
||||||
|
'width': 960,
|
||||||
|
'height': 540,
|
||||||
|
'vcodec': 'avc1.640020',
|
||||||
|
}, {
|
||||||
|
'format_id': '2198',
|
||||||
|
'url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/v5/prog_index.m3u8',
|
||||||
|
'manifest_url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'protocol': 'm3u8',
|
||||||
|
'width': 960,
|
||||||
|
'height': 540,
|
||||||
|
'vcodec': 'avc1.640020',
|
||||||
|
}, {
|
||||||
|
'format_id': '2390',
|
||||||
|
'url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/v5/prog_index.m3u8',
|
||||||
|
'manifest_url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'protocol': 'm3u8',
|
||||||
|
'width': 960,
|
||||||
|
'height': 540,
|
||||||
|
'vcodec': 'avc1.640020',
|
||||||
|
}, {
|
||||||
|
'format_id': '3168',
|
||||||
|
'url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/v6/prog_index.m3u8',
|
||||||
|
'manifest_url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'protocol': 'm3u8',
|
||||||
'width': 1280,
|
'width': 1280,
|
||||||
'height': 720,
|
'height': 720,
|
||||||
|
'vcodec': 'avc1.640020',
|
||||||
|
}, {
|
||||||
|
'format_id': '3199',
|
||||||
|
'url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/v6/prog_index.m3u8',
|
||||||
|
'manifest_url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'protocol': 'm3u8',
|
||||||
|
'width': 1280,
|
||||||
|
'height': 720,
|
||||||
|
'vcodec': 'avc1.640020',
|
||||||
|
}, {
|
||||||
|
'format_id': '3391',
|
||||||
|
'url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/v6/prog_index.m3u8',
|
||||||
|
'manifest_url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'protocol': 'm3u8',
|
||||||
|
'width': 1280,
|
||||||
|
'height': 720,
|
||||||
|
'vcodec': 'avc1.640020',
|
||||||
|
}, {
|
||||||
|
'format_id': '4670',
|
||||||
|
'url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/v7/prog_index.m3u8',
|
||||||
|
'manifest_url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'protocol': 'm3u8',
|
||||||
|
'width': 1920,
|
||||||
|
'height': 1080,
|
||||||
|
'vcodec': 'avc1.64002a',
|
||||||
|
}, {
|
||||||
|
'format_id': '4701',
|
||||||
|
'url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/v7/prog_index.m3u8',
|
||||||
|
'manifest_url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'protocol': 'm3u8',
|
||||||
|
'width': 1920,
|
||||||
|
'height': 1080,
|
||||||
|
'vcodec': 'avc1.64002a',
|
||||||
|
}, {
|
||||||
|
'format_id': '4893',
|
||||||
|
'url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/v7/prog_index.m3u8',
|
||||||
|
'manifest_url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'protocol': 'm3u8',
|
||||||
|
'width': 1920,
|
||||||
|
'height': 1080,
|
||||||
|
'vcodec': 'avc1.64002a',
|
||||||
|
}, {
|
||||||
|
'format_id': '6170',
|
||||||
|
'url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/v8/prog_index.m3u8',
|
||||||
|
'manifest_url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'protocol': 'm3u8',
|
||||||
|
'width': 1920,
|
||||||
|
'height': 1080,
|
||||||
|
'vcodec': 'avc1.64002a',
|
||||||
|
}, {
|
||||||
|
'format_id': '6200',
|
||||||
|
'url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/v8/prog_index.m3u8',
|
||||||
|
'manifest_url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'protocol': 'm3u8',
|
||||||
|
'width': 1920,
|
||||||
|
'height': 1080,
|
||||||
|
'vcodec': 'avc1.64002a',
|
||||||
|
}, {
|
||||||
|
'format_id': '6392',
|
||||||
|
'url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/v8/prog_index.m3u8',
|
||||||
|
'manifest_url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'protocol': 'm3u8',
|
||||||
|
'width': 1920,
|
||||||
|
'height': 1080,
|
||||||
|
'vcodec': 'avc1.64002a',
|
||||||
|
}, {
|
||||||
|
'format_id': '7968',
|
||||||
|
'url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/v9/prog_index.m3u8',
|
||||||
|
'manifest_url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'protocol': 'm3u8',
|
||||||
|
'width': 1920,
|
||||||
|
'height': 1080,
|
||||||
|
'vcodec': 'avc1.64002a',
|
||||||
|
}, {
|
||||||
|
'format_id': '7998',
|
||||||
|
'url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/v9/prog_index.m3u8',
|
||||||
|
'manifest_url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'protocol': 'm3u8',
|
||||||
|
'width': 1920,
|
||||||
|
'height': 1080,
|
||||||
|
'vcodec': 'avc1.64002a',
|
||||||
|
}, {
|
||||||
|
'format_id': '8190',
|
||||||
|
'url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/v9/prog_index.m3u8',
|
||||||
|
'manifest_url': 'https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'protocol': 'm3u8',
|
||||||
|
'width': 1920,
|
||||||
|
'height': 1080,
|
||||||
|
'vcodec': 'avc1.64002a',
|
||||||
}]
|
}]
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
76
test/testdata/m3u8/img_bipbop_adv_example_fmp4.m3u8
vendored
Normal file
76
test/testdata/m3u8/img_bipbop_adv_example_fmp4.m3u8
vendored
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
#EXTM3U
|
||||||
|
#EXT-X-VERSION:6
|
||||||
|
#EXT-X-INDEPENDENT-SEGMENTS
|
||||||
|
|
||||||
|
|
||||||
|
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=2168183,BANDWIDTH=2177116,CODECS="avc1.640020,mp4a.40.2",RESOLUTION=960x540,FRAME-RATE=60.000,CLOSED-CAPTIONS="cc1",AUDIO="aud1",SUBTITLES="sub1"
|
||||||
|
v5/prog_index.m3u8
|
||||||
|
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=7968416,BANDWIDTH=8001098,CODECS="avc1.64002a,mp4a.40.2",RESOLUTION=1920x1080,FRAME-RATE=60.000,CLOSED-CAPTIONS="cc1",AUDIO="aud1",SUBTITLES="sub1"
|
||||||
|
v9/prog_index.m3u8
|
||||||
|
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=6170000,BANDWIDTH=6312875,CODECS="avc1.64002a,mp4a.40.2",RESOLUTION=1920x1080,FRAME-RATE=60.000,CLOSED-CAPTIONS="cc1",AUDIO="aud1",SUBTITLES="sub1"
|
||||||
|
v8/prog_index.m3u8
|
||||||
|
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=4670769,BANDWIDTH=4943747,CODECS="avc1.64002a,mp4a.40.2",RESOLUTION=1920x1080,FRAME-RATE=60.000,CLOSED-CAPTIONS="cc1",AUDIO="aud1",SUBTITLES="sub1"
|
||||||
|
v7/prog_index.m3u8
|
||||||
|
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=3168702,BANDWIDTH=3216424,CODECS="avc1.640020,mp4a.40.2",RESOLUTION=1280x720,FRAME-RATE=60.000,CLOSED-CAPTIONS="cc1",AUDIO="aud1",SUBTITLES="sub1"
|
||||||
|
v6/prog_index.m3u8
|
||||||
|
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=1265132,BANDWIDTH=1268994,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=768x432,FRAME-RATE=30.000,CLOSED-CAPTIONS="cc1",AUDIO="aud1",SUBTITLES="sub1"
|
||||||
|
v4/prog_index.m3u8
|
||||||
|
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=895755,BANDWIDTH=902298,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,FRAME-RATE=30.000,CLOSED-CAPTIONS="cc1",AUDIO="aud1",SUBTITLES="sub1"
|
||||||
|
v3/prog_index.m3u8
|
||||||
|
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=530721,BANDWIDTH=541052,CODECS="avc1.640015,mp4a.40.2",RESOLUTION=480x270,FRAME-RATE=30.000,CLOSED-CAPTIONS="cc1",AUDIO="aud1",SUBTITLES="sub1"
|
||||||
|
v2/prog_index.m3u8
|
||||||
|
|
||||||
|
|
||||||
|
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=2390686,BANDWIDTH=2399619,CODECS="avc1.640020,ac-3",RESOLUTION=960x540,FRAME-RATE=60.000,CLOSED-CAPTIONS="cc1",AUDIO="aud2",SUBTITLES="sub1"
|
||||||
|
v5/prog_index.m3u8
|
||||||
|
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=8190919,BANDWIDTH=8223601,CODECS="avc1.64002a,ac-3",RESOLUTION=1920x1080,FRAME-RATE=60.000,CLOSED-CAPTIONS="cc1",AUDIO="aud2",SUBTITLES="sub1"
|
||||||
|
v9/prog_index.m3u8
|
||||||
|
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=6392503,BANDWIDTH=6535378,CODECS="avc1.64002a,ac-3",RESOLUTION=1920x1080,FRAME-RATE=60.000,CLOSED-CAPTIONS="cc1",AUDIO="aud2",SUBTITLES="sub1"
|
||||||
|
v8/prog_index.m3u8
|
||||||
|
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=4893272,BANDWIDTH=5166250,CODECS="avc1.64002a,ac-3",RESOLUTION=1920x1080,FRAME-RATE=60.000,CLOSED-CAPTIONS="cc1",AUDIO="aud2",SUBTITLES="sub1"
|
||||||
|
v7/prog_index.m3u8
|
||||||
|
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=3391205,BANDWIDTH=3438927,CODECS="avc1.640020,ac-3",RESOLUTION=1280x720,FRAME-RATE=60.000,CLOSED-CAPTIONS="cc1",AUDIO="aud2",SUBTITLES="sub1"
|
||||||
|
v6/prog_index.m3u8
|
||||||
|
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=1487635,BANDWIDTH=1491497,CODECS="avc1.64001e,ac-3",RESOLUTION=768x432,FRAME-RATE=30.000,CLOSED-CAPTIONS="cc1",AUDIO="aud2",SUBTITLES="sub1"
|
||||||
|
v4/prog_index.m3u8
|
||||||
|
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=1118258,BANDWIDTH=1124801,CODECS="avc1.64001e,ac-3",RESOLUTION=640x360,FRAME-RATE=30.000,CLOSED-CAPTIONS="cc1",AUDIO="aud2",SUBTITLES="sub1"
|
||||||
|
v3/prog_index.m3u8
|
||||||
|
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=753224,BANDWIDTH=763555,CODECS="avc1.640015,ac-3",RESOLUTION=480x270,FRAME-RATE=30.000,CLOSED-CAPTIONS="cc1",AUDIO="aud2",SUBTITLES="sub1"
|
||||||
|
v2/prog_index.m3u8
|
||||||
|
|
||||||
|
|
||||||
|
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=2198686,BANDWIDTH=2207619,CODECS="avc1.640020,ec-3",RESOLUTION=960x540,FRAME-RATE=60.000,CLOSED-CAPTIONS="cc1",AUDIO="aud3",SUBTITLES="sub1"
|
||||||
|
v5/prog_index.m3u8
|
||||||
|
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=7998919,BANDWIDTH=8031601,CODECS="avc1.64002a,ec-3",RESOLUTION=1920x1080,FRAME-RATE=60.000,CLOSED-CAPTIONS="cc1",AUDIO="aud3",SUBTITLES="sub1"
|
||||||
|
v9/prog_index.m3u8
|
||||||
|
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=6200503,BANDWIDTH=6343378,CODECS="avc1.64002a,ec-3",RESOLUTION=1920x1080,FRAME-RATE=60.000,CLOSED-CAPTIONS="cc1",AUDIO="aud3",SUBTITLES="sub1"
|
||||||
|
v8/prog_index.m3u8
|
||||||
|
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=4701272,BANDWIDTH=4974250,CODECS="avc1.64002a,ec-3",RESOLUTION=1920x1080,FRAME-RATE=60.000,CLOSED-CAPTIONS="cc1",AUDIO="aud3",SUBTITLES="sub1"
|
||||||
|
v7/prog_index.m3u8
|
||||||
|
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=3199205,BANDWIDTH=3246927,CODECS="avc1.640020,ec-3",RESOLUTION=1280x720,FRAME-RATE=60.000,CLOSED-CAPTIONS="cc1",AUDIO="aud3",SUBTITLES="sub1"
|
||||||
|
v6/prog_index.m3u8
|
||||||
|
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=1295635,BANDWIDTH=1299497,CODECS="avc1.64001e,ec-3",RESOLUTION=768x432,FRAME-RATE=30.000,CLOSED-CAPTIONS="cc1",AUDIO="aud3",SUBTITLES="sub1"
|
||||||
|
v4/prog_index.m3u8
|
||||||
|
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=926258,BANDWIDTH=932801,CODECS="avc1.64001e,ec-3",RESOLUTION=640x360,FRAME-RATE=30.000,CLOSED-CAPTIONS="cc1",AUDIO="aud3",SUBTITLES="sub1"
|
||||||
|
v3/prog_index.m3u8
|
||||||
|
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=561224,BANDWIDTH=571555,CODECS="avc1.640015,ec-3",RESOLUTION=480x270,FRAME-RATE=30.000,CLOSED-CAPTIONS="cc1",AUDIO="aud3",SUBTITLES="sub1"
|
||||||
|
v2/prog_index.m3u8
|
||||||
|
|
||||||
|
|
||||||
|
#EXT-X-I-FRAME-STREAM-INF:AVERAGE-BANDWIDTH=183689,BANDWIDTH=187492,CODECS="avc1.64002a",RESOLUTION=1920x1080,URI="v7/iframe_index.m3u8"
|
||||||
|
#EXT-X-I-FRAME-STREAM-INF:AVERAGE-BANDWIDTH=132672,BANDWIDTH=136398,CODECS="avc1.640020",RESOLUTION=1280x720,URI="v6/iframe_index.m3u8"
|
||||||
|
#EXT-X-I-FRAME-STREAM-INF:AVERAGE-BANDWIDTH=97767,BANDWIDTH=101378,CODECS="avc1.640020",RESOLUTION=960x540,URI="v5/iframe_index.m3u8"
|
||||||
|
#EXT-X-I-FRAME-STREAM-INF:AVERAGE-BANDWIDTH=75722,BANDWIDTH=77818,CODECS="avc1.64001e",RESOLUTION=768x432,URI="v4/iframe_index.m3u8"
|
||||||
|
#EXT-X-I-FRAME-STREAM-INF:AVERAGE-BANDWIDTH=63522,BANDWIDTH=65091,CODECS="avc1.64001e",RESOLUTION=640x360,URI="v3/iframe_index.m3u8"
|
||||||
|
#EXT-X-I-FRAME-STREAM-INF:AVERAGE-BANDWIDTH=39678,BANDWIDTH=40282,CODECS="avc1.640015",RESOLUTION=480x270,URI="v2/iframe_index.m3u8"
|
||||||
|
|
||||||
|
|
||||||
|
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aud1",LANGUAGE="en",NAME="English",AUTOSELECT=YES,DEFAULT=YES,CHANNELS="2",URI="a1/prog_index.m3u8"
|
||||||
|
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aud2",LANGUAGE="en",NAME="English",AUTOSELECT=YES,DEFAULT=YES,CHANNELS="6",URI="a2/prog_index.m3u8"
|
||||||
|
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aud3",LANGUAGE="en",NAME="English",AUTOSELECT=YES,DEFAULT=YES,CHANNELS="6",URI="a3/prog_index.m3u8"
|
||||||
|
|
||||||
|
|
||||||
|
#EXT-X-MEDIA:TYPE=CLOSED-CAPTIONS,GROUP-ID="cc1",LANGUAGE="en",NAME="English",AUTOSELECT=YES,DEFAULT=YES,INSTREAM-ID="CC1"
|
||||||
|
|
||||||
|
|
||||||
|
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="sub1",LANGUAGE="en",NAME="English",AUTOSELECT=YES,DEFAULT=YES,FORCED=NO,URI="s1/en/prog_index.m3u8"
|
14
test/testdata/m3u8/pluzz_francetv_11507.m3u8
vendored
14
test/testdata/m3u8/pluzz_francetv_11507.m3u8
vendored
|
@ -1,14 +0,0 @@
|
||||||
#EXTM3U
|
|
||||||
#EXT-X-VERSION:5
|
|
||||||
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="Francais",DEFAULT=NO,FORCED=NO,URI="http://replayftv-pmd.francetv.fr/subtitles/2017/16/156589847-1492488987.m3u8",LANGUAGE="fra"
|
|
||||||
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aac",LANGUAGE="fra",NAME="Francais",DEFAULT=YES, AUTOSELECT=YES
|
|
||||||
#EXT-X-STREAM-INF:SUBTITLES="subs",AUDIO="aac",PROGRAM-ID=1,BANDWIDTH=180000,RESOLUTION=256x144,CODECS="avc1.66.30, mp4a.40.2"
|
|
||||||
http://replayftv-vh.akamaihd.net/i/streaming-adaptatif_france-dom-tom/2017/S16/J2/156589847-58f59130c1f52-,standard1,standard2,standard3,standard4,standard5,.mp4.csmil/index_0_av.m3u8?null=0
|
|
||||||
#EXT-X-STREAM-INF:SUBTITLES="subs",AUDIO="aac",PROGRAM-ID=1,BANDWIDTH=303000,RESOLUTION=320x180,CODECS="avc1.66.30, mp4a.40.2"
|
|
||||||
http://replayftv-vh.akamaihd.net/i/streaming-adaptatif_france-dom-tom/2017/S16/J2/156589847-58f59130c1f52-,standard1,standard2,standard3,standard4,standard5,.mp4.csmil/index_1_av.m3u8?null=0
|
|
||||||
#EXT-X-STREAM-INF:SUBTITLES="subs",AUDIO="aac",PROGRAM-ID=1,BANDWIDTH=575000,RESOLUTION=512x288,CODECS="avc1.66.30, mp4a.40.2"
|
|
||||||
http://replayftv-vh.akamaihd.net/i/streaming-adaptatif_france-dom-tom/2017/S16/J2/156589847-58f59130c1f52-,standard1,standard2,standard3,standard4,standard5,.mp4.csmil/index_2_av.m3u8?null=0
|
|
||||||
#EXT-X-STREAM-INF:SUBTITLES="subs",AUDIO="aac",PROGRAM-ID=1,BANDWIDTH=831000,RESOLUTION=704x396,CODECS="avc1.77.30, mp4a.40.2"
|
|
||||||
http://replayftv-vh.akamaihd.net/i/streaming-adaptatif_france-dom-tom/2017/S16/J2/156589847-58f59130c1f52-,standard1,standard2,standard3,standard4,standard5,.mp4.csmil/index_3_av.m3u8?null=0
|
|
||||||
#EXT-X-STREAM-INF:SUBTITLES="subs",AUDIO="aac",PROGRAM-ID=1,BANDWIDTH=1467000,RESOLUTION=1024x576,CODECS="avc1.77.30, mp4a.40.2"
|
|
||||||
http://replayftv-vh.akamaihd.net/i/streaming-adaptatif_france-dom-tom/2017/S16/J2/156589847-58f59130c1f52-,standard1,standard2,standard3,standard4,standard5,.mp4.csmil/index_4_av.m3u8?null=0
|
|
16
test/testdata/m3u8/teamcoco_11995.m3u8
vendored
16
test/testdata/m3u8/teamcoco_11995.m3u8
vendored
|
@ -1,16 +0,0 @@
|
||||||
#EXTM3U
|
|
||||||
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio-0",NAME="Default",AUTOSELECT=YES,DEFAULT=YES,URI="hls/CONAN_020217_Highlight_show-audio-160k_v4.m3u8"
|
|
||||||
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio-1",NAME="Default",AUTOSELECT=YES,DEFAULT=YES,URI="hls/CONAN_020217_Highlight_show-audio-64k_v4.m3u8"
|
|
||||||
#EXT-X-I-FRAME-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=37862000,CODECS="avc1.4d001f",URI="hls/CONAN_020217_Highlight_show-2m_iframe.m3u8"
|
|
||||||
#EXT-X-I-FRAME-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=18750000,CODECS="avc1.4d001e",URI="hls/CONAN_020217_Highlight_show-1m_iframe.m3u8"
|
|
||||||
#EXT-X-I-FRAME-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=6535000,CODECS="avc1.42001e",URI="hls/CONAN_020217_Highlight_show-400k_iframe.m3u8"
|
|
||||||
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2374000,RESOLUTION=1024x576,CODECS="avc1.4d001f,mp4a.40.2",AUDIO="audio-0"
|
|
||||||
hls/CONAN_020217_Highlight_show-2m_v4.m3u8
|
|
||||||
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1205000,RESOLUTION=640x360,CODECS="avc1.4d001e,mp4a.40.2",AUDIO="audio-0"
|
|
||||||
hls/CONAN_020217_Highlight_show-1m_v4.m3u8
|
|
||||||
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=522000,RESOLUTION=400x224,CODECS="avc1.42001e,mp4a.40.2",AUDIO="audio-0"
|
|
||||||
hls/CONAN_020217_Highlight_show-400k_v4.m3u8
|
|
||||||
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=413000,RESOLUTION=400x224,CODECS="avc1.42001e,mp4a.40.5",AUDIO="audio-1"
|
|
||||||
hls/CONAN_020217_Highlight_show-400k_v4.m3u8
|
|
||||||
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=71000,CODECS="mp4a.40.5",AUDIO="audio-1"
|
|
||||||
hls/CONAN_020217_Highlight_show-audio-64k_v4.m3u8
|
|
28
test/testdata/m3u8/ted_18923.m3u8
vendored
28
test/testdata/m3u8/ted_18923.m3u8
vendored
|
@ -1,28 +0,0 @@
|
||||||
#EXTM3U
|
|
||||||
#EXT-X-VERSION:4
|
|
||||||
#EXT-X-STREAM-INF:AUDIO="600k",BANDWIDTH=1255659,PROGRAM-ID=1,CODECS="avc1.42c01e,mp4a.40.2",RESOLUTION=640x360
|
|
||||||
/videos/BorisHesser_2018S/video/600k.m3u8?nobumpers=true&uniqueId=76011e2b
|
|
||||||
#EXT-X-STREAM-INF:AUDIO="600k",BANDWIDTH=163154,PROGRAM-ID=1,CODECS="avc1.42c00c,mp4a.40.2",RESOLUTION=320x180
|
|
||||||
/videos/BorisHesser_2018S/video/64k.m3u8?nobumpers=true&uniqueId=76011e2b
|
|
||||||
#EXT-X-STREAM-INF:AUDIO="600k",BANDWIDTH=481701,PROGRAM-ID=1,CODECS="avc1.42c015,mp4a.40.2",RESOLUTION=512x288
|
|
||||||
/videos/BorisHesser_2018S/video/180k.m3u8?nobumpers=true&uniqueId=76011e2b
|
|
||||||
#EXT-X-STREAM-INF:AUDIO="600k",BANDWIDTH=769968,PROGRAM-ID=1,CODECS="avc1.42c015,mp4a.40.2",RESOLUTION=512x288
|
|
||||||
/videos/BorisHesser_2018S/video/320k.m3u8?nobumpers=true&uniqueId=76011e2b
|
|
||||||
#EXT-X-STREAM-INF:AUDIO="600k",BANDWIDTH=984037,PROGRAM-ID=1,CODECS="avc1.42c015,mp4a.40.2",RESOLUTION=512x288
|
|
||||||
/videos/BorisHesser_2018S/video/450k.m3u8?nobumpers=true&uniqueId=76011e2b
|
|
||||||
#EXT-X-STREAM-INF:AUDIO="600k",BANDWIDTH=1693925,PROGRAM-ID=1,CODECS="avc1.4d401f,mp4a.40.2",RESOLUTION=853x480
|
|
||||||
/videos/BorisHesser_2018S/video/950k.m3u8?nobumpers=true&uniqueId=76011e2b
|
|
||||||
#EXT-X-STREAM-INF:AUDIO="600k",BANDWIDTH=2462469,PROGRAM-ID=1,CODECS="avc1.640028,mp4a.40.2",RESOLUTION=1280x720
|
|
||||||
/videos/BorisHesser_2018S/video/1500k.m3u8?nobumpers=true&uniqueId=76011e2b
|
|
||||||
#EXT-X-STREAM-INF:AUDIO="600k",BANDWIDTH=68101,PROGRAM-ID=1,CODECS="mp4a.40.2",DEFAULT=YES
|
|
||||||
/videos/BorisHesser_2018S/audio/600k.m3u8?nobumpers=true&uniqueId=76011e2b
|
|
||||||
|
|
||||||
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=74298,PROGRAM-ID=1,CODECS="avc1.42c00c",RESOLUTION=320x180,URI="/videos/BorisHesser_2018S/video/64k_iframe.m3u8?nobumpers=true&uniqueId=76011e2b"
|
|
||||||
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=216200,PROGRAM-ID=1,CODECS="avc1.42c015",RESOLUTION=512x288,URI="/videos/BorisHesser_2018S/video/180k_iframe.m3u8?nobumpers=true&uniqueId=76011e2b"
|
|
||||||
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=304717,PROGRAM-ID=1,CODECS="avc1.42c015",RESOLUTION=512x288,URI="/videos/BorisHesser_2018S/video/320k_iframe.m3u8?nobumpers=true&uniqueId=76011e2b"
|
|
||||||
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=350933,PROGRAM-ID=1,CODECS="avc1.42c015",RESOLUTION=512x288,URI="/videos/BorisHesser_2018S/video/450k_iframe.m3u8?nobumpers=true&uniqueId=76011e2b"
|
|
||||||
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=495850,PROGRAM-ID=1,CODECS="avc1.42c01e",RESOLUTION=640x360,URI="/videos/BorisHesser_2018S/video/600k_iframe.m3u8?nobumpers=true&uniqueId=76011e2b"
|
|
||||||
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=810750,PROGRAM-ID=1,CODECS="avc1.4d401f",RESOLUTION=853x480,URI="/videos/BorisHesser_2018S/video/950k_iframe.m3u8?nobumpers=true&uniqueId=76011e2b"
|
|
||||||
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=1273700,PROGRAM-ID=1,CODECS="avc1.640028",RESOLUTION=1280x720,URI="/videos/BorisHesser_2018S/video/1500k_iframe.m3u8?nobumpers=true&uniqueId=76011e2b"
|
|
||||||
|
|
||||||
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="600k",LANGUAGE="en",NAME="Audio",AUTOSELECT=YES,DEFAULT=YES,URI="/videos/BorisHesser_2018S/audio/600k.m3u8?nobumpers=true&uniqueId=76011e2b",BANDWIDTH=614400
|
|
13
test/testdata/m3u8/toggle_mobile_12211.m3u8
vendored
13
test/testdata/m3u8/toggle_mobile_12211.m3u8
vendored
|
@ -1,13 +0,0 @@
|
||||||
#EXTM3U
|
|
||||||
#EXT-X-VERSION:4
|
|
||||||
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",LANGUAGE="eng",NAME="English",URI="http://k.toggle.sg/fhls/p/2082311/sp/208231100/serveFlavor/entryId/0_89q6e8ku/v/2/pv/1/flavorId/0_sa2ntrdg/name/a.mp4/index.m3u8"
|
|
||||||
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",LANGUAGE="und",NAME="Undefined",URI="http://k.toggle.sg/fhls/p/2082311/sp/208231100/serveFlavor/entryId/0_89q6e8ku/v/2/pv/1/flavorId/0_r7y0nitg/name/a.mp4/index.m3u8"
|
|
||||||
|
|
||||||
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=155648,RESOLUTION=320x180,AUDIO="audio"
|
|
||||||
http://k.toggle.sg/fhls/p/2082311/sp/208231100/serveFlavor/entryId/0_89q6e8ku/v/2/pv/1/flavorId/0_qlk9hlzr/name/a.mp4/index.m3u8
|
|
||||||
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=502784,RESOLUTION=480x270,AUDIO="audio"
|
|
||||||
http://k.toggle.sg/fhls/p/2082311/sp/208231100/serveFlavor/entryId/0_89q6e8ku/v/2/pv/1/flavorId/0_oefackmi/name/a.mp4/index.m3u8
|
|
||||||
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=827392,RESOLUTION=640x360,AUDIO="audio"
|
|
||||||
http://k.toggle.sg/fhls/p/2082311/sp/208231100/serveFlavor/entryId/0_89q6e8ku/v/12/pv/1/flavorId/0_vyg9pj7k/name/a.mp4/index.m3u8
|
|
||||||
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1396736,RESOLUTION=854x480,AUDIO="audio"
|
|
||||||
http://k.toggle.sg/fhls/p/2082311/sp/208231100/serveFlavor/entryId/0_89q6e8ku/v/12/pv/1/flavorId/0_50n4psvx/name/a.mp4/index.m3u8
|
|
20
test/testdata/m3u8/twitch_vod.m3u8
vendored
20
test/testdata/m3u8/twitch_vod.m3u8
vendored
|
@ -1,20 +0,0 @@
|
||||||
#EXTM3U
|
|
||||||
#EXT-X-TWITCH-INFO:ORIGIN="s3",CLUSTER="edgecast_vod",REGION="EU",MANIFEST-CLUSTER="edgecast_vod",USER-IP="109.171.17.81"
|
|
||||||
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="chunked",NAME="Source",AUTOSELECT=YES,DEFAULT=YES
|
|
||||||
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=3214134,CODECS="avc1.100.31,mp4a.40.2",RESOLUTION="1280x720",VIDEO="chunked"
|
|
||||||
https://vod.edgecast.hls.ttvnw.net/e5da31ab49_riotgames_15001215120_261543898/chunked/index-muted-HM49I092CC.m3u8
|
|
||||||
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="high",NAME="High",AUTOSELECT=YES,DEFAULT=YES
|
|
||||||
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1603789,CODECS="avc1.42C01F,mp4a.40.2",RESOLUTION="1280x720",VIDEO="high"
|
|
||||||
https://vod.edgecast.hls.ttvnw.net/e5da31ab49_riotgames_15001215120_261543898/high/index-muted-HM49I092CC.m3u8
|
|
||||||
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="medium",NAME="Medium",AUTOSELECT=YES,DEFAULT=YES
|
|
||||||
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=893387,CODECS="avc1.42C01E,mp4a.40.2",RESOLUTION="852x480",VIDEO="medium"
|
|
||||||
https://vod.edgecast.hls.ttvnw.net/e5da31ab49_riotgames_15001215120_261543898/medium/index-muted-HM49I092CC.m3u8
|
|
||||||
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="low",NAME="Low",AUTOSELECT=YES,DEFAULT=YES
|
|
||||||
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=628347,CODECS="avc1.42C01E,mp4a.40.2",RESOLUTION="640x360",VIDEO="low"
|
|
||||||
https://vod.edgecast.hls.ttvnw.net/e5da31ab49_riotgames_15001215120_261543898/low/index-muted-HM49I092CC.m3u8
|
|
||||||
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="mobile",NAME="Mobile",AUTOSELECT=YES,DEFAULT=YES
|
|
||||||
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=280474,CODECS="avc1.42C00D,mp4a.40.2",RESOLUTION="400x226",VIDEO="mobile"
|
|
||||||
https://vod.edgecast.hls.ttvnw.net/e5da31ab49_riotgames_15001215120_261543898/mobile/index-muted-HM49I092CC.m3u8
|
|
||||||
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="audio_only",NAME="Audio Only",AUTOSELECT=NO,DEFAULT=NO
|
|
||||||
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=182725,CODECS="mp4a.40.2",VIDEO="audio_only"
|
|
||||||
https://vod.edgecast.hls.ttvnw.net/e5da31ab49_riotgames_15001215120_261543898/audio_only/index-muted-HM49I092CC.m3u8
|
|
10
test/testdata/m3u8/vidio.m3u8
vendored
10
test/testdata/m3u8/vidio.m3u8
vendored
|
@ -1,10 +0,0 @@
|
||||||
#EXTM3U
|
|
||||||
|
|
||||||
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=300000,RESOLUTION=480x270,NAME="270p 3G"
|
|
||||||
https://cdn1-a.production.vidio.static6.com/uploads/165683/dj_ambred-4383-b300.mp4.m3u8
|
|
||||||
|
|
||||||
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=600000,RESOLUTION=640x360,NAME="360p SD"
|
|
||||||
https://cdn1-a.production.vidio.static6.com/uploads/165683/dj_ambred-4383-b600.mp4.m3u8
|
|
||||||
|
|
||||||
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1200000,RESOLUTION=1280x720,NAME="720p HD"
|
|
||||||
https://cdn1-a.production.vidio.static6.com/uploads/165683/dj_ambred-4383-b1200.mp4.m3u8
|
|
|
@ -364,7 +364,7 @@ class YoutubeDL(object):
|
||||||
nopart, updatetime, buffersize, ratelimit, min_filesize, max_filesize, test,
|
nopart, updatetime, buffersize, ratelimit, min_filesize, max_filesize, test,
|
||||||
noresizebuffer, retries, continuedl, noprogress, consoletitle,
|
noresizebuffer, retries, continuedl, noprogress, consoletitle,
|
||||||
xattr_set_filesize, external_downloader_args, hls_use_mpegts,
|
xattr_set_filesize, external_downloader_args, hls_use_mpegts,
|
||||||
http_chunk_size.
|
hls_split_discontinuity, http_chunk_size.
|
||||||
|
|
||||||
The following options are used by the post processors:
|
The following options are used by the post processors:
|
||||||
prefer_ffmpeg: If False, use avconv instead of ffmpeg if both are available,
|
prefer_ffmpeg: If False, use avconv instead of ffmpeg if both are available,
|
||||||
|
|
|
@ -536,6 +536,7 @@ def report_args_compat(arg, name):
|
||||||
'ffmpeg_location': opts.ffmpeg_location,
|
'ffmpeg_location': opts.ffmpeg_location,
|
||||||
'hls_prefer_native': opts.hls_prefer_native,
|
'hls_prefer_native': opts.hls_prefer_native,
|
||||||
'hls_use_mpegts': opts.hls_use_mpegts,
|
'hls_use_mpegts': opts.hls_use_mpegts,
|
||||||
|
'hls_split_discontinuity': opts.hls_split_discontinuity,
|
||||||
'external_downloader_args': opts.external_downloader_args,
|
'external_downloader_args': opts.external_downloader_args,
|
||||||
'postprocessor_args': opts.postprocessor_args,
|
'postprocessor_args': opts.postprocessor_args,
|
||||||
'cn_verification_proxy': opts.cn_verification_proxy,
|
'cn_verification_proxy': opts.cn_verification_proxy,
|
||||||
|
|
|
@ -43,7 +43,6 @@ def can_download(manifest, info_dict, allow_unplayable_formats=False, with_crypt
|
||||||
# r'#EXT-X-PLAYLIST-TYPE:EVENT', # media segments may be appended to the end of
|
# r'#EXT-X-PLAYLIST-TYPE:EVENT', # media segments may be appended to the end of
|
||||||
# # event media playlists [4]
|
# # event media playlists [4]
|
||||||
# r'#EXT-X-MAP:', # media initialization [5]
|
# r'#EXT-X-MAP:', # media initialization [5]
|
||||||
r'^\s*(?:[^#\s]|#EXT-X-MAP:).+?\n\s*#EXT-X-MAP:', # media initialization [5]
|
|
||||||
# 1. https://tools.ietf.org/html/draft-pantos-http-live-streaming-17#section-4.3.2.4
|
# 1. https://tools.ietf.org/html/draft-pantos-http-live-streaming-17#section-4.3.2.4
|
||||||
# 2. https://tools.ietf.org/html/draft-pantos-http-live-streaming-17#section-4.3.2.2
|
# 2. https://tools.ietf.org/html/draft-pantos-http-live-streaming-17#section-4.3.2.2
|
||||||
# 3. https://tools.ietf.org/html/draft-pantos-http-live-streaming-17#section-4.3.3.2
|
# 3. https://tools.ietf.org/html/draft-pantos-http-live-streaming-17#section-4.3.3.2
|
||||||
|
@ -129,6 +128,7 @@ def is_ad_fragment_end(s):
|
||||||
skip_unavailable_fragments = self.params.get('skip_unavailable_fragments', True)
|
skip_unavailable_fragments = self.params.get('skip_unavailable_fragments', True)
|
||||||
test = self.params.get('test', False)
|
test = self.params.get('test', False)
|
||||||
|
|
||||||
|
format_index = info_dict.get('format_index')
|
||||||
extra_query = None
|
extra_query = None
|
||||||
extra_param_to_segment_url = info_dict.get('extra_param_to_segment_url')
|
extra_param_to_segment_url = info_dict.get('extra_param_to_segment_url')
|
||||||
if extra_param_to_segment_url:
|
if extra_param_to_segment_url:
|
||||||
|
@ -138,6 +138,7 @@ def is_ad_fragment_end(s):
|
||||||
decrypt_info = {'METHOD': 'NONE'}
|
decrypt_info = {'METHOD': 'NONE'}
|
||||||
key_list = []
|
key_list = []
|
||||||
byte_range = {}
|
byte_range = {}
|
||||||
|
discontinuity_count = 0
|
||||||
frag_index = 0
|
frag_index = 0
|
||||||
ad_frag_next = False
|
ad_frag_next = False
|
||||||
for line in s.splitlines():
|
for line in s.splitlines():
|
||||||
|
@ -145,6 +146,8 @@ def is_ad_fragment_end(s):
|
||||||
download_frag = False
|
download_frag = False
|
||||||
if line:
|
if line:
|
||||||
if not line.startswith('#'):
|
if not line.startswith('#'):
|
||||||
|
if format_index and discontinuity_count != format_index:
|
||||||
|
continue
|
||||||
if ad_frag_next:
|
if ad_frag_next:
|
||||||
continue
|
continue
|
||||||
frag_index += 1
|
frag_index += 1
|
||||||
|
@ -163,6 +166,8 @@ def is_ad_fragment_end(s):
|
||||||
download_frag = True
|
download_frag = True
|
||||||
|
|
||||||
elif line.startswith('#EXT-X-MAP'):
|
elif line.startswith('#EXT-X-MAP'):
|
||||||
|
if format_index and discontinuity_count != format_index:
|
||||||
|
continue
|
||||||
if frag_index > 0:
|
if frag_index > 0:
|
||||||
self.report_error(
|
self.report_error(
|
||||||
'initialization fragment found after media fragments, unable to download')
|
'initialization fragment found after media fragments, unable to download')
|
||||||
|
@ -218,6 +223,8 @@ def is_ad_fragment_end(s):
|
||||||
ad_frag_next = True
|
ad_frag_next = True
|
||||||
elif is_ad_fragment_end(line):
|
elif is_ad_fragment_end(line):
|
||||||
ad_frag_next = False
|
ad_frag_next = False
|
||||||
|
elif line.startswith('#EXT-X-DISCONTINUITY'):
|
||||||
|
discontinuity_count += 1
|
||||||
|
|
||||||
if download_frag:
|
if download_frag:
|
||||||
count = 0
|
count = 0
|
||||||
|
|
|
@ -1833,9 +1833,8 @@ def _m3u8_meta_format(self, m3u8_url, ext=None, preference=None, quality=None, m
|
||||||
|
|
||||||
def _extract_m3u8_formats(self, m3u8_url, video_id, ext=None,
|
def _extract_m3u8_formats(self, m3u8_url, video_id, ext=None,
|
||||||
entry_protocol='m3u8', preference=None, quality=None,
|
entry_protocol='m3u8', preference=None, quality=None,
|
||||||
m3u8_id=None, note=None, errnote=None,
|
m3u8_id=None, live=False, note=None, errnote=None,
|
||||||
fatal=True, live=False, data=None, headers={},
|
fatal=True, data=None, headers={}, query={}):
|
||||||
query={}):
|
|
||||||
res = self._download_webpage_handle(
|
res = self._download_webpage_handle(
|
||||||
m3u8_url, video_id,
|
m3u8_url, video_id,
|
||||||
note=note or 'Downloading m3u8 information',
|
note=note or 'Downloading m3u8 information',
|
||||||
|
@ -1850,11 +1849,14 @@ def _extract_m3u8_formats(self, m3u8_url, video_id, ext=None,
|
||||||
|
|
||||||
return self._parse_m3u8_formats(
|
return self._parse_m3u8_formats(
|
||||||
m3u8_doc, m3u8_url, ext=ext, entry_protocol=entry_protocol,
|
m3u8_doc, m3u8_url, ext=ext, entry_protocol=entry_protocol,
|
||||||
preference=preference, quality=quality, m3u8_id=m3u8_id, live=live)
|
preference=preference, quality=quality, m3u8_id=m3u8_id,
|
||||||
|
note=note, errnote=errnote, fatal=fatal, live=live, data=data,
|
||||||
|
headers=headers, query=query, video_id=video_id)
|
||||||
|
|
||||||
def _parse_m3u8_formats(self, m3u8_doc, m3u8_url, ext=None,
|
def _parse_m3u8_formats(self, m3u8_doc, m3u8_url, ext=None,
|
||||||
entry_protocol='m3u8', preference=None, quality=None,
|
entry_protocol='m3u8', preference=None, quality=None,
|
||||||
m3u8_id=None, live=False):
|
m3u8_id=None, live=False, note=None, errnote=None,
|
||||||
|
fatal=True, data=None, headers={}, query={}, video_id=None):
|
||||||
if '#EXT-X-FAXS-CM:' in m3u8_doc: # Adobe Flash Access
|
if '#EXT-X-FAXS-CM:' in m3u8_doc: # Adobe Flash Access
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
@ -1868,6 +1870,8 @@ def _parse_m3u8_formats(self, m3u8_doc, m3u8_url, ext=None,
|
||||||
if re.match(r'^https?://', u)
|
if re.match(r'^https?://', u)
|
||||||
else compat_urlparse.urljoin(m3u8_url, u))
|
else compat_urlparse.urljoin(m3u8_url, u))
|
||||||
|
|
||||||
|
split_discontinuity = self._downloader.params.get('hls_split_discontinuity', False)
|
||||||
|
|
||||||
# References:
|
# References:
|
||||||
# 1. https://tools.ietf.org/html/draft-pantos-http-live-streaming-21
|
# 1. https://tools.ietf.org/html/draft-pantos-http-live-streaming-21
|
||||||
# 2. https://github.com/ytdl-org/youtube-dl/issues/12211
|
# 2. https://github.com/ytdl-org/youtube-dl/issues/12211
|
||||||
|
@ -1884,15 +1888,67 @@ def _parse_m3u8_formats(self, m3u8_doc, m3u8_url, ext=None,
|
||||||
# media playlist and MUST NOT appear in master playlist thus we can
|
# media playlist and MUST NOT appear in master playlist thus we can
|
||||||
# clearly detect media playlist with this criterion.
|
# clearly detect media playlist with this criterion.
|
||||||
|
|
||||||
|
def _extract_m3u8_playlist_formats(format_url, m3u8_doc=None):
|
||||||
|
if not m3u8_doc:
|
||||||
|
res = self._download_webpage_handle(
|
||||||
|
format_url, video_id,
|
||||||
|
note=False,
|
||||||
|
errnote=errnote or 'Failed to download m3u8 playlist information',
|
||||||
|
fatal=fatal, data=data, headers=headers, query=query)
|
||||||
|
|
||||||
|
if res is False:
|
||||||
|
return []
|
||||||
|
|
||||||
|
m3u8_doc, urlh = res
|
||||||
|
format_url = urlh.geturl()
|
||||||
|
|
||||||
|
playlist_formats = []
|
||||||
|
i = (
|
||||||
|
0
|
||||||
|
if split_discontinuity
|
||||||
|
else None)
|
||||||
|
format_info = {
|
||||||
|
'index': i,
|
||||||
|
'key_data': None,
|
||||||
|
'files': [],
|
||||||
|
}
|
||||||
|
for line in m3u8_doc.splitlines():
|
||||||
|
if not line.startswith('#'):
|
||||||
|
format_info['files'].append(line)
|
||||||
|
elif split_discontinuity and line.startswith('#EXT-X-DISCONTINUITY'):
|
||||||
|
i += 1
|
||||||
|
playlist_formats.append(format_info)
|
||||||
|
format_info = {
|
||||||
|
'index': i,
|
||||||
|
'url': format_url,
|
||||||
|
'files': [],
|
||||||
|
}
|
||||||
|
playlist_formats.append(format_info)
|
||||||
|
return playlist_formats
|
||||||
|
|
||||||
if '#EXT-X-TARGETDURATION' in m3u8_doc: # media playlist, return as is
|
if '#EXT-X-TARGETDURATION' in m3u8_doc: # media playlist, return as is
|
||||||
return [{
|
|
||||||
|
playlist_formats = _extract_m3u8_playlist_formats(m3u8_doc, True)
|
||||||
|
|
||||||
|
for format in playlist_formats:
|
||||||
|
format_id = []
|
||||||
|
if m3u8_id:
|
||||||
|
format_id.append(m3u8_id)
|
||||||
|
format_index = format.get('index')
|
||||||
|
if format_index:
|
||||||
|
format_id.append(str(format_index))
|
||||||
|
f = {
|
||||||
|
'format_id': '-'.join(format_id),
|
||||||
|
'format_index': format_index,
|
||||||
'url': m3u8_url,
|
'url': m3u8_url,
|
||||||
'format_id': m3u8_id,
|
|
||||||
'ext': ext,
|
'ext': ext,
|
||||||
'protocol': entry_protocol,
|
'protocol': entry_protocol,
|
||||||
'preference': preference,
|
'preference': preference,
|
||||||
'quality': quality,
|
'quality': quality,
|
||||||
}]
|
}
|
||||||
|
formats.append(f)
|
||||||
|
|
||||||
|
return formats
|
||||||
|
|
||||||
groups = {}
|
groups = {}
|
||||||
last_stream_inf = {}
|
last_stream_inf = {}
|
||||||
|
@ -1908,13 +1964,21 @@ def extract_media(x_media_line):
|
||||||
return
|
return
|
||||||
media_url = media.get('URI')
|
media_url = media.get('URI')
|
||||||
if media_url:
|
if media_url:
|
||||||
|
manifest_url = format_url(media_url)
|
||||||
format_id = []
|
format_id = []
|
||||||
|
playlist_formats = _extract_m3u8_playlist_formats(manifest_url)
|
||||||
|
|
||||||
|
for format in playlist_formats:
|
||||||
|
format_index = format.get('index')
|
||||||
for v in (m3u8_id, group_id, name):
|
for v in (m3u8_id, group_id, name):
|
||||||
if v:
|
if v:
|
||||||
format_id.append(v)
|
format_id.append(v)
|
||||||
|
if format_index:
|
||||||
|
format_id.append(str(format_index))
|
||||||
f = {
|
f = {
|
||||||
'format_id': '-'.join(format_id),
|
'format_id': '-'.join(format_id),
|
||||||
'url': format_url(media_url),
|
'format_index': format_index,
|
||||||
|
'url': manifest_url,
|
||||||
'manifest_url': m3u8_url,
|
'manifest_url': m3u8_url,
|
||||||
'language': media.get('LANGUAGE'),
|
'language': media.get('LANGUAGE'),
|
||||||
'ext': ext,
|
'ext': ext,
|
||||||
|
@ -1961,18 +2025,26 @@ def build_stream_name():
|
||||||
tbr = float_or_none(
|
tbr = float_or_none(
|
||||||
last_stream_inf.get('AVERAGE-BANDWIDTH')
|
last_stream_inf.get('AVERAGE-BANDWIDTH')
|
||||||
or last_stream_inf.get('BANDWIDTH'), scale=1000)
|
or last_stream_inf.get('BANDWIDTH'), scale=1000)
|
||||||
|
manifest_url = format_url(line.strip())
|
||||||
|
|
||||||
|
playlist_formats = _extract_m3u8_playlist_formats(manifest_url)
|
||||||
|
|
||||||
|
for format in playlist_formats:
|
||||||
format_id = []
|
format_id = []
|
||||||
if m3u8_id:
|
if m3u8_id:
|
||||||
format_id.append(m3u8_id)
|
format_id.append(m3u8_id)
|
||||||
|
format_index = format.get('index')
|
||||||
stream_name = build_stream_name()
|
stream_name = build_stream_name()
|
||||||
# Bandwidth of live streams may differ over time thus making
|
# Bandwidth of live streams may differ over time thus making
|
||||||
# format_id unpredictable. So it's better to keep provided
|
# format_id unpredictable. So it's better to keep provided
|
||||||
# format_id intact.
|
# format_id intact.
|
||||||
if not live:
|
if not live:
|
||||||
format_id.append(stream_name if stream_name else '%d' % (tbr if tbr else len(formats)))
|
format_id.append(stream_name if stream_name else '%d' % (tbr if tbr else len(formats)))
|
||||||
manifest_url = format_url(line.strip())
|
if format_index:
|
||||||
|
format_id.append(str(format_index))
|
||||||
f = {
|
f = {
|
||||||
'format_id': '-'.join(format_id),
|
'format_id': '-'.join(format_id),
|
||||||
|
'format_index': format_index,
|
||||||
'url': manifest_url,
|
'url': manifest_url,
|
||||||
'manifest_url': m3u8_url,
|
'manifest_url': m3u8_url,
|
||||||
'tbr': tbr,
|
'tbr': tbr,
|
||||||
|
|
|
@ -1226,6 +1226,15 @@ def _dict_from_multiple_values_options_callback(
|
||||||
'--ignore-dynamic-mpd', '--no-allow-dynamic-mpd',
|
'--ignore-dynamic-mpd', '--no-allow-dynamic-mpd',
|
||||||
action='store_false', dest='dynamic_mpd',
|
action='store_false', dest='dynamic_mpd',
|
||||||
help='Do not process dynamic DASH manifests (Alias: --no-allow-dynamic-mpd)')
|
help='Do not process dynamic DASH manifests (Alias: --no-allow-dynamic-mpd)')
|
||||||
|
extractor.add_option(
|
||||||
|
'--hls-split-discontinuity',
|
||||||
|
dest='hls_split_discontinuity', action='store_true', default=False,
|
||||||
|
help='Split HLS playlists to different formats at discontinuities such as ad breaks'
|
||||||
|
)
|
||||||
|
extractor.add_option(
|
||||||
|
'--no-hls-split-discontinuity',
|
||||||
|
dest='hls_split_discontinuity', action='store_false',
|
||||||
|
help='Do not split HLS playlists to different formats at discontinuities such as ad breaks (default)')
|
||||||
|
|
||||||
parser.add_option_group(general)
|
parser.add_option_group(general)
|
||||||
parser.add_option_group(network)
|
parser.add_option_group(network)
|
||||||
|
|
Loading…
Reference in a new issue