This Weird YouTube Trick

python programming shell

A while ago, I’ve found an article on Hackaday, describing how to stream arbitrary YouTube videos to Sonos systems. Before you ask: No, that’s not possible normally, at least not without a premium subscription.

In the original article called How I hacked SONOS and YouTube the same day (lol?????), the author described an approach to grab audio streams from YouTube and to convert them into ADTS streams on-the-fly to convince a Sonos device to play some YouTube music. For this, an MP3 radio station is created that Sonos uses as a source, all without the requirement to first download a video to disk and then streaming it to Sonos afterwards. Some parts seem rather complicated, such as manually parsing MP4 containers to extract AAC audio content. Also, there’s another issue: The author still didn’t release the full source code and also did not (yet?) release the announced mobile app to perform these tasks.

(╯°□°)╯︵ ┻━┻

So today, I’ll present this hefty one-liner that does all of that stuff:

(tmux has-session -t yt 2>/dev/null || tmux new-session -d -s yt) && tmux neww -d \
    "ffmpeg -i \
        '$(python3 -m youtube_dl --user-agent BestUserAgent  -f bestaudio,mp4 -g 'https://www.youtube.com/watch?v=zwu8hgUyr2E' | head -1)' \
        -user_agent BestUserAgent -q:a 0 -map a -f mp3 pipe:1 | \
    cvlc -vvv - --sout '#standard{access=http,mux=mp3,dst=0.0.0.0:3636}' --file-caching 10000 --network-caching 10000"

OK! This does the following things:

  1. Execute all of the following stuff in a new tmux session, for convenience and to be able to run it on a server.
  2. Use youtube-dl to grab a streaming link from YouTube for the specific video. Normally, you’d use streamlink for this, but some YouTube videos are protected and do not allow simple access to the respective streaming links. Luckily, youtube-dl uses its own JS interpreter to even extract streams for protected content. The -f parameter for youtube-dl controls the desired content format. Most of the time, it would be fine to just grab an audio only stream, however some music live streams only offer video streams, for whatever reason. For this purpose, bestaudio,mp4 is specified as a format to just try getting both a music and a video stream. If an audio only stream is available, that one is used instead of the one containing additional video content. Here’s a list of available formats that can be specified with the -f parameter:
youtube-dl --list-formats 'https://www.youtube.com/watch?v=zwu8hgUyr2E'
[youtube] zwu8hgUyr2E: Downloading webpage
[info] Available formats for zwu8hgUyr2E:
format code  extension  resolution note
251          webm       audio only tiny  125k , webm_dash container, opus @125k (48000Hz), 3.20MiB
140          m4a        audio only tiny  127k , m4a_dash container, mp4a.40.2@127k (44100Hz), 3.25MiB
278          webm       192x144    144p   28k , webm_dash container, vp9@  28k, 15fps, video only, 751.12KiB
394          mp4        192x144    144p   34k , mp4_dash container, av01.0.00M.08.0.110.06.01.06.0@  34k, 15fps, video only, 912.75KiB
160          mp4        192x144    144p  109k , mp4_dash container, avc1.4d400c@ 109k, 15fps, video only, 2.79MiB
395          mp4        320x240    240p   42k , mp4_dash container, av01.0.00M.08.0.110.06.01.06.0@  42k, 15fps, video only, 1.10MiB
242          webm       320x240    240p   65k , webm_dash container, vp9@  65k, 15fps, video only, 1.69MiB
133          mp4        320x240    240p  245k , mp4_dash container, avc1.4d400d@ 245k, 15fps, video only, 6.27MiB
18           mp4        320x240    240p  325k , avc1.42001E, 15fps, mp4a.40.2 (44100Hz), 8.33MiB (best)
  1. Use ffmpeg to get the stream contents, piping them to the next application on-the-fly and without downloading the full stream first.
  2. Use cvlc, the CLI version of vlc, to create an audio stream Sonos is able to interpret. This accomplished with an HTTP stream, similar to an MP3 web radio, as described in the VLC documentation. It also uses some caching to prevent buffering during playback.

The only thing that’s left is to point Sonos to the audio stream, for example with:

from soco import SoCo
zone = SoCo("10.1.3.37")
zone.play_uri("x-rincon-mp3radio://10.1.2.3:3636")

The x-rincon-mp3radio handler allows specifying the MP3 stream opened by cvlc and we’re done!

This should work with every YouTube video and can be integrated into a chat bot or some other handy thing.

ヾ(⌐■_■)ノ♪ |̲̅̅●̲̅̅|̲̅̅=̲̅̅|̲̅̅●̲̅̅|

Reinschauer: Remotely Controlling Windows Machines

golang dotnet programming windows

Building a Cloudless UniFi Security System That Doesn't Suck

python

Does This Syncthing Work?

python backup