6 from .common
import InfoExtractor
7 from ..utils
import js_to_json
10 class RTPIE(InfoExtractor
):
11 _VALID_URL
= r
'https?://(?:www\.)?rtp\.pt/play/(?:(?:estudoemcasa|palco|zigzag)/)?p(?P<program_id>[0-9]+)/(?P<id>[^/?#]+)'
13 'url': 'http://www.rtp.pt/play/p405/e174042/paixoes-cruzadas',
14 'md5': 'e736ce0c665e459ddb818546220b4ef8',
18 'title': 'Paixões Cruzadas',
19 'description': 'As paixões musicais de António Cartaxo e António Macedo',
20 'thumbnail': r
're:^https?://.*\.jpg',
23 'url': 'https://www.rtp.pt/play/zigzag/p13166/e757904/25-curiosidades-25-de-abril',
24 'md5': '9a81ed53f2b2197cfa7ed455b12f8ade',
28 'title': '25 Curiosidades, 25 de Abril',
29 'description': 'Estudar ou não estudar - Em cada um dos episódios descobrimos uma curiosidade acerca de como era viver em Portugal antes da revolução do 25 de abr',
30 'thumbnail': r
're:^https?://.*\.jpg',
33 'url': 'http://www.rtp.pt/play/p831/a-quimica-das-coisas',
34 'only_matching': True,
36 'url': 'https://www.rtp.pt/play/estudoemcasa/p7776/portugues-1-ano',
37 'only_matching': True,
39 'url': 'https://www.rtp.pt/play/palco/p13785/l7nnon',
40 'only_matching': True,
43 _RX_OBFUSCATION
= re
.compile(r
'''(?xs)
44 atob\s*\(\s*decodeURIComponent\s*\(\s*
45 (\[[0-9A-Za-z%,'"]*\])
46 \s*\.\s*join\(\s*(?:""|'')\s*\)\s*\)\s*\)
49 def __unobfuscate(self
, data
, *, video_id
):
50 if data
.startswith('{'):
51 data
= self
._RX
_OBFUSCATION
.sub(
53 base64
.b64decode(urllib
.parse
.unquote(
54 ''.join(self
._parse
_json
(m
.group(1), video_id
)),
55 )).decode('iso-8859-1')),
57 return js_to_json(data
)
59 def _real_extract(self
, url
):
60 video_id
= self
._match
_id
(url
)
62 webpage
= self
._download
_webpage
(url
, video_id
)
63 title
= self
._html
_search
_meta
(
64 'twitter:title', webpage
, display_name
='title', fatal
=True)
66 f
, config
= self
._search
_regex
(
68 (?:var\s+f\s*=\s*(?P<f>".*?"|{[^;]+?});\s*)?
69 var\s+player1\s+=\s+new\s+RTPPlayer\s*\((?P<config>{(?:(?!\*/).)+?})\);(?!\s*\*/)
71 'player config', group
=('f', 'config'))
73 config
= self
._parse
_json
(
75 lambda data
: self
.__unobfuscate
(data
, video_id
=video_id
))
76 f
= config
['file'] if not f
else self
._parse
_json
(
78 lambda data
: self
.__unobfuscate
(data
, video_id
=video_id
))
81 if isinstance(f
, dict):
84 formats
.extend(self
._extract
_m
3u8_formats
(
85 f_hls
, video_id
, 'mp4', 'm3u8_native', m3u8_id
='hls'))
87 f_dash
= f
.get('dash')
88 if f_dash
is not None:
89 formats
.extend(self
._extract
_mpd
_formats
(f_dash
, video_id
, mpd_id
='dash'))
94 'vcodec': 'none' if config
.get('mediaType') == 'audio' else None,
99 vtt
= config
.get('vtt')
101 for lcode
, lname
, url
in vtt
:
102 subtitles
.setdefault(lcode
, []).append({
111 'description': self
._html
_search
_meta
(['description', 'twitter:description'], webpage
),
112 'thumbnail': config
.get('poster') or self
._og
_search
_thumbnail
(webpage
),
113 'subtitles': subtitles
,