feat(capture): wire bridge process lifecycle into start/stop for deltacast
This commit is contained in:
parent
4da7bf8b41
commit
d4924b044f
1 changed files with 15 additions and 3 deletions
|
|
@ -355,7 +355,8 @@ class CaptureManager {
|
||||||
|
|
||||||
const startedAt = new Date().toISOString();
|
const startedAt = new Date().toISOString();
|
||||||
|
|
||||||
const { inputArgs, isNetwork } = await this._buildInputArgs({
|
this._sessionIdForBridge = sessionId;
|
||||||
|
const { inputArgs, isNetwork, bridgeProcess = null, audioFifo = null, interlaced = false } = await this._buildInputArgs({
|
||||||
sourceType, device, sourceUrl, listen, listenPort, streamKey,
|
sourceType, device, sourceUrl, listen, listenPort, streamKey,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -369,7 +370,8 @@ class CaptureManager {
|
||||||
|
|
||||||
console.log('[capture] hires ffmpeg args:', hiresCodecArgs.join(' '));
|
console.log('[capture] hires ffmpeg args:', hiresCodecArgs.join(' '));
|
||||||
|
|
||||||
const sdiFilterArgs = (sourceType === 'sdi') ? ['-vf', 'yadif=mode=1:deint=1'] : [];
|
const isInterlacedSource = sourceType === 'sdi' || (sourceType === 'deltacast' && interlaced);
|
||||||
|
const sdiFilterArgs = isInterlacedSource ? ['-vf', 'yadif=mode=1:deint=1'] : [];
|
||||||
|
|
||||||
// When growing-files is on, write directly to the SMB share so Premier
|
// When growing-files is on, write directly to the SMB share so Premier
|
||||||
// can mount and edit the live file. Promotion worker uploads to S3 on EOF.
|
// can mount and edit the live file. Promotion worker uploads to S3 on EOF.
|
||||||
|
|
@ -382,7 +384,7 @@ class CaptureManager {
|
||||||
// ffmpeg: one decklink read -> yadif -> split -> [ProRes/S3] + [H.264/HLS].
|
// ffmpeg: one decklink read -> yadif -> split -> [ProRes/S3] + [H.264/HLS].
|
||||||
let sdiHlsDir = null;
|
let sdiHlsDir = null;
|
||||||
let hiresArgs;
|
let hiresArgs;
|
||||||
if (sourceType === 'sdi' && this._assetIdForHls) {
|
if ((sourceType === 'sdi' || sourceType === 'deltacast') && this._assetIdForHls) {
|
||||||
const fsMod = await import('node:fs');
|
const fsMod = await import('node:fs');
|
||||||
sdiHlsDir = '/live/' + this._assetIdForHls;
|
sdiHlsDir = '/live/' + this._assetIdForHls;
|
||||||
try { fsMod.mkdirSync(sdiHlsDir, { recursive: true }); } catch (_) {}
|
try { fsMod.mkdirSync(sdiHlsDir, { recursive: true }); } catch (_) {}
|
||||||
|
|
@ -409,12 +411,16 @@ class CaptureManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
const hiresProcess = spawn('ffmpeg', hiresArgs, { stdio: hiresStdio });
|
const hiresProcess = spawn('ffmpeg', hiresArgs, { stdio: hiresStdio });
|
||||||
|
if (bridgeProcess) {
|
||||||
|
bridgeProcess.stdout.pipe(hiresProcess.stdin);
|
||||||
|
}
|
||||||
|
|
||||||
const hiresUpload = growingPath
|
const hiresUpload = growingPath
|
||||||
? Promise.resolve({ growingPath })
|
? Promise.resolve({ growingPath })
|
||||||
: createUploadStream(S3_BUCKET, hiresKey, hiresProcess.stdout);
|
: createUploadStream(S3_BUCKET, hiresKey, hiresProcess.stdout);
|
||||||
|
|
||||||
const processes = { hires: hiresProcess };
|
const processes = { hires: hiresProcess };
|
||||||
|
if (bridgeProcess) processes.bridge = bridgeProcess;
|
||||||
const uploads = { hires: hiresUpload };
|
const uploads = { hires: hiresUpload };
|
||||||
|
|
||||||
// ── HLS tee for network sources (live preview in the UI) ──────────
|
// ── HLS tee for network sources (live preview in the UI) ──────────
|
||||||
|
|
@ -478,6 +484,7 @@ class CaptureManager {
|
||||||
device,
|
device,
|
||||||
sourceType,
|
sourceType,
|
||||||
sourceUrl,
|
sourceUrl,
|
||||||
|
audioFifo,
|
||||||
hiresKey,
|
hiresKey,
|
||||||
proxyKey,
|
proxyKey,
|
||||||
growingPath,
|
growingPath,
|
||||||
|
|
@ -505,6 +512,7 @@ class CaptureManager {
|
||||||
if (processes.hires) processes.hires.kill('SIGINT');
|
if (processes.hires) processes.hires.kill('SIGINT');
|
||||||
if (processes.proxy) processes.proxy.kill('SIGINT');
|
if (processes.proxy) processes.proxy.kill('SIGINT');
|
||||||
if (processes.hls) { try { processes.hls.kill('SIGINT'); } catch (_) {} }
|
if (processes.hls) { try { processes.hls.kill('SIGINT'); } catch (_) {} }
|
||||||
|
if (processes.bridge) { try { processes.bridge.kill('SIGINT'); } catch (_) {} }
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const uploadPromises = [currentSession.uploads.hires];
|
const uploadPromises = [currentSession.uploads.hires];
|
||||||
|
|
@ -514,6 +522,10 @@ class CaptureManager {
|
||||||
console.error('Error during upload completion:', error);
|
console.error('Error during upload completion:', error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (currentSession.audioFifo) {
|
||||||
|
try { (await import('node:fs')).unlinkSync(currentSession.audioFifo); } catch (_) {}
|
||||||
|
}
|
||||||
|
|
||||||
const stoppedAt = new Date().toISOString();
|
const stoppedAt = new Date().toISOString();
|
||||||
const startTime = new Date(currentSession.startedAt);
|
const startTime = new Date(currentSession.startedAt);
|
||||||
const stopTime = new Date(stoppedAt);
|
const stopTime = new Date(stoppedAt);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue