@ -3,12 +3,13 @@
from __future__ import unicode_literals
# Allow direct execution
import io
import os
import sys
import unittest
sys . path . insert ( 0 , os . path . dirname ( os . path . dirname ( os . path . abspath ( __file__ ) ) ) )
from test.helper import FakeYDL , expect_dict
from test.helper import FakeYDL , expect_dict , expect_value
from youtube_dl.extractor.common import InfoExtractor
from youtube_dl.extractor import YoutubeIE , get_info_extractor
from youtube_dl.utils import encode_data_uri , strip_jsonp , ExtractorError , RegexNotFoundError
@ -175,6 +176,311 @@ jwplayer("mediaplayer").setup({"abouttext":"Visit Indie DB","aboutlink":"http:\/
} ]
} )
def test_parse_m3u8_formats ( self ) :
_TEST_CASES = [
(
# https://github.com/rg3/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 %2F 16 %2F 156589847-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/master.m3u8?caption=2017 %2F 16 %2F 156589847-1492488987.m3u8 % 3Afra % 3AFrancais&audiotrack=0 % 3Afra % 3AFrancais ' ,
' ext ' : ' mp4 ' ,
' format_id ' : ' meta ' ,
' format_note ' : ' Quality selection URL ' ,
' protocol ' : ' m3u8 ' ,
' preference ' : - 100 ,
' resolution ' : ' multiple '
} , {
' 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/index_0_av.m3u8?null=0 ' ,
' 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/index_1_av.m3u8?null=0 ' ,
' 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/index_2_av.m3u8?null=0 ' ,
' 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/index_3_av.m3u8?null=0 ' ,
' 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/index_4_av.m3u8?null=0 ' ,
' ext ' : ' mp4 ' ,
' protocol ' : ' m3u8 ' ,
' format_id ' : ' 1467 ' ,
' acodec ' : ' mp4a.40.2 ' ,
' vcodec ' : ' avc1.77.30 ' ,
' tbr ' : 1467 ,
' width ' : 1024 ,
' height ' : 576 ,
} ]
) ,
(
# https://github.com/rg3/youtube-dl/issues/11995
# http://teamcoco.com/video/clueless-gamer-super-bowl-for-honor
' teamcoco_11995 ' ,
' http://ak.storage-w.teamcococdn.com/cdn/2017-02/98599/ed8f/main.m3u8 ' ,
[ {
' url ' : ' http://ak.storage-w.teamcococdn.com/cdn/2017-02/98599/ed8f/main.m3u8 ' ,
' ext ' : ' mp4 ' ,
' format_id ' : ' meta ' ,
' format_note ' : ' Quality selection URL ' ,
' protocol ' : ' m3u8 ' ,
' preference ' : - 100 ,
' resolution ' : ' multiple ' ,
} , {
' url ' : ' http://ak.storage-w.teamcococdn.com/cdn/2017-02/98599/ed8f/hls/CONAN_020217_Highlight_show-audio-160k_v4.m3u8 ' ,
' ext ' : ' mp4 ' ,
' format_id ' : ' audio-0-Default ' ,
' protocol ' : ' m3u8 ' ,
' vcodec ' : ' none ' ,
} , {
' url ' : ' http://ak.storage-w.teamcococdn.com/cdn/2017-02/98599/ed8f/hls/CONAN_020217_Highlight_show-audio-64k_v4.m3u8 ' ,
' ext ' : ' mp4 ' ,
' format_id ' : ' audio-1-Default ' ,
' protocol ' : ' m3u8 ' ,
' vcodec ' : ' none ' ,
} , {
' url ' : ' http://ak.storage-w.teamcococdn.com/cdn/2017-02/98599/ed8f/hls/CONAN_020217_Highlight_show-audio-64k_v4.m3u8 ' ,
' manifest_url ' : ' http://ak.storage-w.teamcococdn.com/cdn/2017-02/98599/ed8f/hls/CONAN_020217_Highlight_show-audio-64k_v4.m3u8 ' ,
' ext ' : ' mp4 ' ,
' format_id ' : ' 71 ' ,
' protocol ' : ' m3u8 ' ,
' acodec ' : ' mp4a.40.5 ' ,
' vcodec ' : ' none ' ,
' tbr ' : 71 ,
} , {
' 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/hls/CONAN_020217_Highlight_show-400k_v4.m3u8 ' ,
' ext ' : ' mp4 ' ,
' format_id ' : ' 413 ' ,
' 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/hls/CONAN_020217_Highlight_show-400k_v4.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/hls/CONAN_020217_Highlight_show-1m_v4.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/hls/CONAN_020217_Highlight_show-2m_v4.m3u8 ' ,
' ext ' : ' mp4 ' ,
' format_id ' : ' 2374 ' ,
' protocol ' : ' m3u8 ' ,
' acodec ' : ' none ' ,
' vcodec ' : ' avc1.4d001f ' ,
' tbr ' : 2374 ,
' width ' : 1024 ,
' height ' : 576 ,
} ]
) ,
(
# https://github.com/rg3/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://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 ' : ' meta ' ,
' format_note ' : ' Quality selection URL ' ,
' protocol ' : ' m3u8 ' ,
' preference ' : - 100 ,
' resolution ' : ' multiple '
} , {
' 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 ' ,
' 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 ' ,
' 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://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 ' : ' mp4 ' ,
' format_id ' : ' 155 ' ,
' protocol ' : ' m3u8 ' ,
' tbr ' : 155 ,
' 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://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 ' : ' mp4 ' ,
' format_id ' : ' 502 ' ,
' protocol ' : ' m3u8 ' ,
' tbr ' : 502 ,
' width ' : 480 ,
' height ' : 270 ,
} , {
' 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 ' ,
' manifest_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 ' ,
' ext ' : ' mp4 ' ,
' format_id ' : ' 827 ' ,
' protocol ' : ' m3u8 ' ,
' tbr ' : 827 ,
' 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://k.toggle.sg/fhls/p/2082311/sp/208231100/serveFlavor/entryId/0_89q6e8ku/v/12/pv/1/flavorId/0_50n4psvx/name/a.mp4/index.m3u8 ' ,
' ext ' : ' mp4 ' ,
' format_id ' : ' 1396 ' ,
' protocol ' : ' m3u8 ' ,
' tbr ' : 1396 ,
' 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 %22u ser_id %22% 3Anull % 2C % 22vod_id %22% 3A6528877 % 2C %22e xpires %22% 3A1492887874 % 2C %22c hansub %22% 3A % 7B %22r estricted_bitrates %22% 3A % 5B % 5D % 7D % 2C % 22privileged %22% 3Afalse % 2C % 22https_required %22% 3Afalse % 7D&nauthsig=3e29296a6824a0f48f9e731383f77a614fc79bee ' ,
[ {
' url ' : ' https://usher.ttvnw.net/vod/6528877?allow_source=true&allow_audio_only=true&allow_spectre=true&player=twitchweb&nauth= % 7B %22u ser_id %22% 3Anull % 2C % 22vod_id %22% 3A6528877 % 2C %22e xpires %22% 3A1492887874 % 2C %22c hansub %22% 3A % 7B %22r estricted_bitrates %22% 3A % 5B % 5D % 7D % 2C % 22privileged %22% 3Afalse % 2C % 22https_required %22% 3Afalse % 7D&nauthsig=3e29296a6824a0f48f9e731383f77a614fc79bee ' ,
' ext ' : ' mp4 ' ,
' format_id ' : ' meta ' ,
' format_note ' : ' Quality selection URL ' ,
' protocol ' : ' m3u8 ' ,
' preference ' : - 100 ,
' resolution ' : ' multiple '
} , {
' url ' : ' https://vod.edgecast.hls.ttvnw.net/e5da31ab49_riotgames_15001215120_261543898/audio_only/index-muted-HM49I092CC.m3u8 ' ,
' manifest_url ' : ' https://vod.edgecast.hls.ttvnw.net/e5da31ab49_riotgames_15001215120_261543898/audio_only/index-muted-HM49I092CC.m3u8 ' ,
' ext ' : ' mp4 ' ,
' format_id ' : ' Audio Only ' ,
' protocol ' : ' m3u8 ' ,
' acodec ' : ' mp4a.40.2 ' ,
' vcodec ' : ' none ' ,
' tbr ' : 182 ,
} , {
' url ' : ' https://vod.edgecast.hls.ttvnw.net/e5da31ab49_riotgames_15001215120_261543898/mobile/index-muted-HM49I092CC.m3u8 ' ,
' manifest_url ' : ' https://vod.edgecast.hls.ttvnw.net/e5da31ab49_riotgames_15001215120_261543898/mobile/index-muted-HM49I092CC.m3u8 ' ,
' ext ' : ' mp4 ' ,
' format_id ' : ' Mobile ' ,
' protocol ' : ' m3u8 ' ,
' acodec ' : ' mp4a.40.2 ' ,
' vcodec ' : ' avc1.42C00D ' ,
' tbr ' : 280 ,
' width ' : 400 ,
' height ' : 226 ,
} , {
' url ' : ' https://vod.edgecast.hls.ttvnw.net/e5da31ab49_riotgames_15001215120_261543898/low/index-muted-HM49I092CC.m3u8 ' ,
' manifest_url ' : ' https://vod.edgecast.hls.ttvnw.net/e5da31ab49_riotgames_15001215120_261543898/low/index-muted-HM49I092CC.m3u8 ' ,
' ext ' : ' mp4 ' ,
' format_id ' : ' Low ' ,
' protocol ' : ' m3u8 ' ,
' acodec ' : ' mp4a.40.2 ' ,
' vcodec ' : ' avc1.42C01E ' ,
' tbr ' : 628 ,
' width ' : 640 ,
' height ' : 360 ,
} , {
' url ' : ' https://vod.edgecast.hls.ttvnw.net/e5da31ab49_riotgames_15001215120_261543898/medium/index-muted-HM49I092CC.m3u8 ' ,
' manifest_url ' : ' https://vod.edgecast.hls.ttvnw.net/e5da31ab49_riotgames_15001215120_261543898/medium/index-muted-HM49I092CC.m3u8 ' ,
' ext ' : ' mp4 ' ,
' format_id ' : ' Medium ' ,
' protocol ' : ' m3u8 ' ,
' acodec ' : ' mp4a.40.2 ' ,
' vcodec ' : ' avc1.42C01E ' ,
' tbr ' : 893 ,
' width ' : 852 ,
' height ' : 480 ,
} , {
' url ' : ' https://vod.edgecast.hls.ttvnw.net/e5da31ab49_riotgames_15001215120_261543898/high/index-muted-HM49I092CC.m3u8 ' ,
' manifest_url ' : ' https://vod.edgecast.hls.ttvnw.net/e5da31ab49_riotgames_15001215120_261543898/high/index-muted-HM49I092CC.m3u8 ' ,
' ext ' : ' mp4 ' ,
' format_id ' : ' High ' ,
' protocol ' : ' m3u8 ' ,
' acodec ' : ' mp4a.40.2 ' ,
' vcodec ' : ' avc1.42C01F ' ,
' tbr ' : 1603 ,
' width ' : 1280 ,
' height ' : 720 ,
} , {
' url ' : ' https://vod.edgecast.hls.ttvnw.net/e5da31ab49_riotgames_15001215120_261543898/chunked/index-muted-HM49I092CC.m3u8 ' ,
' manifest_url ' : ' https://vod.edgecast.hls.ttvnw.net/e5da31ab49_riotgames_15001215120_261543898/chunked/index-muted-HM49I092CC.m3u8 ' ,
' ext ' : ' mp4 ' ,
' format_id ' : ' Source ' ,
' protocol ' : ' m3u8 ' ,
' acodec ' : ' mp4a.40.2 ' ,
' vcodec ' : ' avc1.100.31 ' ,
' tbr ' : 3214 ,
' width ' : 1280 ,
' height ' : 720 ,
} ]
)
]
for m3u8_file , m3u8_url , expected_formats in _TEST_CASES :
with io . open ( ' ./test/testdata/m3u8/ %s .m3u8 ' % m3u8_file ,
mode = ' r ' , encoding = ' utf-8 ' ) as f :
formats = self . ie . _parse_m3u8_formats (
f . read ( ) , m3u8_url , ext = ' mp4 ' )
self . ie . _sort_formats ( formats )
expect_value ( self , formats , expected_formats , None )
if __name__ == ' __main__ ' :
unittest . main ( )