zhibo/live-streaming/server/utils/srsHttpApi.js

89 lines
2.3 KiB
JavaScript

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}. Will fallback to callbacks/in-memory status.`);
}
return new Set();
}
};
module.exports = {
getActiveStreamKeys
};