const http = require('http'); const https = require('https'); const requestJson = (url, { timeoutMs = 2000 } = {}) => { return new Promise((resolve, reject) => { const u = new URL(url); const lib = u.protocol === 'https:' ? https : http; const req = lib.request( { protocol: u.protocol, hostname: u.hostname, port: u.port, path: `${u.pathname}${u.search}`, method: 'GET' }, (res) => { let raw = ''; res.setEncoding('utf8'); res.on('data', (chunk) => (raw += chunk)); res.on('end', () => { if (res.statusCode && (res.statusCode < 200 || res.statusCode >= 300)) { return reject(new Error(`SRS HTTP API status ${res.statusCode}`)); } try { resolve(JSON.parse(raw || '{}')); } catch (e) { reject(new Error('Invalid JSON from SRS HTTP API')); } }); } ); req.on('error', reject); req.setTimeout(timeoutMs, () => { req.destroy(new Error('SRS HTTP API request timeout')); }); req.end(); }); }; const normalizeStreamName = (s) => { if (!s) return null; if (typeof s === 'string') return s; return s.stream || s.name || s.id || null; }; const isPublishActive = (streamObj) => { const publish = streamObj && streamObj.publish; if (!publish) return false; if (typeof publish.active === 'boolean') return publish.active; return Boolean(publish.cid); }; let warnedOnce = false; const getActiveStreamKeys = async ({ app = 'live' } = {}) => { const host = process.env.SRS_HOST || 'localhost'; const apiPort = process.env.SRS_API_PORT || 1985; const url = `http://${host}:${apiPort}/api/v1/streams/?count=100`; try { const payload = await requestJson(url, { timeoutMs: 1500 }); const streams = payload.streams || payload.data?.streams || []; const active = new Set(); for (const s of streams) { if (app && s.app && s.app !== app) continue; if (!isPublishActive(s)) continue; const name = normalizeStreamName(s); if (name) active.add(name); } return active; } catch (e) { if (!warnedOnce) { warnedOnce = true; console.warn(`[SRS] HTTP API unavailable at ${url}`); console.warn(`[SRS] Error: ${e.message}`); console.warn(`[SRS] Will fallback to callbacks/in-memory status.`); } return new Set(); } }; module.exports = { getActiveStreamKeys };