xbmc / inputstream.adaptive

kodi inputstream addon for several manifest types
Other
452 stars 241 forks source link

1 minute token validity #199

Closed heddock closed 2 years ago

heddock commented 5 years ago

Hi,

i have created an addon which is working very nice with inputstream.adaptive. The problem however lies in the fact the server will use tokens. The steps i have to take to accomplish a valid stream are:

After this the stream starts playing succesfully for 1 minute because the token is only valid for 1 minute. After this a new token must be retrieved and the url of the playing video must be updated to the new url.

Is this possible? And if so how can i do that?

Thanks in advance.

glennguy commented 5 years ago

This might be what you're looking for: https://github.com/peak3d/inputstream.adaptive/issues/92. Some of the links are broken but from what I can see you need to allow for a plugin call to renew the cookie and return it in a 1 item directory listing.

For example you could setup your addon/default.py to catch the plugin call to plugin://your.addon.id/?action=renew_token which would run a function that is basically like this one here. Then you just need to tell inputstream.adaptive by setting `listitem.setProperty('inputstream.adaptive.media_renewal_url', 'plugin://your.addon.id/?action=renew_token') and when you get a 403 inputstream.adaptive will make the call for the new token.

Haven't tried this myself, has been no need but looks like it should work. Hope this helps!

heddock commented 5 years ago

This might be what you're looking for: #92. Some of the links are broken but from what I can see you need to allow for a plugin call to renew the cookie and return it in a 1 item directory listing.

For example you could setup your addon/default.py to catch the plugin call to plugin://your.addon.id/?action=renew_token which would run a function that is basically like this one here. Then you just need to tell inputstream.adaptive by setting `listitem.setProperty('inputstream.adaptive.media_renewal_url', 'plugin://your.addon.id/?action=renew_token') and when you get a 403 inputstream.adaptive will make the call for the new token.

Haven't tried this myself, has been no need but looks like it should work. Hope this helps!

Thanks very much for your answer. I tested your approach but unfortunately without success.

What i did:

This way the function is not called directly. Kodi log: 20:44:04.377 T:484596434000 ERROR: AddOnLog: InputStream Adaptive: Retrieving renewal URL failed ({pluginid}?action=renew_token)

When i catch the action i can execute a function myself but i am not able to return the new url. mode = args.get('action', None) if mode == 'renew_token' ...

When i return the value in the main file i got the error Error Contents: 'return' outside function (default.py, line 512)

I have also added the library in the addon.xml <extension point="xbmc.python.module" library="default.py" />

Am i missing something? How can i create a function which is accessible from the outside?

I am not very familiar with python so i would be very gratefull i you could help me with this again. Thanks

JinRonin commented 5 years ago

Dont 'return', but create a directory item with the new url. Examples have been posted by glennguy

glennguy commented 5 years ago

Am i missing something? How can i create a function which is accessible from the outside?

Without seeing your code you need to make sure you have a router set up like in this tutorial: https://kodi.wiki/view/HOW-TO:Video_addon and then add the logic to that. Each time you invoke your addon by starting it or clicking on a menu item you parse the url of the listitem and determine what to do from there. In this case, we're just giving the url to call directly to inputstream.adaptive.

Turn on debug logging and go through the menus of your favourite addon and then look at the log, that's the quickest way to explain.

From your log 20:44:04.377 T:484596434000 ERROR: AddOnLog: InputStream Adaptive: Retrieving renewal URL failed ({pluginid}?action=renew_token) you've missed formatting {plugin} (or {pluginid}, was that a change?) to the actual plugin id eg. plugin.video.youtube

I'll be nice and do a whole example:

import sys
import xbmcgui
import xbmcplugin
from urlparse import parse_qsl

_handle = int(sys.argv[1])

def get_license_key():
    # insert your code here to get the key url
    pass

def renew_token():
    listitem = xbmcgui.ListItem()
    xbmcplugin.addDirectoryItem(int(sys.argv[1]), get_license_key(), listitem)
    xbmcplugin.endOfDirectory(int(sys.argv[1]), cacheToDisc=False)

def router(paramstring):
    params = dict(parse_qsl(paramstring))
    if params['action'] == 'renew_token':
        renew_token()

if __name__ == '__main__':
    router(sys.argv[2][1:])

Hope this helps!

heddock commented 5 years ago

@glennguy and @JinRonin

Thank you all for your time and information and sorry for my slow understanding. I misread the post of glennguy because of the return word mentioned.

glennguy:

I tried what you stated in your last post. My code:

def router():
    ...
    mode = args.get('mode', None)

        if mode:
            ...
            if mode[0] == "renew_token":
                renew_token()
            else:
                raise ValueError("Invalid paramstring: {0}!".format(mode[0]))
        else:
            list_folders()    

def play_video(url):
    newItem = getPlayListItem(args.get('contentlocator')[0], url)
    xbmcplugin.setResolvedUrl(addon_handle, True, listitem=newItem)

def getPlayListItem(contentlocator, originalUrl):
    playToken = getToken(contentlocator)

    #getLicenseKey    
    licenseKey = getLicenseKey(contentlocator, playToken)

    #construct URL    
    url = originalUrl.replace('/manifest.mpd', ';vxttoken=' + playToken + '/manifest.mpd')

    #contruct listitem to play video
    newItem = xbmcgui.ListItem(path=url)
    newItem.setProperty("inputstreamaddon", "inputstream.adaptive")
    newItem.setProperty("inputstream.adaptive.manifest_type", "mpd")
    newItem.setProperty("inputstream.adaptive.license_type","com.widevine.alpha")
    newItem.setProperty("inputstream.adaptive.license_key", licenseKey)
    newItem.setProperty("inputstream.adaptive.media_renewal_url"', base_url + "?mode=renew_token&contentlocator=" + args.get("contentlocator")[0] + "&url=" + originalUrl + "&userToken=" + userToken) 

    return newItem

def renew_token():
    global userToken

    xbmc.log("#### NEW TOKEN ####",2)

    contentLocator = args.get("contentlocator")[0]
    url = args.get("url")[0]

    playToken = getToken(contentLocator)
    url = url.replace("/manifest.mpd", ";vxttoken=" + playToken)

    xbmc.log("new url : " + url,2)

    listitem = xbmcgui.ListItem()
    xbmcplugin.addDirectoryItem(addon_handle, url, listitem)
    xbmcplugin.endOfDirectory(addon_handle, cacheToDisc=False)

When starting the video play_video is called with the url. This originalUrl is passed to the listitem link so it can be reused in renew_token. In the log i see that the renew_item method is executed and that it will generate a new valid url with a new token. This token is used to create a new listitem and passed. However when the new mp4 file is queried it will still use the old url and token.

00:02:53.194 T:484702991440 NOTICE: Handle : 3 Mode : 'play' 00:02:53.585 T:485053441104 NOTICE: VideoPlayer::OpenFile: plugin://plugin.video.pluginname/?userToken=00babad72dc0cc32c353a7696add23cf6cf4bc6bc067c4d7964e2fdf7021590c&locationID=24443942973&contentlocator=urn%3Aorion%3Amedia%3Astd%3AjktZWAWs_7pv&mode=play&playlink=http%3A%2F%2Fhostnameofprovider%2Fdash%2FVeronica_HD%2Fmanifest.mpd 00:02:53.586 T:485053441104 ERROR: CCurlFile::Stat - Failed: Unsupported protocol(1) for plugin://plugin.video.pluginname/?userToken=00babad72dc0cc32c353a7696add23cf6cf4bc6bc067c4d7964e2fdf7021590c&locationID=24443942973&contentlocator=urn%3Aorion%3Amedia%3Astd%3AjktZWAWs_7pv&mode=play&playlink=http%3A%2F%2Fhostnameofprovider%2Fdash%2FVeronica_HD%2Fmanifest.mpd 00:02:53.590 T:484702991440 NOTICE: Creating InputStream 00:02:53.650 T:484702991440 ERROR: AddOnLog: InputStream Adaptive: Key system request: com.widevine.alpha 00:02:53.672 T:484843775056 NOTICE: PrimeWire: Service: Playback started 00:02:54.559 T:484702991440 NOTICE: Creating Demuxer 00:02:54.561 T:484702991440 NOTICE: Opening stream: 1 source: 256 00:02:54.579 T:484702991440 NOTICE: Creating video codec with codec id: 27 00:02:54.621 T:484702991440 NOTICE: CDVDVideoCodecAndroidMediaCodec::Open Testing codec:OMX.amlogic.hevc.decoder.awesome 00:02:54.622 T:484702991440 NOTICE: CDVDVideoCodecAndroidMediaCodec::Open Testing codec:OMX.amlogic.avc.decoder.awesome 00:02:54.737 T:484702991440 NOTICE: Creating video thread 00:02:54.744 T:484565939280 NOTICE: running thread: video_thread 00:02:54.766 T:484702991440 NOTICE: Opening stream: 2 source: 256 00:02:54.784 T:484702991440 NOTICE: Finding audio codec for: 86018 00:02:54.810 T:484702991440 NOTICE: CDVDAudioCodecFFmpeg::Open() Successful opened audio decoder aac 00:02:54.825 T:484702991440 NOTICE: Creating audio thread 00:02:54.832 T:484702991440 NOTICE: Opening stream: 3 source: 256 00:02:54.834 T:484562830416 NOTICE: running thread: CVideoPlayerAudio::Process() 00:02:55.146 T:484562830416 NOTICE: CDVDAudioCodecFFmpeg::Open() Successful opened audio decoder aac 00:02:55.249 T:484562830416 NOTICE: Creating audio stream (codec id: 86018, channels: 2, sample rate: 44100, no pass-through) 00:02:55.280 T:485053441104 NOTICE: Instancing CRendererMediaCodecSurface 00:02:55.280 T:485053441104 NOTICE: CRendererMediaCodecSurface::Configure 00:02:55.335 T:484916368464 NOTICE: Trying to open: samplerate: 44100, channelMask: 252, encoding: 4 00:02:55.344 T:484916368464 NOTICE: CAESinkAUDIOTRACK::Initializing with: m_sampleRate: 44100 format: AE_FMT_FLOAT (AE) method: PCM stream-type: PCM-STREAM min_buffer_size: 135936 m_frames: 2832 m_frameSize: 24 channels: 6

Now the video is playing correctly (dispite of the errors in de log). After some time the token becomes invalid and it will call renew_token.

00:02:56.292 T:484863636560 ERROR: CCurlFile::FillBuffer - Failed: Timeout was reached(28) 00:02:56.293 T:484863636560 WARNING: CCurlFile::FillBuffer - Reconnect, (re)try 1 00:02:56.671 T:484753548368 ERROR: CCurlFile::FillBuffer - Failed: Timeout was reached(28) 00:02:56.672 T:484753548368 WARNING: CCurlFile::FillBuffer - Reconnect, (re)try 1 00:03:16.936 T:484753548368 ERROR: CCurlFile::FillBuffer - Failed: Timeout was reached(28) 00:03:16.937 T:484753548368 WARNING: CCurlFile::FillBuffer - Reconnect, (re)try 2 00:03:17.554 T:484863636560 ERROR: CCurlFile::FillBuffer - Failed: Timeout was reached(28) 00:03:17.555 T:484863636560 WARNING: CCurlFile::FillBuffer - Reconnect, (re)try 2 00:03:38.194 T:484753548368 ERROR: CCurlFile::FillBuffer - Failed: Timeout was reached(28) 00:03:38.527 T:484753548368 ERROR: CAddonMgr: Failed to parse addons.xml. 00:03:38.811 T:484863636560 ERROR: CCurlFile::FillBuffer - Failed: Timeout was reached(28) 00:03:39.633 T:484863636560 ERROR: CAddonMgr: Failed to parse addons.xml. 00:05:23.960 T:484863636560 NOTICE: Args : {'url': ['http://hostnameofprovider/dash/Veronica_HD/manifest.mpd'], 'contentlocator': ['urn:orion:media:std:jktZWAWs_7pv'], 'mode': ['renew_token'], 'userToken': ['00babad72dc0cc32c353a7696add23cf6cf4bc6bc067c4d7964e2fdf7021590c']} 00:05:23.962 T:484863636560 NOTICE: Handle : 4 Mode : 'renew_token' 00:05:23.962 T:484863636560 NOTICE: #### NEW TOKEN #### 00:05:24.162 T:484863636560 NOTICE: new url : http://hostnameofprovider/dash/Veronica_HD;vxttoken=cGF0aFVSST0lMkZkYXNoJTJGVmVyb25pY2FfSEQlMkYlMkEmZXhwaXJ5PTE1NDA3NjgwNzgmZm49c2hhMjU2JnJldXNlPS0xJmMtaXAtdW5sb2NrZWQ9MSZ4JTNBZ3VpZD04MGMxY2MwYS04ODRjLTRlYmUtYTUwYS0zZjE3MDdjODAxOWMmeCUzQXN0cmVhbXNlc3Npb25pZD1lMWVjZmRmNC1jZGYxLTQ2MGQtODhjYS0yNmMwNTc3NjcwOGIsYjJkMDNlZWE1Yjk4YWNkNjBkYmJmZjBkYmU5YzRlM2ExNWU5YThhYjlkOGJlMDkyZjg1YmZlNTRkNmI2YWNmNg== 00:05:24.179 T:484701955152 ERROR: AddOnLog: InputStream Adaptive: Download http://hostnameofprovider/dash/Veronica_HD;vxttoken=cGF0aFVSST0lMkZkYXNoJTJGVmVyb25pY2FfSEQlMkYlMkEmZXhwaXJ5PTE1NDA3Njc5MjcmZm49c2hhMjU2JnJldXNlPS0xJmMtaXAtdW5sb2NrZWQ9MSZ4JTNBZ3VpZD1iNDc1YzEzMy02MzZiLTRlYzYtOTlkNi1mN2ViZDdkMWJjOTEmeCUzQXN0cmVhbXNlc3Npb25pZD1hY2RkNjFjNS0zMTE0LTQ2MzgtODBlYS1mMmIzZTJiNDcxOWIsZDNiZjIxMDQ2NjI3ZjA2ZjE0ZTllMTdlMzZlNzExZDIwOWE2MzA3ZWJkYmE5ZDA1MDFkZDhhNGYzY2Q0ZjA3ZQ==/video2/1422292.m4s failed with error: 403 00:05:25.462 T:484863636560 NOTICE: Args : {'url': ['http://hostnameofprovider/dash/Veronica_HD/manifest.mpd'], 'contentlocator': ['urn:orion:media:std:jktZWAWs_7pv'], 'mode': ['renew_token'], 'userToken': ['00babad72dc0cc32c353a7696add23cf6cf4bc6bc067c4d7964e2fdf7021590c']} 00:05:25.463 T:484863636560 NOTICE: Handle : 5 Mode : 'renew_token'

After this it will repeat itself for 21 times. The line new url provides the new url:

00:05:24.162 T:484863636560 NOTICE: new url : http://hostnameofprovider/dash/Veronica_HD;vxttoken=cGF0aFVSST0lMkZkYXNoJTJGVmVyb25pY2FfSEQlMkYlMkEmZXhwaXJ5PTE1NDA3NjgwNzgmZm49c2hhMjU2JnJldXNlPS0xJmMtaXAtdW5sb2NrZWQ9MSZ4JTNBZ3VpZD04MGMxY2MwYS04ODRjLTRlYmUtYTUwYS0zZjE3MDdjODAxOWMmeCUzQXN0cmVhbXNlc3Npb25pZD1lMWVjZmRmNC1jZGYxLTQ2MGQtODhjYS0yNmMwNTc3NjcwOGIsYjJkMDNlZWE1Yjk4YWNkNjBkYmJmZjBkYmU5YzRlM2ExNWU5YThhYjlkOGJlMDkyZjg1YmZlNTRkNmI2YWNmNg==

But the next attempt for the video will still use the old value:

00:05:24.179 T:484701955152 ERROR: AddOnLog: InputStream Adaptive: Download http://hostnameofprovider/dash/Veronica_HD;vxttoken=cGF0aFVSST0lMkZkYXNoJTJGVmVyb25pY2FfSEQlMkYlMkEmZXhwaXJ5PTE1NDA3Njc5MjcmZm49c2hhMjU2JnJldXNlPS0xJmMtaXAtdW5sb2NrZWQ9MSZ4JTNBZ3VpZD1iNDc1YzEzMy02MzZiLTRlYzYtOTlkNi1mN2ViZDdkMWJjOTEmeCUzQXN0cmVhbXNlc3Npb25pZD1hY2RkNjFjNS0zMTE0LTQ2MzgtODBlYS1mMmIzZTJiNDcxOWIsZDNiZjIxMDQ2NjI3ZjA2ZjE0ZTllMTdlMzZlNzExZDIwOWE2MzA3ZWJkYmE5ZDA1MDFkZDhhNGYzY2Q0ZjA3ZQ==/video2/1422292.m4s failed with error: 403

So it looks like the new url is not used at all. Previously i got the error that the new url could not be read or something. Because this error is not present anymore i assume the code of setting this new url is correct now?

Can you see something i'm doing wrong? I saw a thread 145 having the same problem. Unfortunately the last message from @peak3d was not answered anymore. I have already implemented the solution he suggested there.

Can you see what the problem might be? Many thanks.

glennguy commented 5 years ago

@heddock No need to apologise, happy to help. Interested in what is going on with this: 00:02:53.650 T:484702991440 ERROR: AddOnLog: InputStream Adaptive: Key system request: com.widevine.alpha - but debug logging is not on... Can you please turn on debug logging and provide a full log to pastebin or similar and put the link here? Don't turn on component logging though.

heddock commented 5 years ago

Can you please turn on debug logging and provide a full log to pastebin or similar and put the link here?

i have runned this script on my android device before. Because i'm on my work now i am running it on a windows pc. The logging can be found here: logging.

The specific error line is not in this log so it is probably a android thing.

new url : http://hostnameofprovider/dash/Nederland_2_HD;vxttoken=cGF0aFVSST0lMkZkYXNoJTJGTmVkZXJsYW5kXzJfSEQlMkYlMkEmZXhwaXJ5PTE1NDA4MDY2MDEmZm49c2hhMjU2JnJldXNlPS0xJmMtaXAtdW5sb2NrZWQ9MSZ4JTNBZ3VpZD1lNGE0ZTdhZi1mODQ1LTQ3ZDItOWVkYS1kYWE3OWExZTQ2NjkmeCUzQXN0cmVhbXNlc3Npb25pZD01OWRkYzYzNy1hODJmLTRhN2EtYTEzNS02NTRmMmYzOWRkZDcsOTU0ZTRlZjUzMmQ5N2Y0ODc1NjUxNjNhNGE0MDVjMmJhYzc0M2I5MjI0Zjg2ODk2OGU1MWZhYTY3MzJjZWQ1OQ== 10:47:31.568 T:12332 INFO: CPythonInvoker(5, C:\Users\fameul\AppData\Roaming\Kodi\addons\plugin.video.pluginname\default.py): script successfully run 10:47:31.568 T:12332 DEBUG: CPythonInvoker::onExecutionDone(5, C:\Users\fameul\AppData\Roaming\Kodi\addons\plugin.video.pluginname\default.py) 10:47:31.568 T:13488 DEBUG: AddOnLog: InputStream Adaptive: Renewed URL: http://hostnameofprovider/dash/Nederland_2_HD;vxttoken=cGF0aFVSST0lMkZkYXNoJTJGTmVkZXJsYW5kXzJfSEQlMkYlMkEmZXhwaXJ5PTE1NDA4MDY2MDEmZm49c2hhMjU2JnJldXNlPS0xJmMtaXAtdW5sb2NrZWQ9MSZ4JTNBZ3VpZD1lNGE0ZTdhZi1mODQ1LTQ3ZDItOWVkYS1kYWE3OWExZTQ2NjkmeCUzQXN0cmVhbXNlc3Npb25pZD01OWRkYzYzNy1hODJmLTRhN2EtYTEzNS02NTRmMmYzOWRkZDcsOTU0ZTRlZjUzMmQ5N2Y0ODc1NjUxNjNhNGE0MDVjMmJhYzc0M2I5MjI0Zjg2ODk2OGU1MWZhYTY3MzJjZWQ1OQ==

new url is my logging and you can see that it also picked up by inputstream adaptive however it is not used by the next call

http://hostnameofprovider/dash/Nederland_2_HD;vxttoken=cGF0aFVSST0lMkZkYXNoJTJGTmVkZXJsYW5kXzJfSEQlMkYlMkEmZXhwaXJ5PTE1NDA4MDY0NTAmZm49c2hhMjU2JnJldXNlPS0xJmMtaXAtdW5sb2NrZWQ9MSZ4JTNBZ3VpZD05OTI4ZTYxMy1hMzNkLTQ5NjEtOGJlOC0zNzY5ZWFjZmYxZjQmeCUzQXN0cmVhbXNlc3Npb25pZD0wYjQyZGFkMS03ZDEwLTQ1MjgtYjU1Zi04NjJkN2Q3MzVhNDEsMzFjNzI3ZGY4MTM0MTEyNTBhYmI3YjNhMTdhMTE5YWQ2YWQxY2VhOTM3ZWJlNzJhY2Y4ZjdlYjliZGYxYjc0OQ==/audio2/1441556.m4s failed with error: 403

peak3d commented 5 years ago

I would like to test the addon to reproduce the issue, possible? If so, we can continue via mail (see github contact)

heddock commented 5 years ago

I would like to test the addon to reproduce the issue, possible? If so, we can continue via mail (see github contact)

the problem is that i cannot share my credentials because they are not mine. I extracted all the relevant code in my previous post so there is no more code to share i think which can effect this issue. Can i support you another way? Is it maybe possible for you to put in extra lines of logging in your code so i can run it again?

heddock commented 5 years ago

@peak3d @glennguy

i did some more research and i think the problem that the renew action is not working correctly:

21:14:23.337 T:21096 NOTICE: #### NEW TOKEN #### 21:14:23.337 T:21096 NOTICE: new url : http://hostname/dash/Nederland_1_HD;vxttoken=cGF0aFVSST0lMkZkYXNoJTJGTmVkZXJsYW5kXzFfSEQlMkYlMkEmZXhwaXJ5PTE1NDA4NDQxODEmZm49c2hhMjU2JnJldXNlPS0xJmMtaXAtdW5sb2NrZWQ9MSZ4JTNBZ3VpZD1hZTUyNjNmMS04MDcyLTQ4ZDQtOTA5MS00Mjk3ZTAzNjljN2MmeCUzQXN0cmVhbXNlc3Npb25pZD0xYzIwZmRiMi1jNWE1LTRmMzAtYmI4NC1lYzczZGQxZmUyNmIsNGIxMjE3ZGE4ZTUyMzg4NDE1MmI1MGM5NjNlZGQwMzdmNWJkNDdlOWEzOWIyMjIzMDJhYjI5ZDE4NDZlMDdmYw== 21:14:23.337 T:21096 INFO: CPythonInvoker(5, C:\Users\fameul\AppData\Roaming\Kodi\addons\plugin.video.pluginname\default.py): script successfully run 21:14:23.337 T:21096 DEBUG: CPythonInvoker::onExecutionDone(5, C:\Users\fameul\AppData\Roaming\Kodi\addons\plugin.video.pluginname\default.py) 21:14:23.337 T:19228 DEBUG: AddOnLog: InputStream Adaptive: Renewed URL: http://hostname/dash/Nederland_1_HD;vxttoken=cGF0aFVSST0lMkZkYXNoJTJGTmVkZXJsYW5kXzFfSEQlMkYlMkEmZXhwaXJ5PTE1NDA4NDQxODEmZm49c2hhMjU2JnJldXNlPS0xJmMtaXAtdW5sb2NrZWQ9MSZ4JTNBZ3VpZD1hZTUyNjNmMS04MDcyLTQ4ZDQtOTA5MS00Mjk3ZTAzNjljN2MmeCUzQXN0cmVhbXNlc3Npb25pZD0xYzIwZmRiMi1jNWE1LTRmMzAtYmI4NC1lYzczZGQxZmUyNmIsNGIxMjE3ZGE4ZTUyMzg4NDE1MmI1MGM5NjNlZGQwMzdmNWJkNDdlOWEzOWIyMjIzMDJhYjI5ZDE4NDZlMDdmYw== 21:14:23.337 T:19228 DEBUG: CurlFile::ParseAndCorrectUrl() adding custom header option 'connection: keep-alive' 21:14:23.337 T:19228 DEBUG: CurlFile::Open(0x1fff88847a0) http://hostname/dash/Nederland_1_HD;vxttoken=cGF0aFVSST0lMkZkYXNoJTJGTmVkZXJsYW5kXzFfSEQlMkYlMkEmZXhwaXJ5PTE1NDA4NDQwNjEmZm49c2hhMjU2JnJldXNlPS0xJmMtaXAtdW5sb2NrZWQ9MSZ4JTNBZ3VpZD1hODMxNjNiYi1jYzEyLTQyNjktODU2OS03MTM1ZjVhZjI4ZGUmeCUzQXN0cmVhbXNlc3Npb25pZD0xYzIwZmRiMi1jNWE1LTRmMzAtYmI4NC1lYzczZGQxZmUyNmIsMGQxMzU5MTEyZDZhNjIwM2ZlNTkyYjZiOTVjZmI1Mzg2ZDZkYjk3MGM1M2E1ZTg5NDI5Y2QxOWRmNjFiOWUxYQ==/video1/1460359.m4s 21:14:23.338 T:21096 INFO: Python interpreter stopped 21:14:23.338 T:21096 DEBUG: Thread LanguageInvoker 21096 terminating 21:14:23.343 T:19228 ERROR: AddOnLog: InputStream Adaptive: Download http://hostname/dash/Nederland_1_HD;vxttoken=cGF0aFVSST0lMkZkYXNoJTJGTmVkZXJsYW5kXzFfSEQlMkYlMkEmZXhwaXJ5PTE1NDA4NDQwNjEmZm49c2hhMjU2JnJldXNlPS0xJmMtaXAtdW5sb2NrZWQ9MSZ4JTNBZ3VpZD1hODMxNjNiYi1jYzEyLTQyNjktODU2OS03MTM1ZjVhZjI4ZGUmeCUzQXN0cmVhbXNlc3Npb25pZD0xYzIwZmRiMi1jNWE1LTRmMzAtYmI4NC1lYzczZGQxZmUyNmIsMGQxMzU5MTEyZDZhNjIwM2ZlNTkyYjZiOTVjZmI1Mzg2ZDZkYjk3MGM1M2E1ZTg5NDI5Y2QxOWRmNjFiOWUxYQ==/video1/1460359.m4s failed with error: 403

When i manually open (chrome) the url where the error occurs i will get same 403 Forbidden message

21:14:23.343 T:19228 ERROR: AddOnLog: InputStream Adaptive: Download http://hostname/dash/Nederland_1_HD;vxttoken=cGF0aFVSST0lMkZkYXNoJTJGTmVkZXJsYW5kXzFfSEQlMkYlMkEmZXhwaXJ5PTE1NDA4NDQwNjEmZm49c2hhMjU2JnJldXNlPS0xJmMtaXAtdW5sb2NrZWQ9MSZ4JTNBZ3VpZD1hODMxNjNiYi1jYzEyLTQyNjktODU2OS03MTM1ZjVhZjI4ZGUmeCUzQXN0cmVhbXNlc3Npb25pZD0xYzIwZmRiMi1jNWE1LTRmMzAtYmI4NC1lYzczZGQxZmUyNmIsMGQxMzU5MTEyZDZhNjIwM2ZlNTkyYjZiOTVjZmI1Mzg2ZDZkYjk3MGM1M2E1ZTg5NDI5Y2QxOWRmNjFiOWUxYQ==/video1/1460359.m4s failed with error: 403

When i update the link with the new token which is in the new line it is working correctly in chrome:

21:14:23.337 T:19228 DEBUG: AddOnLog: InputStream Adaptive: Renewed URL: http://hostname/dash/Nederland_1_HD;vxttoken=cGF0aFVSST0lMkZkYXNoJTJGTmVkZXJsYW5kXzFfSEQlMkYlMkEmZXhwaXJ5PTE1NDA4NDQxODEmZm49c2hhMjU2JnJldXNlPS0xJmMtaXAtdW5sb2NrZWQ9MSZ4JTNBZ3VpZD1hZTUyNjNmMS04MDcyLTQ4ZDQtOTA5MS00Mjk3ZTAzNjljN2MmeCUzQXN0cmVhbXNlc3Npb25pZD0xYzIwZmRiMi1jNWE1LTRmMzAtYmI4NC1lYzczZGQxZmUyNmIsNGIxMjE3ZGE4ZTUyMzg4NDE1MmI1MGM5NjNlZGQwMzdmNWJkNDdlOWEzOWIyMjIzMDJhYjI5ZDE4NDZlMDdmYw==

I think this will prove that the new url/token is not used correctly by inputstream.adaptive right?

glennguy commented 5 years ago

@heddock you may be right

@peak3d https://github.com/peak3d/inputstream.adaptive/blob/8bfd456a556ab43976c2023ffbd2eb2e48a965cf/src/main.cpp#L359 seems to set the new url in the adaptivetree but doesn't update downloadurl for the retry. Would changing https://github.com/peak3d/inputstream.adaptive/blob/ef3cefb1e6b1363f511345bc74b6a7f1fb6d95e4/src/common/AdaptiveStream.h#L81 to void setEffectiveURL(const std::string url) { tree_.effective_url_ = url, download_url_ = url; }; be an acceptable fix for this?

peak3d commented 5 years ago

@glennguy it should at least work once:

https://github.com/peak3d/inputstream.adaptive/blob/master/src/common/AdaptiveStream.cpp#L304

Edit: Correction: it should work always

peak3d commented 5 years ago

My feeling is that this addon is not legal, reason is that only minimal information are provided - too time consuming for me beside the fact that I don't support illegal addons. @heddock pls. compile kodi by yourself, including inputstream.adaptiive, and analyze the code line I linked in the previous ticket.

Edit: Even it will not fix the issue, the renewalurl must end with a slash.

heddock commented 5 years ago

@glennguy Thanks for the reponse and nice to hear that you have found the code which should be responsible.

@peak3d Also thanks for your time. I want to repond to you feeling.

Part 1:

i do not provide hostnames and stuff is because i do not know if the addon will be legal. I'm trying to make an addon for a iptv provider which has a html5 page created to watch tv. There is also an (android/IOS) app available but no kodi plugin. Their conditions include the following:

And because those terms are not detailed enough i cannot tell you if it will be completely legal. When i provide those details it will be tracable. Hope you will understand.

Part 2:

the inputstream.adaptive is a technique which has nothing to do with a service whatsoever. There are plenty of services which are using the same technique. So i think you are not providing to a (maybe) illegal service but only creating a plugin which will implement this technique. It is like "i'm not building a gun because people can do crazy stuff with it". I think it is the responsibility of the one who is creating the addon.

About the trailing "/" this is not a problem. I also tried it with a slash and i can easily add it.

When i compile Kodi and inputstream.adaptive myself this will not become part of the normal installation of Kodi. New addons will also have this problem when using this technique.

Besides that I have no idea how to compile kodi for android and windows. Can you point me in a direction how to do that?

Again many thanks...

glennguy commented 5 years ago

@heddock https://github.com/xbmc/xbmc/blob/master/docs/README.md

@peak3d forgive me as I can't find where PrepareDownload is called from inside the download method https://github.com/peak3d/inputstream.adaptive/blob/master/src/common/AdaptiveStream.cpp#L242

I can see that tree_.effective_url_ is being updated with the renewal url, but immediately after we goto RETRY which executes another file.CURLCreate(url) - where url points to download_url_, which as far as I can see has not been updated with the renewal url. Therefore we see what is in this log:

10:47:31.568 T:13488   DEBUG: AddOnLog: InputStream Adaptive: Renewed URL: http://hostnameofprovider/dash/Nederland_2_HD;vxttoken=cGF0aFVSST0lMkZkYXNoJTJGTmVkZXJsYW5kXzJfSEQlMkYlMkEmZXhwaXJ5PTE1NDA4MDY2MDEmZm49c2hhMjU2JnJldXNlPS0xJmMtaXAtdW5sb2NrZWQ9MSZ4JTNBZ3VpZD1lNGE0ZTdhZi1mODQ1LTQ3ZDItOWVkYS1kYWE3OWExZTQ2NjkmeCUzQXN0cmVhbXNlc3Npb25pZD01OWRkYzYzNy1hODJmLTRhN2EtYTEzNS02NTRmMmYzOWRkZDcsOTU0ZTRlZjUzMmQ5N2Y0ODc1NjUxNjNhNGE0MDVjMmJhYzc0M2I5MjI0Zjg2ODk2OGU1MWZhYTY3MzJjZWQ1OQ==
10:47:31.568 T:13488   DEBUG: CurlFile::ParseAndCorrectUrl() adding custom header option 'connection: keep-alive'
10:47:31.568 T:13488   DEBUG: CurlFile::Open(0x17dfaa89760) http://hostnameofprovider/dash/Nederland_2_HD;vxttoken=cGF0aFVSST0lMkZkYXNoJTJGTmVkZXJsYW5kXzJfSEQlMkYlMkEmZXhwaXJ5PTE1NDA4MDY0NTAmZm49c2hhMjU2JnJldXNlPS0xJmMtaXAtdW5sb2NrZWQ9MSZ4JTNBZ3VpZD05OTI4ZTYxMy1hMzNkLTQ5NjEtOGJlOC0zNzY5ZWFjZmYxZjQmeCUzQXN0cmVhbXNlc3Npb25pZD0wYjQyZGFkMS03ZDEwLTQ1MjgtYjU1Zi04NjJkN2Q3MzVhNDEsMzFjNzI3ZGY4MTM0MTEyNTBhYmI3YjNhMTdhMTE5YWQ2YWQxY2VhOTM3ZWJlNzJhY2Y4ZjdlYjliZGYxYjc0OQ==/audio2/1441556.m4s
10:47:31.571 T:12332    INFO: Python interpreter stopped
10:47:31.571 T:12332   DEBUG: Thread LanguageInvoker 12332 terminating
10:47:31.593 T:13488   ERROR: AddOnLog: InputStream Adaptive: Download http://hostnameofprovider/dash/Nederland_2_HD;vxttoken=cGF0aFVSST0lMkZkYXNoJTJGTmVkZXJsYW5kXzJfSEQlMkYlMkEmZXhwaXJ5PTE1NDA4MDY0NTAmZm49c2hhMjU2JnJldXNlPS0xJmMtaXAtdW5sb2NrZWQ9MSZ4JTNBZ3VpZD05OTI4ZTYxMy1hMzNkLTQ5NjEtOGJlOC0zNzY5ZWFjZmYxZjQmeCUzQXN0cmVhbXNlc3Npb25pZD0wYjQyZGFkMS03ZDEwLTQ1MjgtYjU1Zi04NjJkN2Q3MzVhNDEsMzFjNzI3ZGY4MTM0MTEyNTBhYmI3YjNhMTdhMTE5YWQ2YWQxY2VhOTM3ZWJlNzJhY2Y4ZjdlYjliZGYxYjc0OQ==/audio2/1441556.m4s failed with error: 403
10:47:32.595 T:13488   DEBUG: AddOnLog: InputStream Adaptive: AdaptiveStream: trying to reload segment ...

where the renewal url is logged but 2 lines after in the log CURL is again asking for the old url, which fails again with a 403 and the method returns false, then it tries to reload the segment again (trying to reload segment ...) using downloadurl which of course still contains the old url, resulting in this failed situation here.

Am I missing something?

glennguy commented 5 years ago

@heddock Also on the issue of legality - this appears to be for [redacted] right? If so then it would be no more illegal than any other addon out there that mimics an official app or browser. From what I can see horizon is a legit service (apps on the playstore, uses widevine) , not an illegal iptv re-broadcaster/pirate streamer.

Related - have you looked at the android implementation? You might not have to jump through the 1 minute token hoop...

heddock commented 5 years ago

@glennguy I saw i forgot to remove a link in the logging indeed :). I would appreciate if you could remove your service findings in this thread so it will not be indexed by google or something. Better be safe than sorry. Tnx.

I did not look at the android implementation. The only possibility is to decompile the sources right?

glennguy commented 5 years ago

Edited.

No not at all. Have a look at mitmproxy. The data for android/ios is also usually a lot easier to work with as the apps will use JSON or XML.

peak3d commented 5 years ago

@glennguy yes, indeed the goto retry looks odd here

peak3d commented 5 years ago

https://github.com/peak3d/inputstream.adaptive/commit/d1d759e138dbe13905a8dff16f14391f1a52e54e could fix the issue

heddock commented 5 years ago

Edited.

Great thanks very much.

@peak3d @glennguy is it possible to generate a new inputstream.adaptive dll or addon for my windows Kodi so i can test this?

Will this change be part of the new nightly build from Kodi of tomorrow?

matthuisman commented 5 years ago

@heddock It should show up in the next Windows nightly (1st November) I have checked 31st October and that is using previous version (2.3.5) (Update, November 1st nightly is up and I have confirmed it's running 2.3.6)

@peak3d I see a few changes to processing the tree. Do you think that may also fix my issue here: https://github.com/peak3d/inputstream.adaptive/issues/178 (That MPD now causes KODI to crash completely) (have now tried 2.3.6 but same issue)

Also, I thought inputstream would now be distributed via binary add-ons repo. I see it is still part of the Windows installer. I'm curious why that is? All other binary add-ons are in repo.

glennguy commented 5 years ago

@matthuisman won't fix issue I don't believe, will comment further in #178

peak3d commented 5 years ago

@matthuisman I committed a patch for your issue in #178 but I'm curious how / where it crashes after my changes yesterday. Can you pls. provide the place where it crashes? stacktrace would be best. thx.

Edit libssd_wv.[dll/so] are currently not supported by the kodi installer, there are severel options to solve it and they have to be evaluated. Thats the reason it's still included in windows / android builds.

heddock commented 5 years ago

@peak3d

I just tested the fix and now it is updating the token. I will keep on playing with the next token. After that something happens what causes the sound to abort. I will dive into that later. Is it probably possible to push the new token somehow instead of reacting to a 403?

heddock commented 5 years ago

@peak3d @glennguy

I have checked what the problem could be. When i look at de MPD there is a part for the subtitles i think:

<AdaptationSet mimeType="application/mp4" segmentAlignment="true" startWithSAP="1" lang="nl">
    <Role schemeIdUri="urn:mpeg:dash:role:2011" value="subtitle"/>
    <SegmentTemplate timescale="90000" initialization="$RepresentationID$/Header.m4s" media="$RepresentationID$/$Number$.m4s" duration="180000" startNumber="610336" presentationTimeOffset="117932280644"/>
    <Representation id="private1" bandwidth="20000" codecs="stpp"></Representation>
</AdaptationSet>

When i look into the logs this part frequently cannot be downloaded.

09:57:46.887 T:7820 ERROR: AddOnLog: InputStream Adaptive: Download http://hostname/dash/Nederland_2_HD;vxttoken=cGF0aFVSST0lMkZkYXNoJTJGTmVkZXJsYW5kXzJfSEQlMkYlMkEmZXhwaXJ5PTE1NDExNDkxNjAmZm49c2hhMjU2JnJldXNlPS0xJmMtaXAtdW5sb2NrZWQ9MSZ4JTNBZ3VpZD1jMmExOWY1Yi1mYTc5LTRiZWYtOGZmNS01MzcxMjk3YzQzZjImeCUzQXN0cmVhbXNlc3Npb25pZD1kNzk2NWM1MC1hOTY5LTRlZjEtYjczYS1lMjUwY2ZhNzc4NDYsOWVkNTk3YThkN2ZjYmQ1OTIyNjk0ODY3YTI0MjMzM2QxODcyMTM3ODVlNDI0NzNiMDRjNzRlNTAwNDEwMWY1Nw==/private1/1612858.m4s failed with error: 404

This will cause the stream to abort at a certain time. When i sniff the original website those subtitles are not downloaded at all. Is it possible to skip a certain adapterset?

peak3d commented 5 years ago

And you can't enable subs in web-browser?

heddock commented 5 years ago

Yes i just enabled subtitles in the web-browser and than the extra calls will appear in the logging too, but all with a 200 response instead of the 404 from Kodi. Maybe it has something to do with the key validity of 1 minute but then i would expect a 403 instead.

It would be very nice if i could push the new token to inputstream.adaptive or could set some option to let inputstream.adaptive get a key (call the function) on an configurable interval without reacting on 403 as it currently does. Is one of those options possible?

peak3d commented 5 years ago

Subs: pls. compare the URL, in special the last number (segment-number) between kodi and web. I have the feeling that the segnum we pass is kind of high.

Pushing notifications to inputstream. No, it is not possible his way. Only possibility would be that I implement a timer in inputstream.adaptive and request the new URL periodically. Pls. keep in mind that your python addon is not running during video playback as long you have no service running. How would you solve the 1 Minute thing in your addon?

heddock commented 5 years ago

What i did now i creating a timer which will update the token to memory every minute. After inputstream.adaptive requests for a new token after 2.5 minute it will return the last one. This however is only working twice. After that it will get a 403 as well. A timer implementation would be great.

Another approach could be a method call to get every url with the original link as parameter. Within the addon a modify of the url could be done. However i don't know the extra load this will produce.

It would also be great if subtitles could be disabled somehow.

glennguy commented 5 years ago

It might be useful to see a new debug log file. Your original log file also had 404s for some of the subtitle segments, but they succeeded again after 1 retry (maybe being a live stream they didn't yet exist)

alannl commented 5 years ago

Hi, I have been working on the same add-on but I am clueless about step four of the first post, which is the license_key link. {url}/license/eme|{static headers}&X-OESP-License-Token={token}|A{SSM}| I am using the headers of the http request which sends the widevine bytes, \x08\x04. I keep getting error 400 while a normal requests.post gives 200 and its response as binary data. Can you please show me your code at getlicensekey() , Heddock? thanks

heddock commented 5 years ago

@alannl

the code is still working only 5 minutes because of the token validation problem discussed in this topic.

alannl commented 5 years ago

@peak3d You could use the date header to control the renewal interval instead of waiting for an error, and make this interval into a parameter for the addon builder.

peak3d commented 5 years ago

@alannl your issue does not sound related to the issue thread here. Pls. be so kind and open a new issue for your case.

alannl commented 5 years ago

Hi @peak3d I have figured out the above issue I had with the license key, now I am experiencing the exact same issue as heddock with the same streaming service. When the play token gets refreshed by your renewal function, the old token expires, normally it expires after 2,5 mins thats why inputstream renews it after 2,5 minutes. The web service itself uses a json parameter delivered with the new token which contains the renewal interval value of 60000ms to be used by the app. After a renewal call, the url call containing the expired token is used first, which gives an 403 which results in a new renewal call, which is followed by a new url call with the last renewed token, again 403 error (invalid token),... this results in a loop, as far as I have looked into it.

Btw, thanks for this module.

peak3d commented 5 years ago

@alannl

1.) If you are able to create an initial, working token, you should be able to produce one after 2,5 minutes, too, or is there anything I misunderstand.

2.) Assume someone pauses the stream for longer time, what would be your solution in this issue?

alannl commented 5 years ago

@peak3d If you decode the tokens above they show a parameter expiry, and if you compare this time to the log time of downloading, you'll see that the expiry time is past, which is the cause of error 403. This happens because the old token is used and not the renewed one, according to the log. Actually, the new token is used correctly only after the first renewal call.

If someone pauses the stream, the segment from the url with the token has already been accessed and downloaded. Token expiration time should be respected when stream is resumed.

From above log:

21:14:23.337 T:21096 NOTICE: #### NEW TOKEN ####
21:14:23.337 T:21096 NOTICE: new url :token_ expiry=1540844181 (21:16:21)
21:14:23.337 T:19228 DEBUG: AddOnLog: InputStream Adaptive: Renewed URL: expiry=1540844181 (21:16:21)
21:14:23.337 T:19228 DEBUG: CurlFile::ParseAndCorrectUrl() adding custom header option 'connection: keep-alive'
21:14:23.337 T:19228 DEBUG: CurlFile::Open(0x1fff88847a0) token_expiry=1540844061 (21:14:21)/video1/1460359.m4s
21:14:23.338 T:21096 INFO: Python interpreter stopped
21:14:23.338 T:21096 DEBUG: Thread LanguageInvoker 21096 terminating
**21:14:23**.343 T:19228 ERROR: AddOnLog: InputStream Adaptive: Download token_expiry=1540844061 (**21:14:21**)/video1/1460359.m4s failed with error: 403

My solution would be to call renew at or close before x ms, of which x is user defined. I will check if the old token is still being used after renewal then.

iranl commented 5 years ago

@alannl

1.) If you are able to create an initial, working token, you should be able to produce one after 2,5 minutes, too, or is there anything I misunderstand.

2.) Assume someone pauses the stream for longer time, what would be your solution in this issue?

@peak3d I'm working on a similar addon and I think I found the problem which causes the first media renewal to succeed and second and subsequent renewals to fail.

https://github.com/peak3d/inputstream.adaptive/blob/3df8a84db327d9417f43d455001486452eea51f9/src/common/AdaptiveStream.cpp#L323

In the above line it's comparing the current url to the tree_.baseurl On the first media renewal the comparison will succeed but on subsequent tries the current url will have changed (based on the renewal url) while the tree_.baseurl will never change from it's original state which means url.find(tree_.baseurl) != 0

Changing the line to:

if (!tree_.effective_url_.empty())

Fixes the problem (in my use case). I had no luck in updating the base_url (which may be a better solution?)

peak3d commented 4 years ago

@iranl do you talk about live content with manifest updates? At least for VOD (without manifest update) in the tree there is always the unchanged / initial URL which should match the base_url.

I see a problem when using live content with manifest update, because URL's in manifest can change to the new one (which then do not match anymore)

Sorien commented 4 years ago

@heddock, @alannl are you still able to start playback? it seems I'm trying to create an addon for the same provider but I'm stuck, every request looks the same as browser one but playback won't even start

iranl commented 4 years ago

@heddock, @alannl are you still able to start playback? it seems I'm trying to create an addon for the same provider but I'm stuck, every request looks the same as browser one but playback won't even start

This provider has recently started enforcing VMP (Verified media path). Which means kodi playback on any platform other than android is impossible for now. See their forums for a discussion by angry linux users. Only way to restore functionality for now is if the provider reverses its enforcement of VMP.

iranl commented 4 years ago

@iranl do you talk about live content with manifest updates? At least for VOD (without manifest update) in the tree there is always the unchanged / initial URL which should match the base_url.

I see a problem when using live content with manifest update, because URL's in manifest can change to the new one (which then do not match anymore)

I never did manage to fully disect the problem. The provider does not update the manifest during reguler playback. I believe the problem occured when audio/video/subtitle streams with different durations where renewed by a 403. In that case I saw inputstream adaptive try to find/replace the wrong urls after which playback failed. After I started using media renewal at 60 sec instead of waiting for the 403 I never encountered the problem again so I stopped debugging at that time.

lhassell commented 4 years ago

Is there any hope of revisiting this to address the problem described here? https://github.com/d21spike/plugin.video.sling/issues/7

peak3d commented 4 years ago

There are new properties for this, refer to the last commits in master branch

xags commented 3 years ago

There are new properties for this, refer to the last commits in master branch

@peak3d Could you clarify what commit this was?

shycoderX commented 3 years ago

290 Any updates on this one? Or somebody else had success with a license/eme endpoint? I keep receiving

[{"type":"state","code":"deviceUnregisteredDeviceLimitReached","reason":"prohibited","providerTitle":"Ketnet","deviceChangeWindowType":"calendarMonth"}]

Even though the device is registered..

matthuo333 commented 3 years ago

@heddock, @alannl are you still able to start playback? it seems I'm trying to create an addon for the same provider but I'm stuck, every request looks the same as browser one but playback won't even start

This provider has recently started enforcing VMP (Verified media path). Which means kodi playback on any platform other than android is impossible for now. See their forums for a discussion by angry linux users. Only way to restore functionality for now is if the provider reverses its enforcement of VMP.

So there is no solution? HBO Max has just happened to be VMP :(

glennguy commented 3 years ago

@heddock can we close this one now? Have you implemented with a proxy?