Beispiel #1
0
def play(asset, play_type=PLAY_FROM_LIVE, **kwargs):
    play_type = int(play_type)

    from_start = False
    if play_type == PLAY_FROM_START or (
            play_type == PLAY_FROM_ASK
            and not gui.yes_no(_.PLAY_FROM,
                               yeslabel=_.PLAY_FROM_LIVE,
                               nolabel=_.PLAY_FROM_START)):
        from_start = True

    stream = api.play(asset, True)

    item = plugin.Item(
        path=stream['url'],
        inputstream=inputstream.Widevine(
            license_key=stream['license']['@uri']),
        headers=HEADERS,
    )

    drm_data = stream['license'].get('drmData')
    if drm_data:
        item.headers['x-axdrm-message'] = drm_data

    if from_start:
        item.resume_from = 1

    return item
Beispiel #2
0
def play(asset, play_type=PLAY_FROM_LIVE, **kwargs):
    play_type = int(play_type)

    from_start = False
    if play_type == PLAY_FROM_START or (
            play_type == PLAY_FROM_ASK
            and not gui.yes_no(_.PLAY_FROM,
                               yeslabel=_.PLAY_FROM_LIVE,
                               nolabel=_.PLAY_FROM_START)):
        from_start = True

    stream = api.play(asset, True)

    item = plugin.Item(
        path=stream['url'],
        inputstream=inputstream.Widevine(
            license_key=stream['license']['@uri']),
        headers=HEADERS,
    )

    drm_data = stream['license'].get('drmData')
    if drm_data:
        item.headers['x-axdrm-message'] = drm_data

    if from_start:
        item.properties['ResumeTime'] = '1'
        item.properties['TotalTime'] = '1'

    if kwargs.get(ROUTE_LIVE_TAG):
        item.inputstream.properties['manifest_update_parameter'] = 'full'

    return item
Beispiel #3
0
def play(id, **kwargs):
    data = api.play(id)

    headers = {}
    headers.update(HEADERS)

    drm_info = data.get('drmInfo') or {}
    cookies = data.get('cookie') or {}

    if drm_info:
        if drm_info['drmScheme'].lower() == 'widevine':
            ia = inputstream.Widevine(license_key=drm_info['drmLicenseUrl'], )
            headers.update(drm_info.get('drmKeyRequestProperties') or {})
        else:
            raise PluginError('Unsupported Stream!')
    else:
        ia = inputstream.HLS(live=True)

    return plugin.Item(
        path=data['url'],
        inputstream=ia,
        headers=headers,
        cookies=cookies,
        resume_from=LIVE_HEAD,  ## Need to seek to live over multi-periods
    )
Beispiel #4
0
def play(slug, **kwargs):
    data, content = api.play(slug)

    headers = {
        'Authorization': 'Bearer {}'.format(userdata.get('access_token')),
    }

    item = plugin.Item(
        path = data['url'],
        inputstream = inputstream.MPD(),
        headers = headers,
    )

    if 'drm' in data:
        item.inputstream = inputstream.Widevine(license_key = data['drm']['licenseUrl'])
        item.proxy_data['manifest_middleware'] = plugin.url_for(mpd_request)
        if settings.getBool('wv_secure'):
            item.inputstream.properties['license_flags'] = 'force_secure_decoder'

    item.play_next = {}
    if ':episode' in slug:
        item.update(
            label = content['titles']['full'],
            art   = {'thumb': _image(content['images'].get('tileburnedin')), 'fanart':  _image(content['images'].get('tile'), size='1920x1080')},
            info  = {
                'plot': content['summaries']['short'],
                'duration': content['duration'],
                'tvshowtitle': content['seriesTitles']['full'],
                'season': content.get('seasonNumber', 1),
                'episode': content.get('numberInSeason', content.get('numberInSeries', 1)),
                'mediatype': 'episode'
            },
        )

        if settings.getBool('play_next_episode', True):
            item.play_next['next_file'] = _get_play_path(content.get('next'))

    elif ':feature' in slug:
        item.update(
            label = content['titles']['full'],
            art   = {'thumb': _image(content['images'].get('tileburnedin')), 'fanart':_image(content['images'].get('tile'), size='1920x1080')},
            info  = {
                'plot': content['summaries']['short'],
                'duration': content['duration'],
                'year': content['releaseYear'],
                'mediatype': 'movie',
            },
        )

        if settings.getBool('play_next_movie', False):
            for slug in content.get('similars', []):
                if ':feature' in slug:
                    item.play_next['next_file'] = 'urn:hbo:feature:' + slug.split(':')[3]
                    break

    if not settings.getBool('ignore_subs', False):
        for row in data.get('textTracks', []):
            item.subtitles.append([row['url'], row['language']])

    return item
Beispiel #5
0
def _play_videos(videos):
    if not videos:
        plugin.exception('No videos found')

    default_audio = settings.getEnum('audio_lang', AUDIO_LANGS)

    if len(videos) == 1:
        chosen = videos[0]
    else:
        videos = sorted(videos, key=lambda x: x['language'])

        chosen = None
        for video in videos:
            if video['language']['iso_639_3'].lower() == default_audio:
                chosen = video
                break

        if not chosen:
            index = gui.select(_.SELECT_LANG,
                               [x['language']['name'] for x in videos])
            if index < 0:
                return

            chosen = videos[index]

    url, license_url = api.play(chosen['id'])
    item = plugin.Item(
        inputstream=inputstream.Widevine(license_url),
        path=url,
        headers=HEADERS,
        use_proxy=
        True,  # Needed for https://github.com/xbmc/inputstream.adaptive/pull/606
    )

    return item
Beispiel #6
0
def _play(program_id, play_type=None, is_live=False):
    play_type  = int(play_type) if play_type else None
    program_data, play_data = api.play(program_id)

    headers = HEADERS.copy()
    headers['dt-custom-data'] = play_data['drm']['customData']

    item = plugin.Item(
        path    = play_data['videoUrl'],
        headers = headers,
        inputstream = inputstream.Widevine(
            license_key  = play_data['drm']['licenseServerUrl'],
            license_data = play_data['drm']['init_data'],
            response     = 'JBlicense',
        ),
    )

    if is_live and (play_type == PLAY_FROM_START or (play_type == PLAY_FROM_ASK and not gui.yes_no(_.PLAY_FROM, yeslabel=_.PLAY_FROM_LIVE, nolabel=_.PLAY_FROM_START))):
        item.properties['ResumeTime'] = '1'
        item.properties['TotalTime']  = '1'

    for row in play_data.get('captions', []):
        item.subtitles.append([row['url'], row['language']])

    # for chapter in program_data.get('chapters', []):
    #     if chapter['name'] == 'Intro':
    #         item.properties['TotalTime'] = item.properties['ResumeTime'] = str(chapter['end']/1000 - 1)
    #     elif chapter['name'] == 'Credits':
    #         item.play_next = {'time': chapter['start']/1000}

    return item
Beispiel #7
0
def play_channel(id, **kwargs):
    url, license_url, headers = api.play_channel(id)

    return plugin.Item(
        inputstream = inputstream.Widevine(license_url, properties={'manifest_update_parameter': 'full'}),
        headers = headers,
        path = url,
    )
Beispiel #8
0
def play_asset(stream_url, content_id, **kwargs):
    url, license_url, headers = api.play_asset(stream_url, content_id)

    return plugin.Item(
        inputstream = inputstream.Widevine(license_url),
        headers = headers,
        path = url,
    )
Beispiel #9
0
def play_video(id, **kwargs):
    url, license_url, headers = api.play_video(id)

    return plugin.Item(
        inputstream = inputstream.Widevine(license_url),
        headers = headers,
        path = url,
    )
Beispiel #10
0
def play(channel_id, call_letter, **kwargs):
    data = api.play(channel_id, call_letter)

    item = plugin.Item(
        path=data['url'],
        headers={'X-AxDRM-Message': data['DRMToken']},
        inputstream=inputstream.Widevine(license_key='{}?KID={}'.format(
            data['LicenseURL'], data['KeyID']), ),
    )

    return item
Beispiel #11
0
def play_video(index, **kwargs):
    video = VIDEO_TESTS[int(index)]

    item = plugin.Item(path=video['url'], )

    if video['type'] == 'ia_hls':
        item.inputstream = inputstream.HLS(force=True, live=False)
    elif video['type'] == 'ia_mpd':
        item.inputstream = inputstream.MPD()
    elif video['type'] == 'ia_widevine':
        item.inputstream = inputstream.Widevine(video.get('license_key'))

    return item
Beispiel #12
0
def _play(media_type, id):
    url, license_url = api.play(media_type, id)

    item = plugin.Item(
        inputstream = inputstream.Widevine(license_key=license_url),
        path = url,
        headers = HEADERS,
    )

    if media_type == TYPE_LIVE:
        item.inputstream.properties['manifest_update_parameter'] = 'full'

    return item
Beispiel #13
0
def play_channel(id, **kwargs):
    url, license = api.play_channel(id)

    item = plugin.Item(
        path=url,
        headers=HEADERS,
        inputstream=inputstream.Widevine(license_key=license, ),
    )

    if kwargs.get(ROUTE_LIVE_TAG):
        item.inputstream.properties['manifest_update_parameter'] = 'full'

    return item
Beispiel #14
0
def play(channel_id, **kwargs):
    url = api.play(channel_id)

    license_path = plugin.url_for(license_request, channel_id=channel_id)

    return plugin.Item(
        path=url,
        inputstream=inputstream.Widevine(license_key=license_path,
                                         challenge='b{SSM}',
                                         response='B'),
        headers=HEADERS,
        proxy_data={'default_language': settings.get('default_language')},
    )
def play_channel(slug, **kwargs):
    channel = Channel.get_by_id(slug)
    split = channel.url.split('|')

    headers = {
        'user-agent': DEFAULT_USERAGENT,
    }

    if len(split) > 1:
        _headers = dict(
            parse_qsl(u'{}'.format(split[1]), keep_blank_values=True))
        for key in _headers:
            if _headers[key].startswith(' '):
                _headers[key] = u'%20{}'.format(_headers[key][1:])

            headers[key.lower()] = _headers[key]

    item = plugin.Item(
        label=channel.name,
        art={'thumb': channel.logo},
        path=split[0],
        properties=channel.properties,
        headers=headers,
        playable=True,
    )

    if channel.radio:
        item.use_proxy = False

    manifest_type = channel.properties.get(
        'inputstream.adaptive.manifest_type', '')
    license_type = channel.properties.get('inputstream.adaptive.license_type',
                                          '')

    if license_type.lower() == 'com.widevine.alpha':
        inputstream.Widevine().check()

    elif manifest_type.lower() == 'hls':
        inputstream.HLS(force=True, live=True).check()

    elif manifest_type.lower() == 'ism':
        inputstream.Playready().check()

    elif manifest_type.lower() == 'mpd':
        inputstream.MPD().check()

    elif not channel.radio and '.m3u8' in split[0].lower(
    ) and settings.getBool('use_ia_hls_live'):
        item.inputstream = inputstream.HLS(live=True)

    return item
Beispiel #16
0
    def get_stream(self, film_id):
        play_data = self._session.get('/services/content/v4/media_content/play/film/{}'.format(film_id), params={'encoding_type':'dash', 'drm':'widevine'}).json()
        if 'error' in play_data:
            raise APIError(play_data['error'])

        mpd_url = play_data['streams'][0]['url']
        key_url = BASE_URL.format('/services/license/widevine/cenc?context={}'.format(play_data['streams'][0]['drm_key_encoded'].strip()))

        item = plugin.Item(
            path = play_data['streams'][0]['url'],
            inputstream = inputstream.Widevine(license_key=key_url),
            headers = self._session.headers,
        )

        return item
Beispiel #17
0
def _play(asset_id, is_linear=False, is_live=False):
    url, license = api.play(asset_id, is_linear=is_linear)

    item = plugin.Item(
        path        = url,
        headers     = HEADERS,
        inputstream = inputstream.Widevine(
            license_key = license,
        ),
    )

    if is_live:
        item.inputstream.properties['manifest_update_parameter'] = 'full'

    return item
Beispiel #18
0
def play(channel_id=None, vod_id=None, **kwargs):
    asset = api.play(channel_id, vod_id)

    _headers = {}
    _headers.update(HEADERS)
    _headers.update({
        'Authorization': asset['DrmToken'],
        'X-CB-Ticket': asset['DrmTicket'],
        'X-ErDRM-Message': asset['DrmTicket'],
    })

    return plugin.Item(
        path=asset['Path'],
        inputstream=inputstream.Widevine(license_key=WV_LICENSE_URL),
        headers=_headers,
    )
Beispiel #19
0
def play(video_id, **kwargs):
    url, license_url, token, data = api.play(video_id)

    item = _parse_item(data)
    item.proxy_data['manifest_middleware'] = plugin.url_for(mpd_request)

    headers = {
        'authorization': 'Bearer {}'.format(token),
    }

    item.update(
        path=url,
        headers=headers,
        inputstream=inputstream.Widevine(license_key=license_url, ),
    )

    return item
Beispiel #20
0
def play(id, **kwargs):
    url, license = api.play_media(id)

    item = plugin.Item(
        path        = url,
        headers     = HEADERS,
        inputstream = inputstream.Widevine(
            license_key  = license,
            challenge    = '',
            content_type = '',
            response     = 'JBlicense',
        ),
    )

    if kwargs.get(ROUTE_LIVE_TAG):
        item.inputstream.properties['manifest_update_parameter'] = 'full'
        gui.text(OLD_MESSAGE)

    return item
Beispiel #21
0
def play(id, play_type=PLAY_FROM_LIVE, **kwargs):
    mpd_url, license, headers, from_start = api.play(id)

    item = plugin.Item(
        path=mpd_url,
        inputstream=inputstream.Widevine(license_key=license),
        headers=headers,
        use_proxy=True,
    )

    play_type = int(play_type)
    if from_start and (
            play_type == PLAY_FROM_START or
        (play_type == PLAY_FROM_ASK and not gui.yes_no(
            _.PLAY_FROM, yeslabel=_.PLAY_FROM_LIVE, nolabel=_.PLAY_FROM_START))
    ):
        item.properties['ResumeTime'] = 1
        item.properties['TotalTime'] = 1

    return item
Beispiel #22
0
    def play(self, slug):
        resp = self._session.get('/videos/{slug}'.format(slug=slug),
                                 allow_redirects=False)

        if resp.status_code == 302 or 'The device limit for your account has been reached' in resp.text:
            raise APIError(_.DEVICE_LIMIT)

        page = resp.text.replace(' ', '').strip()
        play_url = re.search('embed_url:"(.*?)"', page).group(1)

        resp = self._session.get(play_url)
        page = resp.text.replace(' ', '').strip()

        event_id = re.search('eventId:(.*?),', page)

        if event_id:
            config_url = LIVESTREAM_URL.format(event_id=event_id.group(1))
        else:
            config_url = re.search('"config_url":"(.*?)"', page).group(1)
            config_url = config_url.encode().decode('unicode_escape')

        data = self._session.get(config_url,
                                 headers={
                                     'Referer': 'https://embed.vhx.tv/'
                                 }).json()
        if data.get('secure_m3u8_url'):
            return data['secure_m3u8_url'], inputstream.HLS()

        default_cdn = data['request']['files']['dash']['default_cdn']
        mpd_url = data['request']['files']['dash']['cdns'][default_cdn][
            'url']  #.replace('.json?base64_init=1', '.mpd')
        mpd_url = mpd_url.replace('.json', '.mpd')

        if data['request'].get('drm'):
            license_url = self._session.get(
                data['request']['drm']['cdms']['widevine']['license_url']).text
            ia = inputstream.Widevine(license_key=license_url)
        else:
            ia = inputstream.MPD()

        return mpd_url, ia
Beispiel #23
0
def play(id, play_type=PLAY_FROM_LIVE, **kwargs):
    mpd_url, license, headers, from_start = api.play(id)

    item = plugin.Item(
        path=mpd_url,
        inputstream=inputstream.Widevine(license_key=license),
        headers=headers,
    )

    play_type = int(play_type)
    if from_start and (
            play_type == PLAY_FROM_START or
        (play_type == PLAY_FROM_ASK and not gui.yes_no(
            _.PLAY_FROM, yeslabel=_.PLAY_FROM_LIVE, nolabel=_.PLAY_FROM_START))
    ):
        item.resume_from = 1
    elif ROUTE_LIVE_TAG in kwargs:
        ## Need below to seek to live over multi-periods
        item.resume_from = LIVE_HEAD

    return item
Beispiel #24
0
def play(media_id, media_type, start=None, duration=None, **kwargs):
    if start:
        start = int(start)
        now = arrow.utcnow()
        if start > now.timestamp:
            raise PluginError(_.NOT_STARTED_YET)
        elif start < now.shift(hours=-24).timestamp:
            raise PluginError(_.EVENT_EXPIRED)

    data = api.play(media_id, media_type, start, duration)

    headers = HEADERS
    headers.update({'Authorization': 'bearer {}'.format(data['drmToken'])})

    item = plugin.Item(
        path        = data['path'],
        inputstream = inputstream.Widevine(license_key=WIDEVINE_URL),
        headers     = headers,
    )

    if media_type == MEDIA_CHANNEL:
        item.inputstream.properties['manifest_update_parameter'] = 'full'

    return item
Beispiel #25
0
def play(id, start_from=0, play_type=PLAY_FROM_LIVE, **kwargs):
    asset = api.stream(id)

    start_from = int(start_from)
    play_type = int(play_type)
    is_live = kwargs.get(ROUTE_LIVE_TAG) == ROUTE_LIVE_SUFFIX

    streams = [asset['recommendedStream']]
    streams.extend(asset['alternativeStreams'])
    streams = [s for s in streams if s['mediaFormat'] in SUPPORTED_FORMATS]

    if not streams:
        raise PluginError(_.NO_STREAM)

    prefer_cdn = settings.getEnum('prefer_cdn', AVAILABLE_CDNS)
    if prefer_cdn == CDN_AUTO:
        try:
            prefer_cdn = api.use_cdn(is_live)['useCDN']
        except Exception as e:
            log.debug('Failed to get preferred cdn')
            prefer_cdn = None

    providers = [prefer_cdn]
    providers.extend([s['provider'] for s in streams])

    streams = sorted(streams,
                     key=lambda k: (providers.index(k['provider']),
                                    SUPPORTED_FORMATS.index(k['mediaFormat'])))
    stream = streams[0]

    log.debug('Stream CDN: {provider} | Stream Format: {mediaFormat}'.format(
        **stream))

    item = plugin.Item(
        path=stream['manifest']['uri'],
        art=False,
        headers=HEADERS,
    )

    item.headers.update(
        {'authorization': 'Bearer {}'.format(userdata.get('access_token'))})

    if is_live and (play_type == PLAY_FROM_LIVE or
                    (play_type == PLAY_FROM_ASK
                     and gui.yes_no(_.PLAY_FROM,
                                    yeslabel=_.PLAY_FROM_LIVE,
                                    nolabel=_.PLAY_FROM_START))):
        play_type = PLAY_FROM_LIVE
        start_from = 0

    ## Cloudfront streams start from correct position
    if stream['provider'] == CDN_CLOUDFRONT and start_from:
        start_from = 1

    if stream['mediaFormat'] == FORMAT_DASH:
        item.inputstream = inputstream.MPD()

    elif stream['mediaFormat'] == FORMAT_HLS_TS:
        force = (is_live and play_type == PLAY_FROM_LIVE
                 and asset['assetType'] != 'live-linear')
        item.inputstream = inputstream.HLS(force=force, live=is_live)
        if force and not item.inputstream.check():
            raise PluginError(_.HLS_REQUIRED)

    elif stream['mediaFormat'] == FORMAT_HLS_FMP4:
        item.inputstream = inputstream.HLS(force=True, live=is_live)
        if not item.inputstream.check():
            raise PluginError(_.HLS_REQUIRED)

    elif stream['mediaFormat'] in (FORMAT_DRM_DASH, FORMAT_DRM_DASH_HEVC):
        item.inputstream = inputstream.Widevine(license_key=LICENSE_URL, )

    if start_from and not kwargs[ROUTE_RESUME_TAG]:
        item.properties['ResumeTime'] = start_from
        item.properties['TotalTime'] = start_from

    return item
Beispiel #26
0
def play(slug, skip_intro=None, **kwargs):
    data, content = api.play(slug)

    headers = {
        'Authorization': 'Bearer {}'.format(userdata.get('access_token')),
    }

    item = plugin.Item(
        path=data['url'],
        inputstream=inputstream.MPD(),
        headers=headers,
    )

    if 'drm' in data:
        item.inputstream = inputstream.Widevine(
            license_key=data['drm']['licenseUrl'])
        item.proxy_data['manifest_middleware'] = plugin.url_for(mpd_request)
        if settings.getBool('wv_secure'):
            item.inputstream.properties[
                'license_flags'] = 'force_secure_decoder'

    # resume_from = None
    # if kwargs[ROUTE_RESUME_TAG]:
    #     pass
    #     if settings.getBool('disney_sync', False):
    #         continue_watching = api.continue_watching()
    #         resume_from = continue_watching.get(video['contentId'], 0)
    #         item.properties['ForceResume'] = True

    # elif (int(skip_intro) if skip_intro is not None else settings.getBool('skip_intros', False)):
    #     resume_from = _get_milestone(data.get('annotations'), 'SKIP', default=0)

    # if resume_from is not None:
    #     item.properties['ResumeTime'] = resume_from
    #     item.properties['TotalTime']  = resume_from

    item.play_next = {}

    if ':episode' in slug:
        item.update(
            label=content['titles']['full'],
            art={
                'thumb': _image(content['images'].get('tileburnedin')),
                'fanart': _image(content['images'].get('tile'),
                                 size='1920x1080')
            },
            info={
                'plot':
                content['summaries']['short'],
                'duration':
                content['duration'],
                'tvshowtitle':
                content['seriesTitles']['full'],
                'season':
                content.get('seasonNumber', 1),
                'episode':
                content.get('numberInSeason', content.get('numberInSeries',
                                                          1)),
                'mediatype':
                'episode'
            },
        )

        if settings.getBool('play_next_episode', True):
            item.play_next['next_file'] = _get_play_path(content.get('next'))

    elif ':feature' in slug:
        item.update(
            label=content['titles']['full'],
            art={
                'thumb': _image(content['images'].get('tileburnedin')),
                'fanart': _image(content['images'].get('tile'),
                                 size='1920x1080')
            },
            info={
                'plot': content['summaries']['short'],
                'duration': content['duration'],
                'year': content['releaseYear'],
                'mediatype': 'movie',
            },
        )

        if settings.getBool('play_next_movie', False):
            for slug in content.get('similars', []):
                if ':feature' in slug:
                    item.play_next[
                        'next_file'] = 'urn:hbo:feature:' + slug.split(':')[3]
                    break

    for row in data.get('textTracks', []):
        item.subtitles.append([row['url'], row['language']])

    return item
Beispiel #27
0
def play(id, start_from=0, play_type=PLAY_FROM_LIVE, **kwargs):
    asset = api.stream(id)

    start_from = int(start_from)
    play_type = int(play_type)
    is_live = kwargs.get(ROUTE_LIVE_TAG) == ROUTE_LIVE_SUFFIX

    streams = [asset['recommendedStream']]
    streams.extend(asset['alternativeStreams'])
    streams = [s for s in streams if s['mediaFormat'] in SUPPORTED_FORMATS]

    if not streams:
        raise PluginError(_.NO_STREAM)

    providers = SUPPORTED_PROVIDERS[:]
    providers.extend([s['provider'] for s in streams])

    streams = sorted(streams,
                     key=lambda k: (providers.index(k['provider']),
                                    SUPPORTED_FORMATS.index(k['mediaFormat'])))
    stream = streams[0]

    log.debug('Stream CDN: {provider} | Stream Format: {mediaFormat}'.format(
        **stream))

    item = plugin.Item(
        path=stream['manifest']['uri'],
        art=False,
        headers=HEADERS,
        use_proxy=True,  #required to support dolby 5.1 and license requests
    )

    if is_live and (play_type == PLAY_FROM_LIVE or
                    (play_type == PLAY_FROM_ASK
                     and gui.yes_no(_.PLAY_FROM,
                                    yeslabel=_.PLAY_FROM_LIVE,
                                    nolabel=_.PLAY_FROM_START))):
        play_type = PLAY_FROM_LIVE
        start_from = 0

    if stream['mediaFormat'] == FORMAT_DASH:
        item.inputstream = inputstream.MPD()

    elif stream['mediaFormat'] == FORMAT_HLS_TS:
        force = (is_live and play_type == PLAY_FROM_LIVE)
        item.inputstream = inputstream.HLS(force=force, live=is_live)

        if force and not item.inputstream.check():
            raise PluginError(_.HLS_REQUIRED)

    elif stream['mediaFormat'] == FORMAT_HLS_FMP4:
        item.inputstream = inputstream.HLS(force=True, live=is_live)
        if not item.inputstream.check():
            raise PluginError(_.HLS_REQUIRED)

    elif stream['mediaFormat'] in (FORMAT_DRM_DASH, FORMAT_DRM_DASH_HEVC):
        item.inputstream = inputstream.Widevine(
            license_key=plugin.url_for(license_request))

    if start_from:
        item.properties['ResumeTime'] = start_from
        item.properties['TotalTime'] = start_from

    return item
def play(content_id=None, family_id=None, skip_intro=None, **kwargs):
    if KODI_VERSION > 18:
        ver_required = '2.6.0'
    else:
        ver_required = '2.4.5'

    ia = inputstream.Widevine(
        license_key=api.get_config()['services']['drm']['client']['endpoints']
        ['widevineLicense']['href'],
        manifest_type='hls',
        mimetype='application/vnd.apple.mpegurl',
    )

    if not ia.check() or not inputstream.require_version(ver_required):
        gui.ok(
            _(_.IA_VER_ERROR, kodi_ver=KODI_VERSION,
              ver_required=ver_required))

    if family_id:
        data = api.video_bundle(family_id)
        if not data.get('video'):
            raise PluginError(_.NO_VIDEO_FOUND)

        video = data['video']
    else:
        data = api.videos(content_id)
        if not data.get('videos'):
            raise PluginError(_.NO_VIDEO_FOUND)

        video = data['videos'][0]

    playback_url = video['mediaMetadata']['playbackUrls'][0]['href']
    playback_data = api.playback_data(playback_url)
    media_stream = playback_data['stream']['complete']
    original_language = video.get('originalLanguage') or 'en'

    headers = api.session.headers
    ia.properties['original_audio_language'] = original_language

    ## Allow fullres worldwide ##
    media_stream = media_stream.replace('/mickey/ps01/', '/ps01/')
    ##############

    item = _parse_video(video)
    item.update(
        path=media_stream,
        inputstream=ia,
        headers=headers,
        proxy_data={
            'default_language': original_language,
            'original_language': original_language
        },
    )

    if kwargs[ROUTE_RESUME_TAG] and settings.getBool('disney_sync', False):
        continue_watching = api.continue_watching()
        item.resume_from = continue_watching.get(video['contentId'], 0)
        item.force_resume = True

    elif (int(skip_intro) if skip_intro is not None else settings.getBool(
            'skip_intros', False)):
        item.resume_from = _get_milestone(
            video.get('milestones'), 'intro_end', default=0) / 1000

    item.play_next = {}

    if settings.getBool('skip_credits', False):
        next_start = _get_milestone(
            video.get('milestones'), 'up_next', default=0) / 1000
        item.play_next['time'] = next_start

    if video['programType'] == 'episode' and settings.getBool(
            'play_next_episode', True):
        data = api.up_next(video['contentId'])
        for row in data.get('items', []):
            if row['type'] == 'DmcVideo' and row[
                    'programType'] == 'episode' and row[
                        'encodedSeriesId'] == video['encodedSeriesId']:
                item.play_next['next_file'] = _get_play_path(row['contentId'])
                break

    elif video['programType'] != 'episode' and settings.getBool(
            'play_next_movie', False):
        data = api.up_next(video['contentId'])
        for row in data.get('items', []):
            if row['type'] == 'DmcVideo' and row['programType'] != 'episode':
                item.play_next['next_file'] = _get_play_path(row['contentId'])
                break

    if settings.getBool('wv_secure', False):
        item.inputstream.properties['license_flags'] = 'force_secure_decoder'

    if settings.getBool('disney_sync', False):
        telemetry = playback_data['tracking']['telemetry']
        item.callback = {
            'type':
            'interval',
            'interval':
            20,
            'callback':
            plugin.url_for(callback,
                           media_id=telemetry['mediaId'],
                           fguid=telemetry['fguid']),
        }

    return item
Beispiel #29
0
def play(asset_id, **kwargs):
    use_ia_hls = settings.getBool('use_ia_hls')
    stream_data = api.get_stream_data(asset_id)
    token = userdata.get('access_token')

    play_item = plugin.Item(
        art=False,
        headers={'Authorization': 'Bearer {}'.format(token)},
        cookies={
            'access_token': token,
            'client_id': CLIENT_ID
        },
    )

    is_drm = stream_data.get('course_is_drmed', False)

    hls_url = stream_data.get('hls_url')
    if hls_url and not is_drm:
        play_item.path = hls_url
        play_item.inputstream = inputstream.HLS(live=False)
        return play_item

    stream_urls = stream_data.get('stream_urls') or {}
    streams = stream_urls.get('Video') or stream_urls.get('Audio') or []

    CODECS = {
        'libx264': 'H.264',
        'libx265': 'H.265',
    }

    urls = []
    qualities = []
    for item in streams:
        if item['type'] != 'application/x-mpegURL':
            data = stream_data['data']['outputs'][item['label']]

            if data.get('migrated_from_non_labeled_conversions'):
                bandwidth, resolution = BANDWIDTH_MAP.get(int(item['label']))
                codecs, fps = '', ''
            else:
                fps = _(_.QUALITY_FPS, fps=float(data['frame_rate']))
                resolution = '{}x{}'.format(data['width'], data['height'])
                bandwidth = data[
                    'video_bitrate_in_kbps'] * 1000  #(or total_bitrate_in_kbps)
                codecs = CODECS.get(data.get('video_codec'), '')

            urls.append([bandwidth, item['file']])
            qualities.append([
                bandwidth,
                _(_.QUALITY_BITRATE,
                  bandwidth=float(bandwidth) / 1000000,
                  resolution=resolution,
                  fps=fps,
                  codecs=codecs)
            ])

    if not urls:
        for row in stream_data.get('media_sources') or []:
            if row['type'] == 'application/x-mpegURL' and 'encrypted-files' not in row[
                    'src']:
                urls.append([row['src'], inputstream.HLS(live=False)])

            if row['type'] == 'application/dash+xml':
                play_item.path = row['src']

                if is_drm:
                    token = stream_data['media_license_token']
                    ia = inputstream.Widevine(license_key=WV_URL.format(
                        token=token))
                else:
                    ia = inputstream.MPD()

                urls.append([row['src'], ia])

        if urls:
            urls = sorted(urls,
                          key=lambda x: isinstance(x[1], inputstream.Widevine))
            play_item.path = urls[0][0]
            play_item.inputstream = urls[0][1]
            if isinstance(play_item.inputstream, inputstream.Widevine):
                system, arch = get_system_arch()
                if system == 'Windows' or (system == 'Linux'
                                           and arch == 'armv7'):
                    gui.ok(_.VMP_WARNING)

            return play_item

    if not urls:
        raise plugin.Error(_.NO_STREAM_ERROR)

    quality = kwargs.get(QUALITY_TAG)
    if quality is None:
        quality = settings.getEnum('default_quality',
                                   QUALITY_TYPES,
                                   default=QUALITY_ASK)
    else:
        quality = int(quality)

    urls = sorted(urls, key=lambda s: s[0], reverse=True)
    qualities = sorted(qualities, key=lambda s: s[0], reverse=True)

    if quality == QUALITY_CUSTOM:
        quality = int(settings.getFloat('max_bandwidth') * 1000000)
    elif quality == QUALITY_ASK:
        quality = select_quality(qualities)

    if quality == QUALITY_BEST:
        quality = qualities[0][0]
    elif quality == QUALITY_LOWEST:
        quality = qualities[-1][0]

    play_item.path = urls[-1][1]
    for item in urls:
        if item[0] <= quality:
            play_item.path = item[1]
            break

    return play_item