3 from .common
import InfoExtractor
4 from ..utils
import int_or_none
, traverse_obj
7 class PlaySuisseIE(InfoExtractor
):
8 _VALID_URL
= r
'https?://(?:www\.)?playsuisse\.ch/watch/(?P<id>[0-9]+)'
11 'url': 'https://www.playsuisse.ch/watch/763211/0',
12 'md5': '82df2a470b2dfa60c2d33772a8a60cf8',
17 'description': 'md5:8ea7a8076ba000cd9e8bc132fd0afdd8',
24 'thumbnail': 'md5:9260abe0c0ec9b69914d0a10d54c5878'
28 'url': 'https://www.playsuisse.ch/watch/808675/0',
29 'md5': '818b94c1d2d7c4beef953f12cb8f3e75',
33 'title': 'Der Läufer',
34 'description': 'md5:9f61265c7e6dcc3e046137a792b275fd',
36 'episode': 'Der Läufer',
37 'thumbnail': 'md5:44af7d65ee02bbba4576b131868bb783'
41 'url': 'https://www.playsuisse.ch/watch/817193/0',
42 'md5': '1d6c066f92cd7fffd8b28a53526d6b59',
46 'title': 'Die Einweihungsparty',
47 'description': 'md5:91ebf04d3a42cb3ab70666acf750a930',
52 'episode': 'Die Einweihungsparty',
54 'thumbnail': 'md5:637585fb106e3a4bcd991958924c7e44'
60 query AssetWatch($assetId: ID!) {
61 assetV2(id: $assetId) {
68 fragment Asset on AssetV2 {
86 thumbnail16x9WithTitle {
89 thumbnail2x3WithTitle {
93 fragment ImageDetails on AssetImage {
98 def _get_media_data(self
, media_id
):
99 # NOTE In the web app, the "locale" header is used to switch between languages,
100 # However this doesn't seem to take effect when passing the header here.
101 response
= self
._download
_json
(
102 'https://4bbepzm4ef.execute-api.eu-central-1.amazonaws.com/prod/graphql',
103 media_id
, data
=json
.dumps({
104 'operationName': 'AssetWatch',
105 'query': self
._GRAPHQL
_QUERY
,
106 'variables': {'assetId': media_id}
108 headers
={'Content-Type': 'application/json', 'locale': 'de'}
)
110 return response
['data']['assetV2']
112 def _real_extract(self
, url
):
113 media_id
= self
._match
_id
(url
)
114 media_data
= self
._get
_media
_data
(media_id
)
115 info
= self
._extract
_single
(media_data
)
116 if media_data
.get('episodes'):
119 'entries': map(self
._extract
_single
, media_data
['episodes']),
123 def _extract_single(self
, media_data
):
124 thumbnails
= traverse_obj(media_data
, lambda k
, _
: k
.startswith('thumbnail'))
126 formats
, subtitles
= [], {}
127 for media
in traverse_obj(media_data
, 'medias', default
=[]):
128 if not media
.get('url') or media
.get('type') != 'HLS':
130 f
, subs
= self
._extract
_m
3u8_formats
_and
_subtitles
(
131 media
['url'], media_data
['id'], 'mp4', m3u8_id
='HLS', fatal
=False)
133 self
._merge
_subtitles
(subs
, target
=subtitles
)
136 'id': media_data
['id'],
137 'title': media_data
.get('name'),
138 'description': media_data
.get('description'),
139 'thumbnails': thumbnails
,
140 'duration': int_or_none(media_data
.get('duration')),
142 'subtitles': subtitles
,
143 'series': media_data
.get('seriesName'),
144 'season_number': int_or_none(media_data
.get('seasonNumber')),
145 'episode': media_data
.get('name'),
146 'episode_number': int_or_none(media_data
.get('episodeNumber')),