Repository navigation
YouTube Channel
This adds a channel that is YouTube's TV app. You cast to it from the YouTube app on your phone, the same way you'd cast to a smart TV. Whatever you cast plays on the channel, in Emby or Jellyfin and on a remote player.
It works like the weather channel. A container called ytcast runs YouTube's TV page (youtube.com/tv) in Firefox on a hidden screen, and records the picture and sound as a video stream. A small streaming server, MediaMTX, hands that stream to the wrapper, which adds it as a channel.
graph TD
phone[Phone: YouTube app, Cast]
ytcast[ytcast: YouTube TV app in Firefox, recorded]
mediamtx[MediaMTX: serves the stream]
wrapper[Station Wrapper 43: Sources page]
emby[Emby or Jellyfin]
phone --> ytcast --> mediamtx --> wrapper --> emby
Good to know before you start:
- It runs all the time. Expect about a quarter of a CPU core when nothing is playing and about one core while a video plays, plus 600–800 MB of RAM. An Intel GPU can take over the encoding (see below).
- YouTube only shows its TV app to TVs. A tiny Firefox extension that comes with ytcast tells the page it's talking to a TV. Google can change this at any time. If the channel suddenly shows YouTube's normal website or an error, that's why.
- Normal videos play. Paid movies and other DRM videos don't.
- Without a YouTube Premium account you get YouTube's ads, just like on a TV.
These steps use 192.168.1.20 for the server, like the other guides.
ytcast isn't a ready-made image: Docker builds it on your server from a folder in this project. Copy that folder next to your compose file:
cd ~
git clone --depth 1 https://github.com/austincnunn/station-wrapper-43.git sw43
cp -r sw43/extras/ytcast ~/fieldstation42/ytcast
rm -rf sw43Add these two services under services: in ~/fieldstation42/docker-compose.yml, next to the wrapper. (The same text is in ytcast/compose-snippet.yml.)
mediamtx:
image: bluenviron/mediamtx:latest
container_name: mediamtx
restart: unless-stopped
ports:
- "8888:8888" # the stream, for the wrapper and players
environment:
MTX_HLSVARIANT: mpegts
MTX_HLSALWAYSREMUX: "yes"
MTX_RTSPTRANSPORTS: tcp
ytcast:
build: ./ytcast
container_name: ytcast
restart: unless-stopped
shm_size: 1g # needed: Firefox crashes with Docker's small default
mem_limit: 3g
volumes:
- ./data/ytcast/profile:/profile # keeps your phone pairing and sign-in
environment:
PUBLISH_URL: rtsp://mediamtx:8554/youtube
depends_on:
- mediamtxBuild and start them. The first build takes a few minutes:
cd ~/fieldstation42
docker compose up -d --buildCheck that the stream is there. After about half a minute this should print HTTP/1.1 200 OK:
curl -sI http://192.168.1.20:8888/youtube/index.m3u8 | head -1- In the dashboard, open Sources and click Add a source.
- Type: a single stream.
- Address:
http://192.168.1.20:8888/youtube/index.m3u8 - Mode: Convert.
- First channel number: pick one, like
107. - Click Test the address if you like, then save.
Tune to the channel. You should see YouTube's welcome screen: Watch the latest videos, just for you.
There's no remote, so you press the TV app's buttons from the server with xdotool. Each command below sends key presses into the hidden screen. Keep the channel on so you can watch what happens.
First, get past the welcome screen. Press Get started:
docker exec -e DISPLAY=:99 ytcast xdotool key ReturnNow you choose who watches:
-
To sign in with your YouTube account (your subscriptions, and no ads if you have Premium): the screen shows a code and
yt.be/activate. On your phone, go to that address, type the code and pick your account. -
To watch without an account: press Down twice, then Enter, to pick Watch as guest:
docker exec -e DISPLAY=:99 ytcast xdotool key --delay 300 Down Down Return
Then open Settings → Link with TV code (left menu, bottom item, then the 7th line):
docker exec -e DISPLAY=:99 ytcast xdotool key --delay 300 Left Down Down Down Down Down Down Down Down Down Down Down Down Down Right Down Down Down Down Down Down ReturnA 12-digit code appears. (If the menu moved and you land somewhere else, take a picture of the screen as shown below, and use the arrow keys Left, Up, Down, Right, Return and Escape to find Settings → Link with TV code yourself.) In the YouTube app on your phone, tap the Cast button, then Link with TV code, and type it in. The code only lasts a few minutes. If it runs out, press Up, Down and Enter for a fresh one:
docker exec -e DISPLAY=:99 ytcast xdotool key --delay 400 Up Down ReturnThat's it. Next time, open YouTube on your phone, tap Cast and pick the TV. Pairing and sign-in are saved in data/ytcast/profile, so they survive restarts and updates. Several phones can link the same way.
Can't see the channel while you do this? Take a picture of the hidden screen instead:
docker exec -e DISPLAY=:99 ytcast ffmpeg -loglevel error -y -f x11grab -video_size 1280x720 -i :99 -frames:v 1 /tmp/screen.png
docker cp ytcast:/tmp/screen.png .On a PC with Intel graphics, the video encoding can run on the GPU instead of the CPU. Only x86 PCs, not a Raspberry Pi. First find the GPU's "render node". If you have more than one GPU, ls -l /dev/dri/by-path/ shows which is which (00:02.0 is the one built into the CPU):
ls -l /dev/dri/by-path/Then add this to the ytcast service and run docker compose up -d again:
devices:
- /dev/dri/renderD128
environment:
PUBLISH_URL: rtsp://mediamtx:8554/youtube
VAAPI_DEVICE: /dev/dri/renderD128Pass in only the GPU you want ytcast to use.
All optional, under the ytcast service's environment::
| Setting | Default | What it does |
|---|---|---|
SCREEN |
1280x720 |
The size Firefox draws at |
OUT_SIZE |
854:480 |
The size that gets streamed |
FPS |
60 |
Frames per second. 60 looks smoother on an old CRT |
VIDEO_KBPS |
2500 |
Video bitrate |
VAAPI_DEVICE |
(empty) | An Intel GPU to encode on, like /dev/dri/renderD128
|
The picture is widescreen (16:9), like your other channels. A remote player on a 4:3 TV crops the sides the same way it does for everything else.
Firefox gets updates when the image is rebuilt:
cd ~/fieldstation42
docker compose build --pull ytcast && docker compose up -d ytcastTo update ytcast's own files, copy extras/ytcast again (step 1), then run the same two commands.
-
The channel doesn't play: run
docker logs ytcast. Warnings aboutdbus,a11yandSandboxare normal. Then check the stream with thecurlcommand from step 2. -
The picture is jerky: this command shows how many frames ffmpeg had to copy because the screen recording fell behind. Run it twice, a minute apart. The number should barely change:
docker exec ytcast grep dup_frames /tmp/ffmpeg-progressIf it jumps by thousands, the server is too busy or something else is wrong. Check
docker logs ytcast. -
"Firefox is already running": the profile folder isn't writable. ytcast fixes its owner on every start, so restart it:
docker restart ytcast. -
The TV app shows the profile picker: press Enter to pick the highlighted profile:
docker exec -e DISPLAY=:99 ytcast xdotool key Return. -
Typing while a phone is casting can open the TV app's "Ask about this video" panel or pause the video.
Escapecloses the panel, andReturnstarts the video again.