stream

package
v1.3.31 Latest Latest
Warning

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

Go to latest
Published: May 25, 2026 License: MIT Imports: 23 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var Presets = []PlatformPreset{

	{
		Name:     "YouTube",
		ID:       "youtube",
		URL:      "rtmps://a.rtmp.youtube.com/live2",
		Region:   "international",
		HelpURL:  "https://support.google.com/youtube/answer/2907883",
		KeyHint:  "YouTube Studio → Go Live → Stream URL → Stream Key",
		Protocol: "rtmps",
	},
	{
		Name:     "Twitch",
		ID:       "twitch",
		URL:      "rtmps://live.twitch.tv/app",
		Region:   "international",
		HelpURL:  "https://help.twitch.tv/s/article/live-streaming-guide",
		KeyHint:  "Twitch Dashboard → Settings → Stream → Primary Stream Key",
		Protocol: "rtmps",
	},
	{
		Name:     "Facebook Live",
		ID:       "facebook",
		URL:      "rtmps://live-api-s.facebook.com:443/rtmp",
		Region:   "international",
		HelpURL:  "https://www.facebook.com/help/585152814910608",
		KeyHint:  "Facebook → Live Producer → Stream Key",
		Protocol: "rtmps",
	},
	{
		Name:     "X/Twitter",
		ID:       "twitter",
		URL:      "rtmp://rtmp.pscp.tv:80/x",
		Region:   "international",
		HelpURL:  "https://help.x.com/en/using-x/live-video",
		KeyHint:  "X → Go Live → Stream Key (per-session)",
		Protocol: "rtmp",
	},

	{
		Name:     "Bilibili (哔哩哔哩)",
		ID:       "bilibili",
		URL:      "rtmp://live-push.bilivideo.com/live-bvc",
		Region:   "china",
		HelpURL:  "https://link.bilibili.com/p/center/index",
		KeyHint:  "B站直播中心 → 我的直播间 → 开始直播 → 服务器和串流密钥",
		Protocol: "rtmp",
	},
	{
		Name:     "Douyin (抖音)",
		ID:       "douyin",
		URL:      "rtmp://push.douyin.com/app",
		Region:   "china",
		HelpURL:  "https://live.douyin.com/",
		KeyHint:  "抖音直播 → 开播设置 → 推流地址",
		Protocol: "rtmp",
	},
	{
		Name:     "Kuaishou (快手)",
		ID:       "kuaishou",
		URL:      "rtmp://push.kuaishou.com/live",
		Region:   "china",
		HelpURL:  "https://live.kuaishou.com/",
		KeyHint:  "快手直播 → 开播设置 → 推流地址(每次不同)",
		Protocol: "rtmp",
	},
	{
		Name:     "Huya (虎牙)",
		ID:       "huya",
		URL:      "rtmp://push.huya.com/live",
		Region:   "china",
		HelpURL:  "https://www.huya.com/",
		KeyHint:  "虎牙直播 → 开播设置 → 推流地址和推流码",
		Protocol: "rtmp",
	},
	{
		Name:     "Douyu (斗鱼)",
		ID:       "douyu",
		URL:      "rtmp://tx.direct.douyucdn.cn/douyu",
		Region:   "china",
		HelpURL:  "https://www.douyu.com/",
		KeyHint:  "斗鱼直播 → 开播设置 → 推流地址",
		Protocol: "rtmp",
	},
	{
		Name:     "Xiaohongshu (小红书)",
		ID:       "xiaohongshu",
		URL:      "rtmp://push.xiaohongshu.com/live",
		Region:   "china",
		HelpURL:  "https://www.xiaohongshu.com/",
		KeyHint:  "小红书 → 开播设置 → 推流地址(每次不同)",
		Protocol: "rtmp",
	},
}

Presets is the list of all built-in platform presets, ordered by region then name.

Functions

func BestEncoder

func BestEncoder(forceEncoder string) string

BestEncoder selects the optimal encoder name. If forceEncoder is non-empty, it's returned directly (user override). Otherwise, picks the first available hardware encoder, or "libx264" as fallback.

func DejaVuMonoAdvance

func DejaVuMonoAdvance(points float64) (charWidth, charHeight int)

DejaVuMonoAdvance returns the advance width and line height of DejaVu Mono at the given point size.

func DejaVuMonoBold

func DejaVuMonoBold() []byte

DejaVuMonoBold returns the embedded DejaVu Sans Mono bold font bytes.

func DejaVuMonoRegular

func DejaVuMonoRegular() []byte

DejaVuMonoRegular returns the embedded DejaVu Sans Mono regular font bytes.

func EncoderIsHardware

func EncoderIsHardware(name string) bool

EncoderIsHardware reports whether the given encoder name is a hardware encoder.

func FindCJKFont

func FindCJKFont() string

func FindEmojiFont added in v1.1.85

func FindEmojiFont() string

FindEmojiFont finds a system font capable of rendering emoji (color or monochrome).

func FindMonoFont

func FindMonoFont() string

FindMonoFont finds a monospace font (any language).

func IsEmoji added in v1.1.85

func IsEmoji(r rune) bool

IsEmoji returns true if the rune is in an emoji Unicode block.

func IsWide

func IsWide(r rune) bool

IsWide returns true if the rune is a wide (CJK) character.

func IsWideCol

func IsWideCol(r rune) int

IsWideCol returns the display column width of a rune (1 or 2).

func PresetNames

func PresetNames() []string

PresetNames returns a list of all preset display names.

func PresetsByRegion

func PresetsByRegion() map[string][]PlatformPreset

PresetsByRegion returns presets grouped by region.

func ReadFontFile

func ReadFontFile(path string) ([]byte, error)

func StatFile

func StatFile(path string) (os.FileInfo, error)

ReadFontFile reads a font file and returns its bytes. ReadFontFile reads a font file and returns raw font data. Both TTF and TTC (TrueType Collection) formats are supported by truetype.Parse. StatFile checks if a file exists.

Types

type DirectRenderer

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

DirectRenderer converts ANSI terminal strings directly to *image.RGBA without intermediate PNG encoding/decoding.

Font strategy:

  • Primary: embedded DejaVu Mono (true monospace, covers ASCII + box-drawing)
  • Symbols fallback: system monospace font (covers ▶●✓❯█ etc.)
  • CJK fallback: system CJK font (covers Chinese/Japanese/Korean)

func NewDirectRenderer

func NewDirectRenderer(width, height, fontSize int, fontPath string, termCols, termRows int) *DirectRenderer

NewDirectRenderer creates a renderer that produces *image.RGBA directly.

func (*DirectRenderer) Cols

func (r *DirectRenderer) Cols() int

Cols returns terminal column count.

func (*DirectRenderer) FontInfo

func (r *DirectRenderer) FontInfo() string

FontInfo returns a human-readable description of the loaded font.

func (*DirectRenderer) Render

func (r *DirectRenderer) Render(ansiText string) (*image.RGBA, error)

Render converts ANSI text directly to an *image.RGBA.

func (*DirectRenderer) Rows

func (r *DirectRenderer) Rows() int

Rows returns terminal row count.

type Encoder

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

Encoder wraps an FFmpeg subprocess that encodes raw RGBA frames into FLV.

func NewEncoder

func NewEncoder(width, height, quality, fps int, hwEncoder string) *Encoder

NewEncoder creates a new encoder for the given resolution and quality.

func (*Encoder) ExpectedFrameSize

func (e *Encoder) ExpectedFrameSize() int

ExpectedFrameSize returns the expected raw RGBA frame size in bytes.

func (*Encoder) IsRunning

func (e *Encoder) IsRunning() bool

IsRunning returns whether the encoder subprocess is active.

func (*Encoder) Read

func (e *Encoder) Read(p []byte) (int, error)

Read reads encoded FLV data from the encoder stdout. Implements io.Reader for fan-out consumers.

func (*Encoder) Start

func (e *Encoder) Start() error

Start launches the FFmpeg encoder subprocess.

func (*Encoder) Stop

func (e *Encoder) Stop() error

Stop signals the encoder to finish and waits for the process to exit.

func (*Encoder) WriteFrame

func (e *Encoder) WriteFrame(data []byte) error

WriteFrame writes a single raw RGBA frame to the encoder.

type FFmpegCheck

type FFmpegCheck struct {
	Available bool
	Path      string
	Version   string
	Major     int
	Minor     int
	Error     string
}

FFmpegCheck holds the result of an ffmpeg availability check.

func CheckFFmpeg

func CheckFFmpeg() FFmpegCheck

CheckFFmpeg verifies that ffmpeg is installed and meets the minimum version requirement.

type FontSearchResult

type FontSearchResult struct {
	Path  string
	Name  string
	IsCJK bool
}

FontSearchResult holds the result of a system font search.

func FindSystemFonts

func FindSystemFonts() []FontSearchResult

FindSystemFonts searches for monospace fonts on the system. Returns CJK-capable fonts first, then fallback fonts.

type HardwareEncoder

type HardwareEncoder struct {
	Name        string // e.g., "h264_videotoolbox"
	Description string // e.g., "VideoToolbox H.264"
	Platform    string // e.g., "darwin", "linux"
}

HardwareEncoder represents a detected hardware encoder.

func DetectHardwareEncoders

func DetectHardwareEncoders() []HardwareEncoder

DetectHardwareEncoders probes FFmpeg for available hardware H.264 encoders. Results are cached after first call.

type Manager

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

Manager orchestrates live streaming: captures TUI frames, encodes via FFmpeg, and fans out to multiple platform targets.

func NewManager

func NewManager(config StreamConfig) *Manager

NewManager creates a new stream manager with the given configuration.

func (*Manager) EncoderSize

func (m *Manager) EncoderSize() (int, int)

Status returns the status of all streaming targets. EncoderSize returns the actual encoder output resolution. Returns 0,0 if streaming hasn't started yet.

func (*Manager) FPS

func (m *Manager) FPS() int

func (*Manager) IsRunning

func (m *Manager) IsRunning() bool

IsRunning returns whether the manager is actively streaming.

func (*Manager) Start

func (m *Manager) Start(viewFunc ViewFunc) error

Start begins the streaming pipeline. viewFunc is called at the configured FPS to capture TUI frames.

func (*Manager) Status

func (m *Manager) Status() []TargetStatus

func (*Manager) Stop

func (m *Manager) Stop()

Stop shuts down the entire streaming pipeline.

func (*Manager) StopTarget

func (m *Manager) StopTarget(name string) error

StopTarget stops a specific target by name.

type PlatformPreset

type PlatformPreset struct {
	// Name is the display name (e.g., "YouTube", "Bilibili").
	Name string
	// ID is the unique identifier used in config (e.g., "youtube", "bilibili").
	ID string
	// URL is the default RTMP/RTMPS push endpoint (without stream key).
	URL string
	// Region is "international" or "china".
	Region string
	// HelpURL is a link to docs on finding the stream key.
	HelpURL string
	// KeyHint is a hint about where to find the stream key.
	KeyHint string
	// Protocol is "rtmp" or "rtmps".
	Protocol string
}

PlatformPreset defines a built-in streaming platform configuration template.

func PresetByID

func PresetByID(id string) *PlatformPreset

PresetByID returns a preset by its ID, or nil if not found.

type StreamConfig

type StreamConfig struct {
	// HardwareEncoder controls which H.264 encoder to use.
	// "auto" — detect best available (default)
	// "software" — force libx264
	// "h264_videotoolbox", "h264_nvenc", "h264_qsv", "h264_vaapi" — force specific
	HardwareEncoder string `yaml:"hardware_encoder,omitempty" json:"hardware_encoder,omitempty"`
	FPS             int    `yaml:"fps,omitempty" json:"fps,omitempty"`
	// Width of the output video in pixels (default 1280).
	Width int `yaml:"width,omitempty" json:"width,omitempty"`
	// Height of the output video in pixels (default 720).
	Height int `yaml:"height,omitempty" json:"height,omitempty"`
	// Quality is the H.264 QP value (default 26). Lower = better quality, higher bitrate.
	Quality int `yaml:"quality,omitempty" json:"quality,omitempty"`
	// FontSize in points for the terminal font rendering (default 14).
	FontSize int `yaml:"font_size,omitempty" json:"font_size,omitempty"`
	// FontPath is an optional path to a custom TTF font file.
	FontPath string `yaml:"font_path,omitempty" json:"font_path,omitempty"`
	// Targets is the list of streaming platform targets.
	Targets []StreamTarget `yaml:"targets,omitempty" json:"targets,omitempty"`
}

StreamConfig holds live-streaming configuration.

func (*StreamConfig) ApplyDefaults

func (c *StreamConfig) ApplyDefaults()

ApplyDefaults fills in zero-valued fields with sensible defaults.

func (*StreamConfig) ExpandEnv

func (c *StreamConfig) ExpandEnv()

ExpandEnv expands ${ENV_VAR} references in all target stream keys.

func (*StreamConfig) Validate

func (c *StreamConfig) Validate() error

Validate checks the configuration for errors.

type StreamTarget

type StreamTarget struct {
	// Name is a human-readable identifier (e.g., "youtube", "bilibili").
	Name string `yaml:"name" json:"name"`
	// Enabled controls whether this target is active.
	Enabled bool `yaml:"enabled,omitempty" json:"enabled,omitempty"`
	// URL is the RTMP/RTMPS endpoint (without the stream key).
	// Examples:
	//   - YouTube: rtmps://a.rtmp.youtube.com/live2
	//   - Bilibili: rtmp://live-push.bilivideo.com/live-bvc
	//   - Twitch:  rtmps://live.twitch.tv/app
	URL string `yaml:"url" json:"url"`
	// Key is the stream key. Supports ${ENV_VAR} expansion.
	Key string `yaml:"key" json:"key"`
}

StreamTarget represents a single streaming platform destination.

func (*StreamTarget) FullURL

func (t *StreamTarget) FullURL() string

FullURL returns the complete RTMP URL with stream key appended.

type Target

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

Target pushes an FLV stream to a single streaming platform via FFmpeg.

func NewTarget

func NewTarget(name, fullURL string) *Target

NewTarget creates a new streaming target.

func (*Target) Connect

func (t *Target) Connect() (io.Writer, error)

Connect starts the FFmpeg subprocess that pushes FLV data to the platform. The caller writes FLV data to the returned io.Writer (the target's stdin).

func (*Target) Name

func (t *Target) Name() string

Name returns the target's display name.

func (*Target) State

func (t *Target) State() TargetState

State returns the current target state (thread-safe).

func (*Target) Status

func (t *Target) Status() TargetStatus

Status returns a snapshot of the target's current status.

func (*Target) Stop

func (t *Target) Stop()

Stop terminates the FFmpeg subprocess.

func (*Target) Write

func (t *Target) Write(p []byte) (int, error)

Write forwards FLV data to the target's FFmpeg subprocess. Implements io.Writer for fan-out.

type TargetState

type TargetState string

TargetState represents the current state of a streaming target.

const (
	TargetIdle       TargetState = "idle"
	TargetConnecting TargetState = "connecting"
	TargetLive       TargetState = "live"
	TargetError      TargetState = "error"
	TargetStopped    TargetState = "stopped"
)

type TargetStatus

type TargetStatus struct {
	Name      string        `json:"name"`
	State     TargetState   `json:"state"`
	URL       string        `json:"url"` // masked URL (key hidden)
	LastError string        `json:"last_error"`
	Uptime    time.Duration `json:"uptime"`
	BytesSent int64         `json:"bytes_sent"`
}

TargetStatus holds a snapshot of a target's current state.

type TerminalSize

type TerminalSize struct {
	Cols int
	Rows int
}

TerminalSize holds the current terminal dimensions in characters.

type ViewFunc

type ViewFunc func() (content string, size TerminalSize)

ViewFunc returns the current TUI rendering as an ANSI string. The manager calls this at the target FPS to capture frames.

Jump to

Keyboard shortcuts

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