const fs = require('fs'); const net = require('net'); const path = require('path'); const MARKER = path.join(__dirname, '..', '..', '.audio_bridge'); const FRAME_MAX = 4 * 1024 * 1024; const bridgePort = () => { try { const port = Number(String(fs.readFileSync(MARKER, 'utf8')).trim()); return Number.isFinite(port) && port > 0 ? port : 0; } catch (_) { return 0; } }; module.exports = () => ({ open(file, { onJpeg, onPcm, onEnd }) { let ended = false; const finish = () => { if (ended) return; ended = true; try { onEnd(); } catch (_) {} }; const port = bridgePort(); if (!port) { setImmediate(finish); return { stop() { ended = true; } }; } const sock = net.connect(port, '127.0.0.1'); let buf = Buffer.alloc(0); sock.setNoDelay(true); sock.on('error', finish); sock.on('close', finish); sock.on('connect', () => sock.write(Buffer.concat([Buffer.from('S'), Buffer.from(`${file}\n`, 'utf8')]))); sock.on('data', (chunk) => { buf = buf.length ? Buffer.concat([buf, chunk]) : chunk; while (buf.length >= 5) { const len = buf.readUInt32BE(1); if (len > FRAME_MAX) { sock.destroy(); return; } if (buf.length < 5 + len) return; const type = buf[0]; const payload = Buffer.from(buf.subarray(5, 5 + len)); buf = buf.subarray(5 + len); if (ended) continue; if (type === 0x4a) onJpeg(payload); else if (type === 0x41) onPcm(payload); else if (type === 0x45) { finish(); sock.destroy(); return; } } }); return { stop() { ended = true; try { sock.destroy(); } catch (_) {} } }; } });