Coder Social home page Coder Social logo

mediaservicecore's Introduction

Unofficial Java api for YouTube

mediaservicecore's People

Contributors

ajayyy avatar joneschi avatar roblav96 avatar sankam-nikolya avatar warmelk avatar yuliskov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

mediaservicecore's Issues

DIAL with lounge API

Hey! I'm the author of Playlet, a YouTube app for Roku TV.

I recently embarked on the journey to support casting from the YouTube app using lounge.

Some projects, like https://github.com/henriquekano/youtube-lounge-api, https://github.com/yuliskov/MediaServiceCore, and (especially) https://github.com/patrickkfkan/yt-cast-receiver helped me understand the protocol better, so I wanted to say thanks, and also share a bit of my findings in case it is useful.

As I tried to understand the DIAL spec, which is the "Link using Wifi" option, I found it was mostly working like this:

Chain of events

  1. Devices (mobile) broadcast an SSDP message M-SEARCH
M-SEARCH * HTTP/1.1
HOST: 239.255.255.250:1900
MAN: "ssdp:discover"
MX: 5
ST: urn:dial-multiscreen-org:service:dial:1
  1. And devices (TVs) capable of accepting casting would respond with something like
Cache-Control: max-age=3600
ST: urn:dial-multiscreen-org:service:dial:1
USN: ID::urn:dial-multiscreen-org:service:dial:1
Ext: 
Server: Roku/12.5.5 UPnP/1.0 Roku/12.5.5
LOCATION: http://IP:8060/dial/dd.xml
WAKEUP: MAC=MAC;Timeout=10

Notice the LOCATION header. This would be a link to an xml file containing the device description.

  1. The device (mobile) makes an http GET request to the LOCATION. My TV's response looks something like this
<?xml version="1.0"?>
<root xmlns="urn:schemas-upnp-org:device-1-0">
    <specVersion>
        <major>1</major>
        <minor>0</minor>
    </specVersion>
    <device>
        <deviceType>urn:roku-com:device:player:1-0</deviceType>
        <friendlyName>TV</friendlyName>
        <manufacturer>XXX</manufacturer>
        <manufacturerURL>xxx.com</manufacturerURL>
        <modelDescription>Roku Streaming Player Network Media</modelDescription>
        <modelName>XXX</modelName>
        <modelNumber>XXX</modelNumber>
        <modelURL>http://www.roku.com/</modelURL>
        <serialNumber>XXXXXXX</serialNumber>
        <UDN>uuid:XXXXXXXXXX</UDN>
        <iconList>
            <icon>
                <mimetype>image/png</mimetype>
                <width>360</width>
                <height>219</height>
                <depth>8</depth>
                <url>device-image.png</url>
            </icon>
        </iconList>
        <serviceList>
            <service>
                <serviceType>urn:roku-com:service:ecp:1</serviceType>
                <serviceId>urn:roku-com:serviceId:ecp1-0</serviceId>
                <controlURL></controlURL>
                <eventSubURL></eventSubURL>
                <SCPDURL>ecp_SCPD.xml</SCPDURL>
            </service>
            <service>
                <serviceType>urn:dial-multiscreen-org:service:dial:1</serviceType>
                <serviceId>urn:dial-multiscreen-org:serviceId:dial1-0</serviceId>
                <controlURL></controlURL>
                <eventSubURL></eventSubURL>
                <SCPDURL>dial_SCPD.xml</SCPDURL>
            </service>
        </serviceList>
    </device>
</root>

Notice how the service list contains urn:dial-multiscreen-org:service:dial:1, which is saying the device is capable of DIAL. Good.
In the response headers for hitting the device description http://IP:8060/dial/dd.xml, there's one important header to capture:

Application-Url: http://IP:8060/dial

Because it is the URL used to check if a specific DIAL compatible app is installed or not.

  1. The device (mobile) makes a GET request to Application-Url + /YouTube (case sensitive). In this case that would be http://IP:8060/dial/YouTube. The response would be something like this:
<?xml version="1.0" encoding="UTF-8" ?>
<service
	xmlns="urn:dial-multiscreen-org:schemas:dial" dialVer="2.1">
	<name>YouTube</name>
	<options allowStop="true" />
	<state>stopped</state>
</service>

If the mobile device gets a valid response, then it will see the device over wifi and offer to connect to it (it will show up as the friendlyName from the device description file.)
Note: on my Roku, the request will be blocked, unless the Origin header is set to https://www.youtube.com

  1. The response from http://IP:8060/dial/YouTube Might be in different state, and the mobile devices react differently based on the presence of the additionalData field.
  • In the case the xml does not contain additionalData (so similar to the content from step 4)
    • The mobile device would send a POST request to http://IP:8060/dial/YouTube, which includes theme and pairingCode url encoded in the body. The pairing code can be registered using https://www.youtube.com/api/lounge/pairing/register_pairing_code and then the mobile phone would join the lounge once the code is registered.
  • In the case the xml contains additionalData, e.g. :
Example copied from https://github.com/henriquekano/youtube-lounge-api/wiki/Discovery
<service xmlns="urn:dial-multiscreen-org:schemas:dial">
  <name>YouTube</name>
  <options allowStop="false"/>
  <state>running</state>
  <link rel="run" href="http://192.168.x.y:58722//run"/>
  <additionalData>
    <brand>Sony</brand>
    <model>PS4 Pro</model>
    <screenId>qweqweqwe</screenId>
    <theme>??</theme>
    <deviceId>ssssssssss</deviceId>
    <loungeToken>xxxxxxxx</loungeToken>
    <loungeTokenRefreshIntervalMs>1500000</loungeTokenRefreshIntervalMs>
  </additionalData>
</service>

Then the phone will not send a pairing code, and will just join the lounge, since it has everything it needs already.

  • In the case the xml contains additionalData, but not containing a loungeToken, e.g :
<?xml version="1.0" encoding="UTF-8" ?>
<service
	xmlns="urn:dial-multiscreen-org:schemas:dial" dialVer="2.1">
	<name>YouTube</name>
	<options allowStop="true" />
	<state>stopped</state>
	<additionalData>
		<testXXXXXXX>xxxxxxx</testXXXXXXX>
		<brand>XXX</brand>
		<model>XXXX</model>
		<yumi>XXXXXXXXXXXXXX</yumi>
		<passiveSessionId>XXXXXXXXXXX</passiveSessionId>
	</additionalData>
</service>

Now this is the part I haven't explored yet - but I'm guessing a passiveSessionId is some form of new feature allowing the session to be passive until a device connects to it.

  1. One last thing, when <options allowStop="true" /> is returned, the mobile device (actually I tested this with Chrome browser) will a send a DELETE request to close the app. Just a small detail.

Implementation

So the device is responsible for responding to the M-SEARCH requests, and for providing a device description xml file. So by definition, only one app can have the identifier YouTube for DIAL. This is why when the YouTube mobile app casts to a device, the official YouTube tv app will launch. This is why I went a different route.

  1. A DIAL server
    I have a udp connection listening for broadcast messages. When it sees an M-SEARCH, it responds just like the device does (see step 2 in the first section), but I set the LOCATION here to point to a file that I'm serving on a local web server running on the app.

  2. Serving device description
    Using a local server, I'm serving a "virtual device description" xml file, and also serve an xml file for the/dial/YouTube file.
    For the device description, I set the friendlyName to "Playlet on" + tvName so that users can Identify the app they want to cast to.

So far I'm have a working implementation (just a PoC that needs cleanup) here iBicha/playlet#276 that does what I'm describing. I thought the approach could be used to add DIAL support to SmartTube. Most people never link using TV code, since it is more convenient for the auto discovery over WIFI to just work.

That's it. I just wanted to overshare since information about this stuff is pretty scarce, and it's hard to find.

Cheers!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.