How to Set Up bilistream for YouTube Live Stream Rebroadcast (転播)
bilistream automates YouTube live stream rebroadcasting to Bilibili by detecting live status via yt-dlp, extracting the direct .m3u8 URL, and pushing the stream through FFmpeg to your Bilibili RTMP endpoint.
The open-source tool limitcool/bilistream is a Rust-based relay service designed to monitor external live platforms and mirror them to Bilibili. When configured for bilistream YouTube live stream workflows, it handles detection, URL resolution, and continuous streaming without manual intervention.
How bilistream Handles YouTube Live Streams
The architecture follows a plugin-based design where platform-specific logic is abstracted behind a common Live trait.
Plugin Selection and Platform Detection
When the Platform field in config.yaml is set to Youtube, the select_live function in src/plugins/live.rs (lines 30-49) instantiates the Youtube plugin. This dispatch mechanism allows bilistream to treat all platforms uniformly while delegating platform-specific scraping to dedicated modules.
Live Status Checking
The Youtube struct implements get_status by delegating to get_youtube_live_status in src/plugins/live.rs (lines 46-55). This function performs an HTTP request to the YouTube channel's live page, scrapes the embedded ytInitialData JSON, and extracts the isLive boolean. When isLive is true, bilistream proceeds to URL extraction; otherwise, it waits for the next Interval cycle.
Extracting the Stream URL
To obtain the actual media stream, Youtube::get_real_m3u8_url in src/plugins/youtube.rs (lines 61-81) executes yt-dlp. The command structure is:
yt-dlp -g https://www.youtube.com/channel/<CHANNEL_ID>/live
The -g flag instructs yt-dlp to return the direct .m3u8 URL without downloading. If a Cookies path is configured in config.yaml, the command appends --cookies <PATH> (lines 66-70) to support member-only or age-restricted streams.
FFmpeg Rebroadcasting
The main event loop in src/main.rs (lines 56-73) constructs an FFmpeg command that ingests the YouTube .m3u8 and pushes to Bilibili's RTMP endpoint:
ffmpeg -i <youtube_m3u8_url> -c copy -f flv <BiliRtmpUrl>/<BiliRtmpKey>
If FfmpegProxy is configured, the loop injects -http_proxy <PROXY> into the FFmpeg arguments (lines 34-38), which is essential for users outside China to access YouTube while pushing to Bilibili.
Configuration Guide for YouTube Rebroadcast
Minimal config.yaml Setup
Create a config.yaml in your working directory:
Interval: 60
Platform: Youtube
Youtube:
Room: UC1zFJrfEKvCixhsjNSb1toQ # Replace with target Channel ID
AccessToken: "" # Deprecated, leave empty
BiliLive:
SESSDATA: "<your_bilibili_sessdata>"
bili_jct: "<your_csrf_token>"
DedeUserID: "<your_user_id>"
DedeUserID__ckMd5: "<md5_hash>"
Room: 660428
BiliRtmpUrl: "rtmp://live-push.bilivideo.com/live-bvc/"
BiliRtmpKey: "?streamname=live_0000000_0000000&key=xxxxxxxxxx"
FfmpegProxy: "http://127.0.0.1:7890" # Required if running outside China
Docker Deployment
The recommended deployment method uses the pre-built container:
# docker-compose.yaml
services:
bilistream:
image: ghcr.io/limitcool/bilistream:latest
container_name: bilistream
volumes:
- ./config.yaml:/app/config.yaml:ro
- ./cookies.txt:/app/cookies.txt:ro
restart: unless-stopped
environment:
- TZ=Asia/Shanghai
- http_proxy=http://host.docker.internal:7890
- https_proxy=http://host.docker.internal:7890
Start the service:
docker compose up -d
docker compose logs -f
Binary Installation
For bare-metal deployment:
# Install dependencies
apt update && apt install -y ffmpeg python3-pip
pip3 install -U yt-dlp
# Download latest release
curl -L -o bilistream.tar.gz \
https://github.com/limitcool/bilistream/releases/download/v0.4.0/bilistream-v0.4.0-x86_64-unknown-linux-musl.tar.gz
tar -xzf bilistream.tar.gz
./bilistream-v0.4.0-x86_64-unknown-linux-musl/bilistream
Advanced Configuration Options
Handling Member-Only Streams
To rebroadcast member-only or private YouTube streams, provide a cookies file exported from your browser:
Cookies: "/app/cookies.txt"
The Youtube::ytdlp function in src/plugins/youtube.rs automatically appends --cookies <PATH> to the yt-dlp command when this field is populated.
Proxy Configuration for FFmpeg
If bilistream runs outside mainland China, YouTube access requires a proxy while Bilibili RTMP push requires direct connection. Set FfmpegProxy to route only FFmpeg's HTTP requests:
FfmpegProxy: "http://127.0.0.1:7890"
As implemented in src/main.rs lines 34-38, this injects -http_proxy into the FFmpeg command without affecting the RTMP push connection.
Gotify Notifications
Enable push notifications when streams start:
Gotify:
url: "https://gotify.example.com"
token: "your_application_token"
The send_gotify_notification function in src/push.rs POSTs a message to your Gotify server whenever bilistream detects a live event and begins rebroadcasting.
Summary
- bilistream automates YouTube-to-Bilibili rebroadcasting by combining
yt-dlpfor URL extraction, web scraping for live detection, and FFmpeg for RTMP pushing. - The
Youtubeplugin insrc/plugins/youtube.rshandles channel-specific logic, whilesrc/main.rsorchestrates the polling loop and streaming process. - Configuration requires only a YouTube Channel ID, Bilibili credentials, and optionally a proxy for FFmpeg if running outside China.
- Member-only streams are supported via cookie files, and notifications can be sent via Gotify when broadcasts begin.
Frequently Asked Questions
What is bilistream and how does it work with YouTube?
bilistream is an open-source Rust application that monitors external live streaming platforms and rebroadcasts them to Bilibili. For YouTube specifically, it uses the yt-dlp tool to extract direct .m3u8 URLs from live channels and pushes the stream via FFmpeg to Bilibili's RTMP servers, running this check loop every 60 seconds by default.
Do I need a YouTube API key to use bilistream?
No API key is required. bilistream scrapes the YouTube channel's live page directly to detect the isLive status in the embedded JavaScript, and uses yt-dlp (a command-line tool) to resolve stream URLs. This approach avoids API rate limits and authentication complexity, though it requires yt-dlp to be installed and occasionally updated.
How do I handle member-only or private YouTube live streams?
Configure the Cookies field in config.yaml with the path to a Netscape-format cookies file exported from your browser after logging into YouTube. When Cookies is set, bilistream automatically appends --cookies <path> to the yt-dlp command, allowing it to access restricted content. Ensure the cookies file is readable and mounted correctly if using Docker.
Can I run bilistream without Docker?
Yes, you can run the pre-compiled binary directly on any Linux system. You must manually install the dependencies ffmpeg and yt-dlp (via pip3 install -U yt-dlp), download the latest release from GitHub, extract it, and execute the binary. The binary expects a config.yaml file in the working directory. This method is suitable for bare-metal servers or custom systemd services.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →