import api from './client' export interface RenditionConfig { label: string enabled: boolean width: number height: number fps: number codec: 'libx264' | 'libx265' bitrate: string crf: number preset: 'ultrafast' | 'superfast' | 'veryfast' | 'faster' | 'fast' | 'medium' | 'slow' audio_bitrate: string keyframe_seconds: number } export interface StreamInfo { id: number title: string description?: string cover_url?: string stream_key?: string status: string scheduled_at?: string started_at?: string ended_at?: string multicast_enabled: boolean created_at: string replay_file?: string replay_url?: string chapters: Chapter[] transcode_profile: string renditions?: RenditionConfig[] | null homepage_visible: boolean remote_control_enabled: boolean } export interface Chapter { title: string time: number } export interface StreamCreateReq { title: string description?: string cover_url?: string scheduled_at?: string replay_file?: string | null replay_url?: string | null chapters?: Chapter[] transcode_profile?: string renditions?: RenditionConfig[] homepage_visible?: boolean remote_control_enabled?: boolean } export interface WatchInfo { stream_id: number title: string status: string multicast_available: boolean selected_node?: { id: string; name: string } | null lines: LineInfo[] qualities: QualityInfo[] description?: string scheduled_at?: string replay_url?: string replay_local_url?: string chapters: Chapter[] remote_control_enabled: boolean } export interface LineInfo { node_id: string node_name: string weight: number type: string url: string unicast_fallback?: string qualities: QualityUrl[] } export interface QualityUrl { label: string width: number height: number url: string } export interface QualityInfo { label: string width: number height: number } export interface ViewerSessionInfo { session_id: string node_id?: string node_name?: string quality?: string playback_state: string buffered_seconds?: number error?: string remote_adjusted: boolean last_heartbeat: string } export interface ControlAuditInfo { id: number operator: string target_session_id: string action: string value?: string status: string result?: string created_at: string claimed_at?: string } export interface RemoteCommandInfo { id: number action: 'switch_node' | 'switch_quality' | 'restore_auto' value?: string created_at: string } export async function fetchStreams(admin = false): Promise { const { data } = await api.get('/streams', { params: admin ? { admin: true } : undefined }) return data } export async function fetchMediaFiles(): Promise { const { data } = await api.get('/streams/media-files') return data } export async function createStream(req: StreamCreateReq): Promise<{ id: number; stream_key: string; rtmp_url: string; status: string }> { const { data } = await api.post('/streams', req) return data } export async function getStream(streamId: number): Promise { const { data } = await api.get(`/streams/${streamId}`) return data } export async function updateStream(streamId: number, req: Partial): Promise { await api.put(`/streams/${streamId}`, req) } export async function deleteStream(streamId: number): Promise { await api.delete(`/streams/${streamId}`) } export async function goLive(streamId: number): Promise { await api.post(`/streams/${streamId}/go-live`) } export async function endStream(streamId: number): Promise { await api.post(`/streams/${streamId}/end`) } export async function getWatchUrls(streamId: number): Promise { const { data } = await api.get(`/streams/${streamId}/watch`) return data } export function getStreamStatusUrl(streamId: number): string { return `/api/streams/${streamId}/events` } export async function sendViewerHeartbeat(streamId: number, payload: Record): Promise<{ remote_adjusted: boolean }> { const { data } = await api.post(`/streams/${streamId}/viewer-heartbeat`, payload) return data } export async function pollRemoteCommand(streamId: number, sessionId: string): Promise { const { data } = await api.get(`/streams/${streamId}/remote-command`, { params: { session_id: sessionId } }) return data } export async function reportRemoteCommandResult(streamId: number, commandId: number, sessionId: string, result: string): Promise { await api.post(`/streams/${streamId}/remote-command/${commandId}/result`, { result }, { params: { session_id: sessionId } }) } export async function fetchViewerSessions(streamId: number): Promise { const { data } = await api.get(`/streams/${streamId}/viewer-sessions`) return data } export async function fetchControlAudit(streamId: number): Promise { const { data } = await api.get(`/streams/${streamId}/control-audit`) return data } export async function createRemoteSession(streamId: number, expiresIn = 300): Promise<{ token: string; expires_in: number }> { const { data } = await api.post(`/streams/${streamId}/remote-session`, { expires_in: expiresIn }) return data } export async function sendRemoteCommand(streamId: number, token: string, action: string, targets: string[], value?: string): Promise { await api.post(`/streams/${streamId}/remote-command`, { token, action, targets, value }) }