2015-04-04 10:19:28 -07:00
# coding: utf-8
2014-06-27 06:53:59 -07:00
from __future__ import unicode_literals
2015-05-23 12:21:18 -07:00
from . common import InfoExtractor
from . . utils import (
ExtractorError ,
2016-09-02 09:02:15 -07:00
int_or_none ,
float_or_none ,
mimetype2ext ,
2015-05-23 12:21:18 -07:00
parse_iso8601 ,
2016-09-02 05:48:56 -07:00
remove_end ,
2017-02-03 23:38:28 -08:00
update_url_query ,
2015-05-23 12:21:18 -07:00
)
2014-06-27 06:53:59 -07:00
2015-02-18 08:20:22 -08:00
class DRTVIE ( InfoExtractor ) :
2017-02-03 23:38:28 -08:00
_VALID_URL = r ' https?://(?:www \ .)?dr \ .dk/(?:tv/se|nyheder|radio/ondemand)/(?:[^/]+/)*(?P<id>[ \ da-z-]+)(?:[/#?]|$) '
2017-03-05 12:23:01 -08:00
_GEO_BYPASS = False
_GEO_COUNTRIES = [ ' DK ' ]
2017-02-03 23:38:28 -08:00
IE_NAME = ' drtv '
2016-09-02 05:48:56 -07:00
_TESTS = [ {
2016-09-02 09:53:17 -07:00
' url ' : ' https://www.dr.dk/tv/se/boern/ultra/klassen-ultra/klassen-darlig-taber-10 ' ,
' md5 ' : ' 25e659cccc9a2ed956110a299fdf5983 ' ,
2014-06-27 06:53:59 -07:00
' info_dict ' : {
2016-09-02 09:53:17 -07:00
' id ' : ' klassen-darlig-taber-10 ' ,
2014-06-27 06:53:59 -07:00
' ext ' : ' mp4 ' ,
2016-09-02 09:53:17 -07:00
' title ' : ' Klassen - Dårlig taber (10) ' ,
' description ' : ' md5:815fe1b7fa656ed80580f31e8b3c79aa ' ,
' timestamp ' : 1471991907 ,
' upload_date ' : ' 20160823 ' ,
' duration ' : 606.84 ,
} ,
' params ' : {
' skip_download ' : True ,
2014-06-27 06:53:59 -07:00
} ,
2016-09-02 05:48:56 -07:00
} , {
' url ' : ' https://www.dr.dk/nyheder/indland/live-christianias-rydning-af-pusher-street-er-i-gang ' ,
2016-09-02 09:53:17 -07:00
' md5 ' : ' 2c37175c718155930f939ef59952474a ' ,
2016-09-02 05:48:56 -07:00
' info_dict ' : {
' id ' : ' christiania-pusher-street-ryddes-drdkrjpo ' ,
' ext ' : ' mp4 ' ,
' title ' : ' LIVE Christianias rydning af Pusher Street er i gang ' ,
' description ' : ' - Det er det fedeste, der er sket i 20 år, fortæller christianit til DR Nyheder. ' ,
' timestamp ' : 1472800279 ,
' upload_date ' : ' 20160902 ' ,
' duration ' : 131.4 ,
2016-09-02 09:53:17 -07:00
} ,
2017-05-07 04:04:23 -07:00
} , {
' url ' : ' https://www.dr.dk/tv/se/historien-om-danmark/-/historien-om-danmark-stenalder ' ,
' md5 ' : ' 7c8ca12e6c3d3e3edd59ba5a9b7ca10a ' ,
' info_dict ' : {
' id ' : ' historien-om-danmark-stenalder ' ,
' ext ' : ' mp4 ' ,
' title ' : ' Historien om Danmark: Stenalder (1) ' ,
' description ' : ' Én fascinerende historie om tusindvis af år, hvor vores land bliver skabt ud af is og vand, og hvor de første danskere ankommer til vores egn. Det bliver en rejse ind i urtiden og det liv, som urtidsjægerne har levet i skovene og ved havet og helt frem til bondestenalderen. Gennem skeletfund afslører eksperter, hvordan vores forfædre har set ud i stenalderen og hvorfor stenaldermennesket byggede de imponerende jættestuer, som ligger overalt i det danske. ' ,
' timestamp ' : 1490401996 ,
' upload_date ' : ' 20170325 ' ,
' duration ' : 3502.04 ,
} ,
2016-09-02 05:48:56 -07:00
} ]
2014-06-27 06:53:59 -07:00
def _real_extract ( self , url ) :
2014-10-29 12:10:00 -07:00
video_id = self . _match_id ( url )
2014-06-27 06:53:59 -07:00
2015-02-02 07:11:25 -08:00
webpage = self . _download_webpage ( url , video_id )
2015-04-04 10:17:09 -07:00
if ' >Programmet er ikke længere tilgængeligt ' in webpage :
raise ExtractorError (
' Video %s is not available ' % video_id , expected = True )
2015-02-02 07:11:25 -08:00
video_id = self . _search_regex (
2016-09-02 05:48:56 -07:00
( r ' data-(?:material-identifier|episode-slug)= " ([^ " ]+) " ' ,
r ' data-resource= " [^> " ]+mu/programcard/expanded/([^ " ]+) " ' ) ,
2015-02-02 07:11:25 -08:00
webpage , ' video id ' )
2014-06-27 06:53:59 -07:00
2015-02-02 07:11:25 -08:00
programcard = self . _download_json (
' http://www.dr.dk/mu/programcard/expanded/ %s ' % video_id ,
video_id , ' Downloading video JSON ' )
2014-06-27 06:53:59 -07:00
data = programcard [ ' Data ' ] [ 0 ]
2016-09-02 09:02:15 -07:00
title = remove_end ( self . _og_search_title (
webpage , default = None ) , ' | TV | DR ' ) or data [ ' Title ' ]
description = self . _og_search_description (
webpage , default = None ) or data . get ( ' Description ' )
2016-09-02 05:48:56 -07:00
2016-09-02 09:02:15 -07:00
timestamp = parse_iso8601 ( data . get ( ' CreatedTime ' ) )
2014-06-27 06:53:59 -07:00
thumbnail = None
duration = None
restricted_to_denmark = False
formats = [ ]
subtitles = { }
for asset in data [ ' Assets ' ] :
2017-02-03 23:38:28 -08:00
kind = asset . get ( ' Kind ' )
if kind == ' Image ' :
2016-09-02 09:02:15 -07:00
thumbnail = asset . get ( ' Uri ' )
2017-05-07 04:04:23 -07:00
preference = 0
sign_language = asset . get ( ' Target ' ) == ' SignLanguage '
if kind in ( ' VideoResource ' , ' AudioResource ' ) :
2016-09-02 09:02:15 -07:00
duration = float_or_none ( asset . get ( ' DurationInMilliseconds ' ) , 1000 )
restricted_to_denmark = asset . get ( ' RestrictedToDenmark ' )
spoken_subtitles = asset . get ( ' Target ' ) == ' SpokenSubtitles '
for link in asset . get ( ' Links ' , [ ] ) :
uri = link . get ( ' Uri ' )
if not uri :
continue
target = link . get ( ' Target ' )
format_id = target or ' '
2015-01-25 09:56:04 -08:00
if spoken_subtitles :
2015-05-23 12:21:18 -07:00
preference = - 1
2015-01-25 09:56:04 -08:00
format_id + = ' -spoken-subtitles '
2017-05-07 04:04:23 -07:00
if sign_language :
preference = - 1
format_id + = " -sign-language "
2015-05-23 12:21:18 -07:00
if target == ' HDS ' :
2017-02-03 23:38:28 -08:00
f4m_formats = self . _extract_f4m_formats (
2015-05-23 12:21:18 -07:00
uri + ' ?hdcore=3.3.0&plugin=aasp-3.3.0.99.43 ' ,
2017-02-03 23:38:28 -08:00
video_id , preference , f4m_id = format_id )
if kind == ' AudioResource ' :
for f in f4m_formats :
f [ ' vcodec ' ] = ' none '
formats . extend ( f4m_formats )
2015-05-23 12:21:18 -07:00
elif target == ' HLS ' :
formats . extend ( self . _extract_m3u8_formats (
2016-09-02 09:02:15 -07:00
uri , video_id , ' mp4 ' , entry_protocol = ' m3u8_native ' ,
preference = preference , m3u8_id = format_id ) )
2015-05-23 12:21:18 -07:00
else :
bitrate = link . get ( ' Bitrate ' )
if bitrate :
format_id + = ' - %s ' % bitrate
formats . append ( {
' url ' : uri ,
' format_id ' : format_id ,
2016-09-02 09:02:15 -07:00
' tbr ' : int_or_none ( bitrate ) ,
2015-05-23 12:21:18 -07:00
' ext ' : link . get ( ' FileFormat ' ) ,
2017-02-03 23:38:28 -08:00
' vcodec ' : ' none ' if kind == ' AudioResource ' else None ,
2015-05-23 12:21:18 -07:00
} )
2014-06-27 06:53:59 -07:00
subtitles_list = asset . get ( ' SubtitlesList ' )
if isinstance ( subtitles_list , list ) :
LANGS = {
2016-01-22 11:54:00 -08:00
' Danish ' : ' da ' ,
2014-06-27 06:53:59 -07:00
}
for subs in subtitles_list :
2016-09-02 09:02:15 -07:00
if not subs . get ( ' Uri ' ) :
continue
lang = subs . get ( ' Language ' ) or ' da '
subtitles . setdefault ( LANGS . get ( lang , lang ) , [ ] ) . append ( {
' url ' : subs [ ' Uri ' ] ,
' ext ' : mimetype2ext ( subs . get ( ' MimeType ' ) ) or ' vtt '
} )
2014-06-27 06:53:59 -07:00
if not formats and restricted_to_denmark :
2016-09-02 09:02:15 -07:00
self . raise_geo_restricted (
' Unfortunately, DR is not allowed to show this program outside Denmark. ' ,
2017-03-05 12:23:01 -08:00
countries = self . _GEO_COUNTRIES )
2014-06-27 06:53:59 -07:00
self . _sort_formats ( formats )
return {
' id ' : video_id ,
' title ' : title ,
' description ' : description ,
' thumbnail ' : thumbnail ,
' timestamp ' : timestamp ,
' duration ' : duration ,
' formats ' : formats ,
2015-02-18 08:20:22 -08:00
' subtitles ' : subtitles ,
2014-06-27 06:53:59 -07:00
}
2017-02-03 23:38:28 -08:00
class DRTVLiveIE ( InfoExtractor ) :
IE_NAME = ' drtv:live '
_VALID_URL = r ' https?://(?:www \ .)?dr \ .dk/(?:tv|TV)/live/(?P<id>[ \ da-z-]+) '
2017-03-05 12:21:03 -08:00
_GEO_COUNTRIES = [ ' DK ' ]
2017-02-03 23:38:28 -08:00
_TEST = {
' url ' : ' https://www.dr.dk/tv/live/dr1 ' ,
' info_dict ' : {
' id ' : ' dr1 ' ,
' ext ' : ' mp4 ' ,
' title ' : ' re:^DR1 [0-9] {4} -[0-9] {2} -[0-9] {2} [0-9] {2} :[0-9] {2} $ ' ,
} ,
' params ' : {
# m3u8 download
' skip_download ' : True ,
} ,
}
def _real_extract ( self , url ) :
channel_id = self . _match_id ( url )
channel_data = self . _download_json (
' https://www.dr.dk/mu-online/api/1.0/channel/ ' + channel_id ,
channel_id )
title = self . _live_title ( channel_data [ ' Title ' ] )
formats = [ ]
for streaming_server in channel_data . get ( ' StreamingServers ' , [ ] ) :
server = streaming_server . get ( ' Server ' )
if not server :
continue
link_type = streaming_server . get ( ' LinkType ' )
for quality in streaming_server . get ( ' Qualities ' , [ ] ) :
for stream in quality . get ( ' Streams ' , [ ] ) :
stream_path = stream . get ( ' Stream ' )
if not stream_path :
continue
stream_url = update_url_query (
' %s / %s ' % ( server , stream_path ) , { ' b ' : ' ' } )
if link_type == ' HLS ' :
formats . extend ( self . _extract_m3u8_formats (
stream_url , channel_id , ' mp4 ' ,
m3u8_id = link_type , fatal = False , live = True ) )
elif link_type == ' HDS ' :
formats . extend ( self . _extract_f4m_formats ( update_url_query (
' %s / %s ' % ( server , stream_path ) , { ' hdcore ' : ' 3.7.0 ' } ) ,
channel_id , f4m_id = link_type , fatal = False ) )
self . _sort_formats ( formats )
return {
' id ' : channel_id ,
' title ' : title ,
' thumbnail ' : channel_data . get ( ' PrimaryImageUri ' ) ,
' formats ' : formats ,
' is_live ' : True ,
}