From 4391eea04db1f5a3526a1e6f9f7fb3d0a0f9b2aa Mon Sep 17 00:00:00 2001 From: CN-JS-HuiBai Date: Sat, 4 Apr 2026 12:54:02 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0Watchdog?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server.js | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/server.js b/server.js index d0b41d7..a4ef5d0 100644 --- a/server.js +++ b/server.js @@ -679,9 +679,26 @@ app.get('/api/hls/playlist.m3u8', async (req, res) => { res.setHeader('Cache-Control', 'no-cache'); res.send(m3u8); }); - const hlsProcesses = new Map(); +// Watchdog: Kill HLS transcoding if the frontend stops requesting segments +setInterval(() => { + const now = Date.now(); + for (const [key, processInfo] of hlsProcesses.entries()) { + if (processInfo.lastActive && now - processInfo.lastActive > 30000) { + try { + if (processInfo.command) { + processInfo.command.kill('SIGKILL'); + } + } catch (e) { + console.warn(`Failed to kill inactive HLS process for ${key}:`, e); + } + hlsProcesses.delete(key); + console.log(`[Watchdog] Terminated inactive HLS transcode for ${key}`); + } + } +}, 10000); + app.get('/api/hls/segment.ts', async (req, res) => { const bucket = req.query.bucket; const key = req.query.key; @@ -702,6 +719,10 @@ app.get('/api/hls/segment.ts', async (req, res) => { const targetSegPath = path.join(hlsDir, `segment_${seg}.ts`); let currentProcess = hlsProcesses.get(progressKey); + if (currentProcess) { + currentProcess.lastActive = Date.now(); + } + const checkIsCachedAndCompleted = () => { if (!fs.existsSync(targetSegPath)) return false; const m3u8Path = path.join(hlsDir, `temp.m3u8`); @@ -799,7 +820,7 @@ app.get('/api/hls/segment.ts', async (req, res) => { }); ffmpegCommand.run(); - currentProcess = { command: ffmpegCommand, currentSeg: seg }; + currentProcess = { command: ffmpegCommand, currentSeg: seg, lastActive: Date.now() }; hlsProcesses.set(progressKey, currentProcess); } @@ -807,8 +828,10 @@ app.get('/api/hls/segment.ts', async (req, res) => { if (!ready) { return res.status(500).send('Segment generation timeout'); } - - if (currentProcess) currentProcess.currentSeg = Math.max(currentProcess.currentSeg, seg); + if (currentProcess) { + currentProcess.currentSeg = Math.max(currentProcess.currentSeg, seg); + currentProcess.lastActive = Date.now(); + } res.setHeader('Content-Type', 'video/MP2T'); res.sendFile(targetSegPath);