/** * Stream Manager — cross-platform RTMP streaming via FFmpeg. * * Supports multiple input modes: * - "pipe": Receives JPEG frames via writeFrame() → FFmpeg stdin (image2pipe). * Used for streaming Electron window contents captured with capturePage(). * - "avfoundation" / "screen": macOS native screen capture. * - "x11grab": Linux virtual display capture (Xvfb). Like Hyperscape's approach. * - "file": Reads a continuously-updated JPEG file (browser-capture). * - "testsrc": Solid color test pattern (default fallback). * * Audio support: * - "silent": Synthetic silent audio (anullsrc) — default. * - "system": System/desktop audio capture. * - "microphone": Microphone input. * - File path: Play an audio file as stream audio. * * Volume control: * - setVolume(0-100), mute(), unmute() — restarts FFmpeg to apply. * * Usage: * import { streamManager } from "./services/stream-manager"; * await streamManager.start({ rtmpUrl, rtmpKey, inputMode: "pipe" }); * streamManager.writeFrame(jpegBuffer); // called from frame capture * streamManager.setVolume(50); // adjust volume mid-stream * await streamManager.stop(); * * @module services/stream-manager */ import { type ITtsStreamBridge } from "./tts-stream-bridge"; export type AudioSource = "silent" | "system" | "microphone" | "tts"; export interface StreamConfig { rtmpUrl: string; rtmpKey: string; /** FFmpeg video input source. Defaults to "testsrc" (test pattern). */ inputMode?: "testsrc" | "avfoundation" | "screen" | "pipe" | "file" | "x11grab"; /** avfoundation video device index (default "3" = Capture screen 0 on macOS) */ videoDevice?: string; /** Path to JPEG frame file (for "file" input mode) */ frameFile?: string; /** Resolution (default "1280x720") */ resolution?: string; /** Video bitrate (default "2500k") */ bitrate?: string; /** Frame rate (default 15) */ framerate?: number; /** X11 display for x11grab mode (e.g., ":99"). Default ":99". */ display?: string; /** Audio source. Default "silent" (anullsrc). Can also be an absolute file path. */ audioSource?: AudioSource | string; /** Audio device identifier (platform-specific). For macOS avfoundation: device index. For Linux: pulse/alsa device name. */ audioDevice?: string; /** Volume level 0–100. Default 80. Applied as FFmpeg audio filter. */ volume?: number; /** Whether audio is muted. Default false. Overrides volume to 0 when true. */ muted?: boolean; } declare class StreamManager { private ffmpeg; private _running; private startedAt; private _frameCount; /** Current stream config — stored for restart on volume/audio changes. */ private _config; /** Current volume level (0–100). */ private _volume; /** Whether audio is muted. */ private _muted; /** Auto-restart state. */ private _restartAttempts; private _maxRestartAttempts; private _restartDecayTimer; private _intentionalStop; /** Pending auto-restart timer — cleared in stop() to prevent races. */ private _restartTimer; /** Guard: prevents concurrent start() calls from orphaning FFmpeg. */ private _starting; isRunning(): boolean; getUptime(): number; getHealth(): { running: boolean; ffmpegAlive: boolean; uptime: number; frameCount: number; volume: number; muted: boolean; audioSource: string; inputMode: "pipe" | "file" | "screen" | "testsrc" | "avfoundation" | "x11grab" | null; }; getVolume(): number; isMuted(): boolean; /** * Set volume (0–100). Restarts FFmpeg if currently streaming to apply the change. */ setVolume(level: number): Promise; /** Mute audio. Restarts FFmpeg if currently streaming. */ mute(): Promise; /** Unmute audio. Restarts FFmpeg if currently streaming. */ unmute(): Promise; /** Restart the stream with updated config (preserves uptime tracking). */ private restart; /** * Write a JPEG frame to FFmpeg's stdin (only works in "pipe" mode). * Returns true if the frame was accepted. */ writeFrame(jpegData: Buffer): boolean; start(config: StreamConfig): Promise; private _startInner; stop(): Promise<{ uptime: number; }>; /** Attempt to restart FFmpeg after unexpected exit with exponential backoff. */ private autoRestart; private buildVideoInputArgs; private buildAudioInputArgs; /** Get the TTS stream bridge for external speak triggers. */ getTtsBridge(): ITtsStreamBridge; } export declare const streamManager: StreamManager; export {}; //# sourceMappingURL=stream-manager.d.ts.map