Files
scrypted/server/src/media-helpers.ts

98 lines
2.6 KiB
TypeScript

import { ChildProcess } from "child_process";
import process from 'process';
import { sleep } from "./sleep";
const filtered = [
'decode_slice_header error',
'no frame!',
'non-existing PPS',
];
export async function safeKillFFmpeg(cp: ChildProcess) {
if (!cp)
return;
if (cp.exitCode != null)
return;
await new Promise(async resolve => {
cp.on('exit', resolve);
// this will allow ffmpeg to send rtsp TEARDOWN etc
try {
cp.stdin.on('error', () => { });
cp.stdin.write('q\n');
}
catch (e) {
}
await sleep(2000);
for (const f of cp.stdio) {
try {
f?.destroy();
}
catch (e) {
}
}
cp.kill();
await sleep(2000);
cp.kill('SIGKILL');
});
}
export function ffmpegLogInitialOutput(console: Console, cp: ChildProcess, forever?: boolean, storage?: Storage) {
if (!console)
return;
const SCRYPTED_FFMPEG_NOISY = !!process.env.SCRYPTED_FFMPEG_NOISY || !!storage?.getItem('SCRYPTED_FFMPEG_NOISY');
function logger(log: (str: string) => void): (buffer: Buffer) => void {
const ret = (buffer: Buffer) => {
const str = buffer.toString();
for (const filter of filtered) {
if (str.indexOf(filter) !== -1)
return;
}
if (!SCRYPTED_FFMPEG_NOISY && !forever && (str.indexOf('frame=') !== -1 || str.indexOf('size=') !== -1)) {
log(str);
log('video/audio detected, discarding further input');
cp.stdout.removeListener('data', ret);
cp.stderr.removeListener('data', ret);
return;
}
log(str);
}
return ret;
};
cp.stdout?.on('data', logger(console.log));
cp.stderr?.on('data', logger(console.error));
cp.on('exit', () => console.log('ffmpeg exited'));
}
export function safePrintFFmpegArguments(console: Console, args: string[]) {
if (!console)
return;
const ret = [];
let redactNext = false;
for (const arg of args) {
try {
if (redactNext) {
const url = new URL(arg);
ret.push(`${url.protocol}[REDACTED]`)
}
else {
ret.push(arg);
}
}
catch (e) {
ret.push(arg);
}
// input arguments may contain passwords.
redactNext = arg === '-i';
}
console.log(ret.join(' '));
}