Auto-extract YouTube live stream URLs using yt-dlp and serve them via clean proxy paths.
- Add any YouTube channel handle (e.g.
@ABCNews) - Automatically runs
yt-dlp -gevery 3 hours - Stores URLs in Supabase Database
- Access streams via
https://your-app.com/1.m3u8,/2.m3u8, etc. - Clean dark-mode web UI to manage channels
- Create a new project at supabase.com
- Go to Table Editor → New Table
- Create table
channels:id: int8, primary key, auto-incrementhandle: text, not nullpath: text, not null, uniquestream_url: textstatus: text (default: 'pending')error_msg: textexpires_at: timestamptzupdated_at: timestamptzcreated_at: timestamptz, default: now()
- Go to Project Settings → API → copy
URLandservice_role key - Paste them into your environment variables
- Push this repo to GitHub
- On Render, create a New Web Service → connect your repo
- Set Build Command:
pip install yt-dlp && npm install - Set Start Command:
node server.js - Add environment variables (SUPABASE_URL, SUPABASE_SERVICE_KEY)
- Deploy
Note: Render free web services spin down after 15 min inactivity. For reliable 3-hour cron jobs, use Render's Background Worker (paid) or upgrade to a paid web service. Alternatively, use an external ping service (like UptimeRobot) to hit
/healthevery 5 minutes to keep it awake.
- Push repo to GitHub
- Create new project → deploy from GitHub repo
- Add variables in Railway dashboard
- In Settings → add build command:
pip install yt-dlp && npm install - Railway keeps services running 24/7 on paid plans
- Vercel: Serverless functions have max timeout (~300s on Pro, 10s on Hobby).
yt-dlpneeds shell access and can take 30-60s. Not suitable. - Cloudflare Workers: No shell/binary access. Cannot run
yt-dlp. - GitHub: Not a hosting platform for persistent servers. You could use GitHub Actions for cron, but not for serving web traffic.
| Method | Endpoint | Description |
|---|---|---|
| GET | / |
Web UI |
| GET | /api/channels |
List all channels |
| POST | /api/channels |
Add channel (body: {handle}) |
| DELETE | /api/channels/:id |
Remove channel |
| POST | /api/channels/:id/refresh |
Manual refresh |
| GET | /:path.m3u8 |
Redirect to actual stream URL |
| GET | /health |
Health check |
- You add
@ABCNewsvia the UI - Server immediately runs:
yt-dlp --js-runtimes node -g https://www.youtube.com/@ABCNews/live - Output URL is saved to Supabase with path
1 - Every 3 hours, cron re-runs the command and updates the URL
- Visiting
your-app.com/1.m3u8302-redirects to the current live stream URL