import { types as mediasoupTypes } from 'mediasoup'; import type { CreateMcuOptions, McuServer, McuSession, McuLayout, McuResolution } from '../types/index.js'; import { type FfmpegProcess } from './ffmpeg.js'; export declare function createMcuServer(opts: CreateMcuOptions): Promise; /** * McuSessionImpl gère 1 session = 1 publisher recording. * * Cycle : * 1. publisher WHIP ingest → on stocke ingressTransport + audio/video producers * 2. dès qu'au moins 1 producer (audio ou video) existe, on démarre ffmpeg * avec les PlainTransports correspondants * 3. ffmpeg écrit sur outputDir/. * 4. close() : kill ffmpeg, close transports, file est dispo */ export declare class McuSessionImpl implements McuSession { readonly id: string; layout: McuLayout; programInputId: string | null; readonly resolution: McuResolution; readonly inputs: any[]; readonly outputPlaylistPath: string; readonly outputPaths: string[]; readonly createdAt: number; private opts; private router; ingressTransports: mediasoupTypes.WebRtcTransport[]; producers: mediasoupTypes.Producer[]; plainTransports: mediasoupTypes.PlainTransport[]; plainConsumers: mediasoupTypes.Consumer[]; ffmpeg: FfmpegProcess | null; private _kfTimers; private _allocatedPorts; constructor(id: string, layout: McuLayout, resolution: McuResolution, opts: CreateMcuOptions, router: mediasoupTypes.Router); /** * Crée un WebRtcTransport pour l'ingest publisher WHIP. * À appeler depuis le API handler quand WHIP arrive. */ createIngressTransport(): Promise; /** * Démarre ffmpeg si pas déjà actif. Crée un PlainTransport par producer * et lance ffmpeg avec le SDP correspondant. * * Ordre critique : * 1. Crée PlainTransport + consumer en **paused** (pas de RTP encore) * 2. Alloue ports ffmpeg via dgram bind (vrais ports libres, hors plage mediasoup) * 3. transport.connect vers ces ports * 4. spawn ffmpeg → bind les sockets décrits dans le SDP * 5. wait ~500ms ffmpeg listen * 6. consumer.resume() → mediasoup pousse RTP vers ffmpeg déjà prêt */ startRecording(): Promise; /** Démonte le pipeline ffmpeg + plain transports/consumers (restart ou close). B9 : annule les timers. */ private _teardownPipeline; addInput(producerId: string): Promise; removeInput(inputId: string): Promise; switchLayout(newLayout: McuLayout): Promise; /** * Bus PROGRAMME : commute la source DIFFUSÉE (Studio LIVE TALK). * La source passe en vidéo plein écran et devient la SEULE à émettre l'audio * (audio solo). `inputId` = `appData.inputId` (ou producerId) ; `null` → revient * au layout courant. Reconstruit le pipeline ffmpeg si l'enregistrement tourne. */ setProgram(inputId: string | null): Promise; /** * Close session, finalize ffmpeg cleanly, retourne info fichier final * pour que le caller puisse l'uploader (storage hook). * @returns null si pas de recording, sinon { path, size, mimeType } */ close(): Promise<{ path: string; size: number; mimeType: string; } | null>; } //# sourceMappingURL=server.d.ts.map