2015-02-20 13:13:41 +01:00
# coding: utf-8
from __future__ import unicode_literals
from . common import InfoExtractor
2016-09-15 19:54:34 +02:00
from . . compat import compat_str
2015-02-20 13:13:41 +01:00
from . . utils import (
2016-09-15 19:54:34 +02:00
int_or_none ,
2015-02-20 13:13:41 +01:00
parse_iso8601 ,
2016-09-15 19:54:34 +02:00
try_get ,
2017-01-13 10:19:53 +01:00
determine_ext ,
2015-02-20 13:13:41 +01:00
)
class TV4IE ( InfoExtractor ) :
IE_DESC = ' tv4.se and tv4play.se '
_VALID_URL = r ''' (?x)https?://(?:www \ .)?
( ? :
tv4 \. se / ( ? : [ ^ / ] + ) / klipp / ( ? : . * ) - |
tv4play \. se /
( ? :
( ? : program | barn ) / ( ? : [ ^ \? ] + ) \? video_id = |
iframe / video / |
film / |
sport / |
)
) ( ? P < id > [ 0 - 9 ] + ) '''
2017-02-19 00:24:38 +01:00
_GEO_COUNTRIES = [ ' SE ' ]
2015-02-20 13:13:41 +01:00
_TESTS = [
{
' url ' : ' http://www.tv4.se/kalla-fakta/klipp/kalla-fakta-5-english-subtitles-2491650 ' ,
2017-01-13 10:19:53 +01:00
' md5 ' : ' cb837212f342d77cec06e6dad190e96d ' ,
2015-02-20 13:13:41 +01:00
' info_dict ' : {
' id ' : ' 2491650 ' ,
' ext ' : ' mp4 ' ,
' title ' : ' Kalla Fakta 5 (english subtitles) ' ,
2017-01-02 13:08:07 +01:00
' thumbnail ' : r ' re:^https?://.* \ .jpg$ ' ,
2015-02-20 13:13:41 +01:00
' timestamp ' : int ,
' upload_date ' : ' 20131125 ' ,
} ,
} ,
{
' url ' : ' http://www.tv4play.se/iframe/video/3054113 ' ,
2017-01-13 10:19:53 +01:00
' md5 ' : ' cb837212f342d77cec06e6dad190e96d ' ,
2015-02-20 13:13:41 +01:00
' info_dict ' : {
' id ' : ' 3054113 ' ,
' ext ' : ' mp4 ' ,
' title ' : ' Så här jobbar ficktjuvarna - se avslöjande bilder ' ,
2017-01-02 13:08:07 +01:00
' thumbnail ' : r ' re:^https?://.* \ .jpg$ ' ,
2015-02-20 13:13:41 +01:00
' description ' : ' Unika bilder avslöjar hur turisternas fickor vittjas mitt på Stockholms central. Två experter på ficktjuvarna avslöjar knepen du ska se upp för. ' ,
' timestamp ' : int ,
' upload_date ' : ' 20150130 ' ,
} ,
} ,
{
' url ' : ' http://www.tv4play.se/sport/3060959 ' ,
' only_matching ' : True ,
} ,
{
' url ' : ' http://www.tv4play.se/film/2378136 ' ,
' only_matching ' : True ,
} ,
{
' url ' : ' http://www.tv4play.se/barn/looney-tunes?video_id=3062412 ' ,
' only_matching ' : True ,
} ,
]
def _real_extract ( self , url ) :
video_id = self . _match_id ( url )
info = self . _download_json (
2016-09-15 19:54:34 +02:00
' http://www.tv4play.se/player/assets/ %s .json ' % video_id ,
video_id , ' Downloading video info JSON ' )
2015-02-20 13:13:41 +01:00
2016-09-15 19:54:34 +02:00
title = info [ ' title ' ]
2015-02-20 13:13:41 +01:00
2017-01-13 10:19:53 +01:00
subtitles = { }
2015-02-20 13:13:41 +01:00
formats = [ ]
2016-09-15 19:54:34 +02:00
# http formats are linked with unresolvable host
2017-02-19 00:16:00 +01:00
for kind in ( ' hls3 ' , ' ' ) :
2016-09-15 19:54:34 +02:00
data = self . _download_json (
' https://prima.tv4play.se/api/web/asset/ %s /play.json ' % video_id ,
video_id , ' Downloading sources JSON ' , query = {
' protocol ' : kind ,
2017-01-13 10:19:53 +01:00
' videoFormat ' : ' MP4+WEBVTT ' ,
2016-09-15 19:54:34 +02:00
} )
2017-01-13 10:19:53 +01:00
items = try_get ( data , lambda x : x [ ' playback ' ] [ ' items ' ] [ ' item ' ] )
if not items :
2016-09-15 19:54:34 +02:00
continue
2017-01-13 10:19:53 +01:00
if isinstance ( items , dict ) :
items = [ items ]
for item in items :
manifest_url = item . get ( ' url ' )
if not isinstance ( manifest_url , compat_str ) :
continue
ext = determine_ext ( manifest_url )
if ext == ' m3u8 ' :
formats . extend ( self . _extract_m3u8_formats (
manifest_url , video_id , ' mp4 ' , entry_protocol = ' m3u8_native ' ,
m3u8_id = kind , fatal = False ) )
elif ext == ' f4m ' :
formats . extend ( self . _extract_akamai_formats (
manifest_url , video_id , {
' hls ' : ' tv4play-i.akamaihd.net ' ,
} ) )
elif ext == ' webvtt ' :
subtitles = self . _merge_subtitles (
subtitles , {
' sv ' : [ {
' url ' : manifest_url ,
' ext ' : ' vtt ' ,
} ] } )
2017-02-19 00:24:38 +01:00
if not formats and info . get ( ' is_geo_restricted ' ) :
self . raise_geo_restricted ( countries = self . _GEO_COUNTRIES )
2015-02-20 13:13:41 +01:00
self . _sort_formats ( formats )
return {
' id ' : video_id ,
2016-09-15 19:54:34 +02:00
' title ' : title ,
2015-02-20 13:13:41 +01:00
' formats ' : formats ,
2017-01-13 10:19:53 +01:00
' subtitles ' : subtitles ,
2015-02-20 13:13:41 +01:00
' description ' : info . get ( ' description ' ) ,
' timestamp ' : parse_iso8601 ( info . get ( ' broadcast_date_time ' ) ) ,
2016-09-15 19:54:34 +02:00
' duration ' : int_or_none ( info . get ( ' duration ' ) ) ,
2015-02-20 13:13:41 +01:00
' thumbnail ' : info . get ( ' image ' ) ,
2016-09-15 19:54:34 +02:00
' is_live ' : info . get ( ' is_live ' ) is True ,
2015-02-20 13:13:41 +01:00
}