stream

package module
v0.0.0-...-1f99bdc Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 19, 2026 License: MIT Imports: 12 Imported by: 0

README

bilibili_stream_lib

Go library for subscribing to Bilibili live room audio/video streams. Provides a channel-based pub/sub interface following the same design pattern as bilibili_dm_lib.

Features

  • Monitor live rooms for live/offline transitions via polling
  • Fetch stream URLs (FLV/HLS) from Bilibili's API
  • Capture audio from live streams as raw PCM via ffmpeg
  • StreamClient combines all three with auto-capture on live events

Requirements

  • Go 1.22+
  • ffmpeg installed and available in PATH (for audio capture)

Install

go get github.com/MatchaCake/bilibili_stream_lib

Architecture

The library has three independent layers that can be used separately or combined:

StreamClient (high-level, auto-capture)
    ├── Monitor (live/offline detection)
    ├── API (stream URL, room info)
    └── Capture (ffmpeg PCM extraction)

Usage

Layer 1: API (standalone functions)
import stream "github.com/MatchaCake/bilibili_stream_lib"

// Resolve short room ID to real room ID
realID, err := stream.ResolveRoomID(ctx, 123)

// Get room metadata
info, err := stream.GetRoomInfo(ctx, realID)
fmt.Println(info.Title, info.LiveStatus)

// Get stream URL (only works when live)
url, err := stream.GetStreamURL(ctx, realID)
Layer 2: Monitor (live/offline events)
m := stream.NewMonitor(
    stream.WithMonitorInterval(15 * time.Second),
)

events, err := m.Watch(ctx, []int64{12345, 67890})
if err != nil {
    log.Fatal(err)
}

for ev := range events {
    if ev.Live {
        fmt.Printf("Room %d went live: %s\n", ev.RoomID, ev.Title)
    } else {
        fmt.Printf("Room %d went offline\n", ev.RoomID)
    }
}

Dynamic room management:

m.AddRoom(99999)    // start watching
m.RemoveRoom(12345) // stop watching
Layer 3: Capture (ffmpeg audio)
url, _ := stream.GetStreamURL(ctx, roomID)

reader, err := stream.CaptureAudio(ctx, url, &stream.CaptureConfig{
    SampleRate: 16000,
    Channels:   1,
    Format:     "s16le",
})
if err != nil {
    log.Fatal(err)
}
defer reader.Close()

// Read raw PCM data
buf := make([]byte, 4096)
for {
    n, err := reader.Read(buf)
    if err != nil {
        break
    }
    // Process buf[:n] - pipe to STT, save to file, etc.
}
Full: StreamClient (auto-capture)
client := stream.NewStreamClient(
    stream.WithInterval(15 * time.Second),
    stream.WithAudioConfig(stream.CaptureConfig{
        SampleRate: 16000,
        Channels:   1,
        Format:     "s16le",
    }),
    stream.WithAutoCapture(true),
)

events, err := client.Subscribe(ctx, []int64{12345, 67890})
if err != nil {
    log.Fatal(err)
}

for ev := range events {
    switch ev.Type {
    case stream.EventLive:
        fmt.Printf("Room %d is live: %s\n", ev.RoomID, ev.Title)
    case stream.EventOffline:
        fmt.Printf("Room %d went offline\n", ev.RoomID)
    case stream.EventAudioReady:
        // ev.Audio.Reader is an io.ReadCloser with raw PCM data
        go processAudio(ev.Audio)
    case stream.EventError:
        fmt.Printf("Error for room %d: %v\n", ev.RoomID, ev.Error)
    }
}

Dynamic room management works the same way:

client.AddRoom(99999)
client.RemoveRoom(12345)

Event Types

RoomEvent (from Monitor)
Field Type Description
RoomID int64 Bilibili room ID
Live bool true=went live, false=offline
Title string Room title (when going live)
StreamEvent (from StreamClient)
Field Type Description
RoomID int64 Bilibili room ID
Type string "live", "offline", "audio_ready", "error"
Audio *AudioStream Non-nil for "audio_ready"
Error error Non-nil for "error"
Title string Room title

Audio Format

By default, audio is captured as:

  • Format: signed 16-bit little-endian PCM (s16le)
  • Sample rate: 16000 Hz
  • Channels: 1 (mono)

This is ideal for speech-to-text pipelines. Customize via CaptureConfig.

License

MIT License - see LICENSE

Documentation

Index

Constants

View Source
const (
	EventLive       = "live"
	EventOffline    = "offline"
	EventAudioReady = "audio_ready"
	EventError      = "error"
)

Event type constants for StreamEvent.Type.

Variables

This section is empty.

Functions

func CaptureAudio

func CaptureAudio(ctx context.Context, streamURL string, cfg *CaptureConfig) (io.ReadCloser, error)

CaptureAudio starts an ffmpeg process that reads from streamURL and outputs raw PCM audio to the returned ReadCloser. The caller must close the reader or cancel the context to stop ffmpeg and release resources.

ffmpeg must be installed and available in the system PATH.

func GetStreamURL

func GetStreamURL(ctx context.Context, roomID int64) (string, error)

GetStreamURL fetches the FLV stream URL for a live room. Returns an error if the room is not currently live.

func ResolveRoomID

func ResolveRoomID(ctx context.Context, shortID int64) (int64, error)

ResolveRoomID converts a short room ID to the real (long) room ID. If the ID is already a real room ID, Bilibili returns it unchanged.

Types

type AudioStream

type AudioStream struct {
	RoomID int64
	Reader io.ReadCloser
	Cancel context.CancelFunc
}

AudioStream represents an active audio capture from a live stream. Reader delivers raw PCM data according to the CaptureConfig used. Call Cancel to stop the ffmpeg process and release resources.

type CaptureConfig

type CaptureConfig struct {
	SampleRate int    // default 16000
	Channels   int    // default 1 (mono)
	Format     string // default "s16le"
}

CaptureConfig controls ffmpeg audio capture parameters.

func DefaultCaptureConfig

func DefaultCaptureConfig() CaptureConfig

DefaultCaptureConfig returns a CaptureConfig with sensible defaults for speech processing: 16kHz mono signed 16-bit little-endian PCM.

type ClientOption

type ClientOption func(*clientConfig)

ClientOption configures a StreamClient.

func WithAudioConfig

func WithAudioConfig(cfg CaptureConfig) ClientOption

WithAudioConfig sets the audio capture parameters (sample rate, channels, format).

func WithAutoCapture

func WithAutoCapture(enabled bool) ClientOption

WithAutoCapture controls whether audio capture starts automatically when a room goes live. Default is true.

func WithClientCookie

func WithClientCookie(sessdata string) ClientOption

WithClientCookie sets the SESSDATA cookie for authenticated API requests.

func WithInterval

func WithInterval(d time.Duration) ClientOption

WithInterval sets the polling interval for live status monitoring. Default is 30 seconds.

type Monitor

type Monitor struct {
	// contains filtered or unexported fields
}

Monitor watches Bilibili live rooms for live/offline transitions and emits RoomEvent on a channel when a room's status changes.

func NewMonitor

func NewMonitor(opts ...MonitorOption) *Monitor

NewMonitor creates a Monitor with the given options.

func (*Monitor) AddRoom

func (m *Monitor) AddRoom(roomID int64)

AddRoom adds a room to the monitor. Safe to call after Watch().

func (*Monitor) RemoveRoom

func (m *Monitor) RemoveRoom(roomID int64)

RemoveRoom stops monitoring a room.

func (*Monitor) Watch

func (m *Monitor) Watch(ctx context.Context, roomIDs []int64) (<-chan RoomEvent, error)

Watch begins monitoring the given rooms and returns a channel that receives RoomEvent whenever a room transitions between live and offline. The channel is closed when ctx is cancelled.

type MonitorOption

type MonitorOption func(*monitorConfig)

MonitorOption configures a Monitor.

func WithCookie

func WithCookie(sessdata string) MonitorOption

WithCookie sets the SESSDATA cookie for authenticated API requests. This is optional; most API endpoints work without authentication.

func WithMonitorInterval

func WithMonitorInterval(d time.Duration) MonitorOption

WithMonitorInterval sets the polling interval for live status checks. Default is 30 seconds.

type RoomEvent

type RoomEvent struct {
	RoomID int64
	Live   bool   // true = went live, false = went offline
	Title  string // room title (populated when going live)
}

RoomEvent represents a live/offline transition detected by Monitor.

type RoomInfo

type RoomInfo struct {
	RoomID     int64
	ShortID    int64
	UID        int64
	LiveStatus int // 0=offline, 1=live, 2=rotation
	Title      string
	LiveTime   string
}

RoomInfo holds metadata about a Bilibili live room.

func GetRoomInfo

func GetRoomInfo(ctx context.Context, roomID int64) (*RoomInfo, error)

GetRoomInfo fetches metadata for a live room.

type StreamClient

type StreamClient struct {
	// contains filtered or unexported fields
}

StreamClient is a high-level client that combines Monitor, stream URL fetching, and ffmpeg audio capture into a single pub/sub interface.

When a room goes live, StreamClient automatically fetches the stream URL and starts audio capture (if autoCapture is enabled), emitting StreamEvent on the subscribed channel.

func NewStreamClient

func NewStreamClient(opts ...ClientOption) *StreamClient

NewStreamClient creates a StreamClient with the given options.

func (*StreamClient) AddRoom

func (c *StreamClient) AddRoom(roomID int64)

AddRoom adds a room to the client. Safe to call after Subscribe().

func (*StreamClient) RemoveRoom

func (c *StreamClient) RemoveRoom(roomID int64)

RemoveRoom stops monitoring a room and cancels any active capture.

func (*StreamClient) Subscribe

func (c *StreamClient) Subscribe(ctx context.Context, roomIDs []int64) (<-chan StreamEvent, error)

Subscribe begins monitoring the given rooms and returns a channel that receives StreamEvent for live/offline transitions, audio readiness, and errors. The channel is closed when ctx is cancelled.

type StreamEvent

type StreamEvent struct {
	RoomID int64
	Type   string       // "live", "offline", "audio_ready", "error"
	Audio  *AudioStream // non-nil when Type == "audio_ready"
	Error  error        // non-nil when Type == "error"
	Title  string
}

StreamEvent is emitted by StreamClient to report room state changes and audio capture lifecycle events.

Directories

Path Synopsis
cmd
example command
Example demonstrates the three layers of bilibili_stream_lib: 1.
Example demonstrates the three layers of bilibili_stream_lib: 1.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL