yuliskov / mediaservicecore Goto Github PK
View Code? Open in Web Editor NEWUnofficial Java api for YouTube
Unofficial Java api for YouTube
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:
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
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.
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.
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
http://IP:8060/dial/YouTube
Might be in different state, and the mobile devices react differently based on the presence of the additionalData
field.additionalData
(so similar to the content from step 4)
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.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.
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.
<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.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.
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.
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!
Hope you build a documentation or a guide to use this library
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.