forked from streamlink/streamlink
/
gulli.py
92 lines (77 loc) · 3.03 KB
/
gulli.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
"""
$description French live TV channel and video on-demand service owned by Gulli.
$url replay.gulli.fr
$type live, vod
$region France
"""
import logging
import re
from streamlink.plugin import Plugin, pluginmatcher
from streamlink.plugin.api import validate
from streamlink.stream.hls import HLSStream
from streamlink.stream.http import HTTPStream
log = logging.getLogger(__name__)
@pluginmatcher(re.compile(
r'https?://replay\.gulli\.fr/(?:Direct|.+/(?P<video_id>VOD\d+))'
))
class Gulli(Plugin):
LIVE_PLAYER_URL = 'https://replay.gulli.fr/jwplayer/embedstreamtv'
VOD_PLAYER_URL = 'https://replay.gulli.fr/jwplayer/embed/{0}'
_playlist_re = re.compile(r'sources: (\[.+?\])', re.DOTALL)
_vod_video_index_re = re.compile(r'jwplayer\(idplayer\).playlistItem\((?P<video_index>[0-9]+)\)')
_mp4_bitrate_re = re.compile(r'.*_(?P<bitrate>[0-9]+)\.mp4')
_video_schema = validate.Schema(
validate.all(
validate.transform(lambda x: re.sub(r'"?file"?:\s*[\'"](.+?)[\'"],?', r'"file": "\1"', x, flags=re.DOTALL)),
validate.transform(lambda x: re.sub(r'"?\w+?"?:\s*function\b.*?(?<={).*(?=})', "", x, flags=re.DOTALL)),
validate.parse_json(),
[
validate.Schema({
'file': validate.url()
})
]
)
)
def _get_streams(self):
video_id = self.match.group('video_id')
if video_id is not None:
# VOD
live = False
player_url = self.VOD_PLAYER_URL.format(video_id)
else:
# Live
live = True
player_url = self.LIVE_PLAYER_URL
res = self.session.http.get(player_url)
playlist = re.findall(self._playlist_re, res.text)
index = 0
if not live:
# Get the index for the video on the playlist
match = self._vod_video_index_re.search(res.text)
if match is None:
return
index = int(match.group('video_index'))
if not playlist:
return
videos = self._video_schema.validate(playlist[index])
for video in videos:
video_url = video['file']
# Ignore non-supported MSS streams
if 'isml/Manifest' in video_url:
continue
try:
if '.m3u8' in video_url:
for stream in HLSStream.parse_variant_playlist(self.session, video_url).items():
yield stream
elif '.mp4' in video_url:
match = self._mp4_bitrate_re.match(video_url)
if match is not None:
bitrate = '%sk' % match.group('bitrate')
else:
bitrate = 'vod'
yield bitrate, HTTPStream(self.session, video_url)
except IOError as err:
if '403 Client Error' in str(err):
log.error('Failed to access stream, may be due to geo-restriction')
raise
__plugin__ = Gulli