def test_get_stream_not_live(self): responses.add('GET', re.compile('https://edge.api.brightcove.com/'), body=self.VIDEO_JSON) url = config.BRIGHTCOVE_DRM_URL.format(config.BRIGHTCOVE_ACCOUNT, '42') observed = comm.get_stream(url) self.assertIn('713677e9', observed.get('url')) self.assertIn('text.vtt', observed.get('sub_url'))
def test_get_stream(self, mock_token, mock_uuid): mock_uuid.side_effect = fakes.UUID mock_token.return_value = 'foo' program_id = '1234' url = re.compile('^https://www.sbs.com.au/api/v3/video_stream') responses.add(responses.GET, url, body=self.VIDEO_STREAM_JSON, status=200) observed = comm.get_stream(program_id) self.assertEqual({'stream_url': 'https://foo.bar/content.m3u8'}, observed)
def test_get_stream_kodi18(self, mock_addon, mock_token, mock_uuid, mock_ver): mock_addon.return_value = fakes.FakeAddon(user_token='foo', DAI='true') mock_ver.return_value = 18 mock_uuid.side_effect = fakes.UUID mock_token.return_value = 'foo' program = comm.classes.Program() program.id = '1234' url = re.compile('^https://www.sbs.com.au/api/v3/video_stream') responses.add(responses.GET, url, body=self.VIDEO_STREAM_JSON, status=200) observed = comm.get_stream(program) self.assertEqual({'stream_url': 'https://foo.bar/content.m3u8'}, observed)
def play(url): try: addon = xbmcaddon.Addon() p = classes.Program() p.parse_kodi_url(url) stream_info = comm.get_stream(p.id) if not stream_info: return stream_url = stream_info.get('stream_url') bandwidth = addon.getSetting('BANDWIDTH') if bandwidth == '0': stream_url = stream_url.replace('&b=0-2000', '&b=400-600') elif bandwidth == '1': stream_url = stream_url.replace('&b=0-2000', '&b=900-1100') elif bandwidth == '2': stream_url = stream_url.replace('&b=0-2000', '&b=1400-1600') listitem = comm.create_listitem(label=p.get_list_title(), path=str(stream_url)) listitem.setArt({'icon': p.thumb, 'thumb': p.thumb}) listitem.setInfo('video', p.get_kodi_list_item()) # Add subtitles if available if 'subtitles' in stream_info: sub_url = stream_info['subtitles'] profile = addon.getAddonInfo('profile') path = xbmc.translatePath(profile) if not os.path.isdir(path): os.makedirs(path) subfile = xbmc.translatePath( os.path.join(path, 'subtitles.eng.srt')) if os.path.isfile(subfile): os.remove(subfile) try: sess = session.Session() data = sess.get(sub_url).text f = open(subfile, 'w') f.write(data) f.close() if hasattr(listitem, 'setSubtitles'): # This function only supported from Kodi v14+ listitem.setSubtitles([subfile]) except Exception: utils.log('Subtitles not available for this program') listitem.setProperty('inputstreamaddon', 'inputstream.adaptive') listitem.setProperty('inputstream.adaptive.manifest_type', 'hls') listitem.setProperty('inputstream.adaptive.license_key', stream_url) if hasattr(listitem, 'addStreamInfo'): listitem.addStreamInfo('audio', p.get_kodi_audio_stream_info()) listitem.addStreamInfo('video', p.get_kodi_video_stream_info()) listitem.setProperty('isPlayable', 'true') if utils.get_kodi_major_version() >= 18: listitem.setIsFolder(False) xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem=listitem) try: import upnext except Exception as e: utils.log('UpNext addon not installed: %s' % e) return np = comm.get_next_program(p) if not isinstance(np, classes.Program): return next_info = OrderedDict(current_episode=OrderedDict( episodeid=p.id, tvshowid=p.get_tvshowid(), title=p.get_title(), art={ 'thumb': p.get_thumb(), 'tvshow.fanart': p.get_fanart(), }, season=p.get_season_no(), episode=p.get_episode_no(), showtitle=p.get_series_title(), plot=p.get_description(), playcount=0, rating=None, firstaired=p.get_date(), runtime=p.get_duration(), ), next_episode=OrderedDict( episodeid=np.id, tvshowid=np.get_tvshowid(), title=np.get_title(), art={ 'thumb': np.get_thumb(), 'tvshow.fanart': np.get_fanart(), }, season=np.get_season_no(), episode=np.get_episode_no(), showtitle=np.get_series_title(), plot=np.get_description(), playcount=0, rating=None, firstaired=np.get_date(), runtime=np.get_duration(), ), play_url='{0}?{1}'.format( sys.argv[0], np.make_kodi_url()), notification_offset=p.get_credits_time()) upnext.send_signal(xbmcaddon.Addon().getAddonInfo('id'), next_info) except Exception: utils.handle_error("Unable to play video")
def play_video(params): """ Determine content and pass url to Kodi for playback """ try: _url = sys.argv[0] _handle = int(sys.argv[1]) json_url = config.BRIGHTCOVE_DRM_URL.format(config.BRIGHTCOVE_ACCOUNT, params['id']) play_item = xbmcgui.ListItem() play_item.setProperty('inputstreamaddon', 'inputstream.adaptive') play_item.setProperty('inputstream', 'inputstream.adaptive') if params.get('drm') == 'True': if xbmcaddon.Addon().getSetting('ignore_drm') == 'false': if not drmhelper.check_inputstream(): return widevine = comm.get_widevine_auth(json_url) url = widevine['url'] sub_url = widevine['sub_url'] play_item.setPath(url) play_item.setProperty('inputstream.adaptive.manifest_type', 'mpd') play_item.setProperty('inputstream.adaptive.license_type', 'com.widevine.alpha') play_item.setProperty( 'inputstream.adaptive.license_key', widevine['key'] + ('|Content-Type=application%2F' 'x-www-form-urlencoded|A{SSM}|')) else: live = params['action'] == 'listchannels' stream_data = comm.get_stream(json_url, live=live) url = str(stream_data.get('url')) sub_url = stream_data.get('sub_url') play_item.setPath(url) play_item.setProperty('inputstream.adaptive.manifest_type', 'hls') utils.log('Playing {0} - {1}'.format(params.get('title'), url)) if sub_url: try: utils.log("Enabling subtitles: {0}".format(sub_url)) profile = xbmcaddon.Addon().getAddonInfo('profile') subfilename = xbmc.translatePath( os.path.join(profile, 'subtitle.srt')) profiledir = xbmc.translatePath(os.path.join(profile)) if not os.path.isdir(profiledir): os.makedirs(profiledir) with custom_session.Session() as s: webvtt_data = s.get(sub_url).text if webvtt_data: with open(subfilename, 'w') as f: webvtt_subtitle = WebVTTReader().read(webvtt_data) srt_subtitle = SRTWriter().write(webvtt_subtitle) srt_unicode = srt_subtitle.encode('utf-8') f.write(srt_unicode) if hasattr(play_item, 'setSubtitles'): # This function only supported from Kodi v14+ play_item.setSubtitles([subfilename]) except Exception as e: utils.log('Unable to add subtitles: {0}'.format(e)) play_item.setProperty('isPlayable', 'true') if hasattr(play_item, 'setIsFolder'): play_item.setIsFolder(False) # TODO: add more info play_item.setInfo( 'video', { 'mediatype': 'episode', 'tvshowtitle': params.get('series_title', ''), 'title': params.get('episode_name', ''), 'plot': params.get('desc', ''), 'plotoutline': params.get('desc', ''), 'duration': params.get('duration', ''), 'aired': params.get('airdate', ''), 'season': params.get('season_no', ''), 'episode': params.get('episode_no', '') }) xbmcplugin.setResolvedUrl(_handle, True, play_item) if params['action'] != 'listepisodes': return next_item = comm.get_next_episode(params) if not next_item: return try: import upnext except Exception as e: utils.log('UpNext addon not installed: %s' % e) return upnext_info = dict(current_episode=dict( episodeid=params.get('id', ''), tvshowid=params.get('series_slug', ''), title=params.get('episode_name', ''), art={ 'thumb': params.get('thumb', ''), 'tvshow.fanart': params.get('fanart', ''), }, season=params.get('season_no', ''), episode=params.get('episode_no', ''), showtitle=params.get('series_title', ''), plot=params.get('desc', ''), playcount=0, rating=None, firstaired=params.get('airdate', ''), runtime=params.get('duration', ''), ), next_episode=dict( episodeid=next_item.id, tvshowid=next_item.series_slug, title=next_item.episode_name, art={ 'thumb': next_item.thumb, 'tvshow.fanart': next_item.fanart, }, season=next_item.season_no, episode=next_item.episode_no, showtitle=next_item.series_title, plot=next_item.desc, playcount=0, rating=None, firstaired=next_item.airdate, runtime=next_item.duration, ), play_url='{0}?action=listepisodes{1}'.format( _url, next_item.make_kodi_url())) upnext.send_signal(xbmcaddon.Addon().getAddonInfo('id'), upnext_info) except Exception: utils.handle_error('Unable to play video')