Cast your screen to a Chromecast without Chrome
I tried to cast my screen to my TV (with a built-in Chromecast).
1. Tools tested
1.1. Google Chrome / Chromium
Best experience by far. Streaming starts very fast and with very low delay (~0.5 seconds).
But I would like to not use Chrome if possible, and I think it's not the browser's job to cast my screen. So I kept looking for some alternatives.
This didn't work for me, and it is not fully implemented yet.
I was able to run
miracle-wifid, but only after I disconnected from my normal wifi.
miracle-wifictl hung when I ran the
I didn't investigate any further.
It found a TV nearby, but not mine. My Fire TV stick was also not found, and is not supported. Chromecast is also not supported: Issue
Tool exclusivly to work with Chromecast. I was able to find the Chromecast in my network and stream media to it.
Unfortunately, there is no built-in command to stream your desktop. https://github.com/xat/castnow/issues/208
The only way it worked for me was using
ffmpeg -hide_banner -loglevel error -video_size 3840x2160 -framerate 30 -f x11grab -i :0.0 -vf "scale=iw/2:ih/2" -c:v libx264 -level 3.0 -pix_fmt yuv420p -x264opts keyint=2 -crf 23 -preset ultrafast -tune zerolatency -f mp4 -movflags frag_keyframe+faststart - | castnow --quiet -
However, the delay was very high (~10 seconds).
Also, I found that
ffmpeg didn't output to stdout immediately, but had a delay itself.
I was able to reduce it by setting the
keyint option. Still not perfect, but way faster.
Similar experience to
$ ./go-chromecast ls 1) device="2021/22 Philips UHD Android TV" device_name="Philips TV" address="192.168.1.23:8009" uuid="1234567890abcdef1234567890abcdef"
./go-chromecast transcode --content-type video/mp4 --command="ffmpeg -video_size 3840x2160 -framerate 10 -f x11grab -i :0.0 -c:v libx264 -level 3.0 -pix_fmt yuv420p -x264opts keyint=2 -crf 23 -preset ultrafast -tune zerolatency -f mp4 -movflags frag_keyframe+faststart -"
1.6. Android: miracast-widget
To cast your screen on Android without using the Google Home app, you can use this neat tool.
All it does is opening the Android built-in cast page. I wasn't even able to open the page without this widget, maybe Samsung hides it in their menus(?).
But with this widget, casting the screen was super fast, just like using Google Chrome.
2. Difference between Google Chrome and the other tools
I wondered how and why Google Chrome was faster to establish the connection and start the screen sharing. Just from my feeling, it looks like it doesn't tell the Chromecast to "stream a video", but rather puts the Chromecast in a different mode.
With all other tools I see this loading screen for about a second before it starts the video streaming:
But with Google Chrome, this screen does not show up at all. Instead, the first frame I see is the casted screen. So I'm pretty sure it should be possible to reverse engineer this and see what exact commands Chrome sends to the Chromecast.
3. Chromecast Protocol
One thing I learned was how my laptop finds the Chromecast. It uses avahi:
Avahi is a system which enables programs to publish and discover services and hosts running on a local network.
Avahi implements the Apple Zeroconf specification, mDNS, DNS-SD and RFC 3927/IPv4LL.
Find Chromecasts in your network:
$ avahi-browse --verbose --ignore-local --resolve --terminate _googlecast._tcp Server version: avahi 0.8; Host name: neonew-lenovo.local E Ifce Prot Name Type Domain + wlp1s0 IPv4 2021/22-Philips-UHD--1234567890abcdef1234567890abcdef _googlecast._tcp local = wlp1s0 IPv4 2021/22-Philips-UHD--1234567890abcdef1234567890abcdef _googlecast._tcp local hostname = [1a2b3c4d-5e6f-1a2b-3c4d-5e6f1a2b3c4d.local] address = [192.168.1.23] port =  txt = ["rs=Default Media Receiver" "nf=1" "bs=1A2B3C4D5E6F" "st=1" "ca=123456" "fn=Philips TV" "ic=/setup/icon.png" "md=2021/22 Philips UHD Android TV" "ve=05" "rm=" "cd=1A2B3C4D5E6F1A2B3C4D5E6F1A2B3C4D" "id=1234567890abcdef1234567890abcdef"] : Cache exhausted : All for now
Find all services available via avahi:
avahi-browse --all --verbose --ignore-local --resolve --terminate
CASTV2 is the name of the proprietary protocol Google Cast uses. It wraps Protocol Buffers (Protobuf) messages in a TLS connection.
I've found https://github.com/dylanmckay/gcast/blob/master/PROTOCOL.md and https://github.com/thibauts/node-castv2.
Unfortunately, the private key used for device authentication is not available, so we cannot create an own server which is accepted by the Google Chrome browser for example.
See here: https://github.com/thibauts/node-castv2/issues/2#issuecomment-45437332
Interestingly, there is an Android app called AirReceiverLite, which emulates a Chromecast device and I was able to connect to it via Chrome. Somebody says:
It's using predefined AuthResponse, most likely precomputed on a rooted chromecast. DRM not working. Not long till Google bans the certificate.
That was in Jul 2021.