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-dlp for URL extraction, web scraping for live detection, and FFmpeg for RTMP pushing.
  • The Youtube plugin in src/plugins/youtube.rs handles channel-specific logic, while src/main.rs orchestrates 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →