NOTE: The technology explained here is already available in the enigma2 tarball that has been published with Opendreambox 2.5 (krogoth).
During the last weeks we've put some work in building a better solution for handling streaming services with temporary or "usually unknown" URLs.
So we came up with the all new "eServiceUri" (Service ID 0x2001 / 8193).
eServiceUri brings the possibility to register an "eUriResolver" for custom transport-type-schemas.
An eUriResolver can be used to asynchronously resolve some arbitary "alias url" to a real streaming url and "standard" service type like eServiceMP3 or eServiceDVB.
For further explanation here's how this has been implemented for youtube using yt://<videoid> or youtube://<videoid> as pseudo-transport (this has not yet been pushed to public plugin git)
For better undestanding it has lots of comments
- from enigma import eServiceReference, eUriResolver, StringList
- from Videos import VideoUrlRequest
- from Tools.Log import Log
- class YoutubeUriResolver(eUriResolver):
- _schemas = ("youtube", "yt")
- instance = None
- def __init__(self):
- #call eUriResolver.__init__ with a StringList of supported schemas (if you don't you'll never be called!)
- eUriResolver.__init__(self, StringList(self._schemas))
- #EVERY eUriResolver HAS TO implement the resolve method
- def resolve(self, service, uri):
- #There is no mandatory need to check the transport.
- #Resolver matching has already been done by the core.
- video_id = uri.split("://")
- watch_url = "http://youtube.com/watch?v=%s" % (video_id,)
- #for youtube this is the async callback once the video url is ready
- def onUrlReady(uri, format):
- Log.d("%s (%s)" %(uri, format))
- #Especially when doing web stuff there's always a proper high risk of running into an exception, it's advised to surround any "potentially dangerous" code with try/except
- # it is essential to check service.ptrValid() before accessing the service once resolving has finished.
- # The user may have changed service already which would cause the service to be gone.
- if not service.ptrValid():
- Log.w("Service became invalid!")
- #Just quit processing if the service has been invalidated, there's nothing to do anymore
- if uri:
- # So we have the "actual" uri ready and set it calling "service.setResolvedUri(uri, eServiceReference.<id*>)" (Where <id*> is any valid real service type like idDVB or idGST)
- # Again: If you didn't check service.ptrValid() like you've been told to do, this will crash the core whenever someone zapped away before you finished resolving
- # Once setResolvedUri has been set the eServiceUri will internally create a service of the given service-type and start it. All events will be proxied (even EPG will if you resolve to a standard dvb service).
- if VideoUrlRequest.isHls(format): # HLS uses transport streams and works best as DVB service
- service.setResolvedUri(uri, eServiceReference.idDVB)
- else: #anything but hls goes the standard gst route
- service.setResolvedUri(uri, eServiceReference.idGST)
- # Whenever you haven't been able to resolve the service, please do not forget to call "service.failedToResolveUri()" so the service can core can raise proper events
- # Seems we did somethings wrong, so we tell the service we failed.
- # remember? Resolving urls doing http(s) requests may always throw exceptions!
- # Start the async resolve using our onUrlReady method as callback
- VideoUrlRequest(watch_url, [onUrlReady], async=True)
- # Tell the core that we think we can resolve this (return False if you know you can't)
- return True
- #Register/Activate our YoutubeUriResolver
- YoutubeUriResolver.instance = YoutubeUriResolver()
With this you can now simply add any youtube video or live-stream to any boquuet:
We hope you like it.
This code and functionality for youtube will soon be available in our github plugin repository (and on any box that runs krogoth based images)!