https://github.com/torxed/chromecast
As vanilla as it gets, cast a YouTube (or custom) video to a Chromecast
https://github.com/torxed/chromecast
cast chromecast custom mp4 python vanilla youtube
Last synced: about 2 months ago
JSON representation
As vanilla as it gets, cast a YouTube (or custom) video to a Chromecast
- Host: GitHub
- URL: https://github.com/torxed/chromecast
- Owner: Torxed
- License: gpl-3.0
- Created: 2020-09-26T20:58:12.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2020-09-27T16:44:32.000Z (over 4 years ago)
- Last Synced: 2025-02-12T08:39:14.820Z (3 months ago)
- Topics: cast, chromecast, custom, mp4, python, vanilla, youtube
- Language: Python
- Homepage:
- Size: 303 KB
- Stars: 4
- Watchers: 2
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# chromecast
As vanilla as it gets, cast a youtube *(or custom)* video to a chromecast without any dependencies *(No Google or Google-ProtoBuf libs required)*- [Dependencies](#dependencies)
- [Usage](#usage)
- [Note on ProtoBuf, chromecast and alternatives](#note-on-protobuf-chromecast-and-alternatives)
* [Protobuf in general](#protobuf-in-general)
+ [`INT` variables](#int-variables-with-a-field-id-of-5)
+ [`string` variables](#string-example-with-a-payload-and-field-id-of-3)
* [Chromecast specifics](#chromecast-specifics)
+ [protocol_version](#protocol_version)
+ [source_id](#source_id)
+ [destination_id](#destination_id)
+ [namespace](#namespace)
+ [payload_type](#payload_type)
+ [payload_utf8](#payload_utf8)
- [Honorable mentions](#honorable-mentions)# Dependencies
None! this script is written in pure vanilla Python 3+.
# Usage
python chromecast.py
For instance:
python chromecast.py 192.168.0.10 ZTidn2dBYbY
Or feed a custom mp4 URL to the script *(Currently mp4 is a hardcoded header until I figure something out)*:
python chromecast.py 192.168.0.10 http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4
*Note:* To find your chromecasts, you can use `avahi-browse -tr _googlecast._tcp` or `nmap --open -sS -Pn -n -p 8009 192.168.0.0/24` *(Replace the subnet with your own and look for `8009/tcp open`)*.
# Note on ProtoBuf, chromecast and alternatives
Two things. The first being - just use [pychromecast](https://github.com/home-assistant-libs/pychromecast) or [casttube](https://github.com/ur1katz/casttube). They're more fully fledged.
Secondly, Google heavily uses their open protocol called [protobuf](https://developers.google.com/protocol-buffers/docs/encoding).
It's essentially just a `struct` -> `bytes` serializer. I've included a very crude serializer & de-serializer for sending and reading protobuf streams. A quick overview of how that works would be:## Protobuf in general
Variable type overview:
| | | |Below are two examples describing the most common variables found in a chromecast session.
### `INT` variables with a field ID of 5:
| 00101 | 000 | 0001 1000 |
The value of this integer would be `24`, and it's up to the developer to define what field `5` should be.
In chromecast world, that's `payload_type`, so that would normally have a int value of `0` for `utf8` string payload.### `string` example with a payload and field ID of 3:
| 00011 | 010 | 0001 0011 | {"type": "CONNECT"}
The field ID *(`00011`)* is 3. And the variable type *(`010`)* is `string`.
The length of the string is the next byte, which in this case is 19 *(`0001 0011`)*.The payload is `{"type": "CONNECT"}`. That's the basics of ProtoBuf.
## Chromecast specifics
Chromecast has a set of fields that needs to be defined in a ProtoBuf format.
Those fields are:* protocol_version `::int`
* source_id `::str`
* destination_id `::str`
* namespace `::str`
* payload_type `::int`
* payload_utf8 `::str`And the order is very important. Because the field_id is in the data stream and they need to come in a certain order to match on both sides.
The names however can be anything, but the type - meaning - and order is important.
But the names are just for your convenience and you can decide to name them whatever you want.### protocol_version
Protocol version just tells chromecast which protocol to talk. Currently that's `v2.1.0` which is represented by the int `0`. So a lonely ZERO (0) defines that.
### source_id
Source ID is the sender *(or caster's)* id. This can *probably (!?)* be anything you want.
But in reality the magic keyword of `sender-0` seams to do the trick.### destination_id
This field changes depending on what casting-state you're in.
It starts off with the magic keyword of `receiver-0` but once an application has been launched,
this should be changed to whatever the instance-id is of that application - letting the chromecast know you're talking to the application and not the chromecast.There's also a magic keyword `Tr@n$p0rt-0` which feels like an odd design choice. But is used by the chromecast to send heartbeat information in the shape of `{"type":"PING"}` with the sender and receiver-id's being `Tr@n$p0rt-0`. Not sure why, seams like an odd implementation thing.
### namespace
Namespace is the URN *(or URI/URL if you're more familiar with those terms)* in which you want to call or talk to. Lets say you want to talk to the YouTube app, you need a namespace URN of: `urn:x-cast:com.google.youtube.mdx` in order to let the chromecast know you want to talk to the YouTube app. All applications have their own URN's, and I don't know how you can find those other than [finding URN's in other libraries](https://github.com/home-assistant-libs/pychromecast/blob/0c1d904ab15b91922c8ac45cb7e6641201910578/pychromecast/controllers/plex.py#L178) or listening for the `namespaces` response when launching an app *(which requires you to know an app ID to launch)*.
### payload_type
The payload type can be two different types, either `bytes` or `utf8` strings. I think chromecast supports both. But sticking to `utf8` strings are quite simple and works for most cases talking to the youtube and the generic media app heh. So keep the type `0` for `utf8` strings *(`1` for `bytes` payloads as a reference)*.
### payload_utf8
The payload contains the actual data being sent back and fourth for parsing.
For instance, the `{"type": "CONNECT"}` payload is meant to connect a session to the chromecast or an app on the chromecast.`{"type": "PING"}` is another common one that should be replied with `{"type": "PONG"}`.
The different data payloads, in which order they come/should be sent can be seen in this very crude flowchart:
# Honorable mentions
* [Perth Linux User Group](http://plug.org.au/)'s [talk from 2016](https://docs.google.com/presentation/d/1X1BdFunVnLkF7L0BgevH2zzkcSe0_gtdTJ_pMdEuakQ/htmlpresent).
* [pychromecast](https://github.com/home-assistant-libs/pychromecast) Which had a lot of `URN`'s that could be re-used.
* [casttube](https://github.com/ur1katz/casttube) Which had all the YouTube Web-API's to manage a YouTube lounge.
* Google for making the [ProtoBuf](https://developers.google.com/protocol-buffers/docs/encoding) protocol very open and easy to deconstruct.