mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-15 17:12:59 -04:00
repalay
This commit is contained in:
@@ -12,7 +12,7 @@ const { getRoomCameras, roomCameraEvents } = require('./roomCameraService');
|
|||||||
const execFileAsync = promisify(execFile);
|
const execFileAsync = promisify(execFile);
|
||||||
|
|
||||||
const FFMPEG_BIN = process.env.FFMPEG_BIN || 'ffmpeg';
|
const FFMPEG_BIN = process.env.FFMPEG_BIN || 'ffmpeg';
|
||||||
const SEGMENT_ROOT = process.env.REPLAY_SEGMENT_DIR || '/var/lib/replay-segments-v2';
|
const SEGMENT_ROOT = process.env.REPLAY_SEGMENT_DIR || '/var/lib/replay-segments';
|
||||||
const SEGMENT_SECONDS = Math.max(1, Number.parseInt(process.env.REPLAY_SEGMENT_SECONDS || '1', 10));
|
const SEGMENT_SECONDS = Math.max(1, Number.parseInt(process.env.REPLAY_SEGMENT_SECONDS || '1', 10));
|
||||||
const BUFFER_SECONDS = Math.max(20, Number.parseInt(process.env.REPLAY_BUFFER_SECONDS || '45', 10));
|
const BUFFER_SECONDS = Math.max(20, Number.parseInt(process.env.REPLAY_BUFFER_SECONDS || '45', 10));
|
||||||
const CLEANUP_INTERVAL_MS = 10_000;
|
const CLEANUP_INTERVAL_MS = 10_000;
|
||||||
@@ -28,13 +28,14 @@ const events = new EventEmitter();
|
|||||||
const workers = new Map(); // key -> worker
|
const workers = new Map(); // key -> worker
|
||||||
const segmentIndex = new Map(); // key -> [{filePath,startMs,endMs,mtimeMs,size,kind,sourceType,sourceId}]
|
const segmentIndex = new Map(); // key -> [{filePath,startMs,endMs,mtimeMs,size,kind,sourceType,sourceId}]
|
||||||
let cleanupTimer = null;
|
let cleanupTimer = null;
|
||||||
|
let activeSegmentRoot = SEGMENT_ROOT;
|
||||||
|
|
||||||
function sourceKey(source) {
|
function sourceKey(source) {
|
||||||
return `${source.sourceType}__${source.kind}__${source.id}`;
|
return `${source.sourceType}__${source.kind}__${source.id}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function sourceDirForKey(key) {
|
function sourceDirForKey(key) {
|
||||||
return path.join(SEGMENT_ROOT, key);
|
return path.join(activeSegmentRoot, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
function toSrtReadPath(streamId) {
|
function toSrtReadPath(streamId) {
|
||||||
@@ -312,11 +313,11 @@ async function refreshSegmentIndex() {
|
|||||||
async function cleanupOldFiles() {
|
async function cleanupOldFiles() {
|
||||||
const cutoff = Date.now() - BUFFER_SECONDS * 1000;
|
const cutoff = Date.now() - BUFFER_SECONDS * 1000;
|
||||||
try {
|
try {
|
||||||
await ensureDir(SEGMENT_ROOT);
|
await ensureDir(activeSegmentRoot);
|
||||||
const dirs = await fsp.readdir(SEGMENT_ROOT, { withFileTypes: true });
|
const dirs = await fsp.readdir(activeSegmentRoot, { withFileTypes: true });
|
||||||
for (const dirent of dirs) {
|
for (const dirent of dirs) {
|
||||||
if (!dirent.isDirectory()) continue;
|
if (!dirent.isDirectory()) continue;
|
||||||
const dirPath = path.join(SEGMENT_ROOT, dirent.name);
|
const dirPath = path.join(activeSegmentRoot, dirent.name);
|
||||||
let files;
|
let files;
|
||||||
try {
|
try {
|
||||||
files = await fsp.readdir(dirPath, { withFileTypes: true });
|
files = await fsp.readdir(dirPath, { withFileTypes: true });
|
||||||
@@ -654,8 +655,8 @@ function getReplayHealthSnapshot() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function bootstrapIndexFromDisk() {
|
async function bootstrapIndexFromDisk() {
|
||||||
await ensureDir(SEGMENT_ROOT);
|
await ensureDir(activeSegmentRoot);
|
||||||
const dirs = await fsp.readdir(SEGMENT_ROOT, { withFileTypes: true });
|
const dirs = await fsp.readdir(activeSegmentRoot, { withFileTypes: true });
|
||||||
for (const dirent of dirs) {
|
for (const dirent of dirs) {
|
||||||
if (!dirent.isDirectory()) continue;
|
if (!dirent.isDirectory()) continue;
|
||||||
segmentIndex.set(dirent.name, []);
|
segmentIndex.set(dirent.name, []);
|
||||||
@@ -670,7 +671,20 @@ async function tick() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function start() {
|
async function start() {
|
||||||
await ensureDir(SEGMENT_ROOT);
|
try {
|
||||||
|
await ensureDir(SEGMENT_ROOT);
|
||||||
|
activeSegmentRoot = SEGMENT_ROOT;
|
||||||
|
} catch (err) {
|
||||||
|
const fallback = path.join(os.tmpdir(), 'mrr-replay-segments');
|
||||||
|
await ensureDir(fallback);
|
||||||
|
activeSegmentRoot = fallback;
|
||||||
|
logger.warn('Replay segment root unavailable; using fallback path', {
|
||||||
|
configuredRoot: SEGMENT_ROOT,
|
||||||
|
fallbackRoot: fallback,
|
||||||
|
error: err.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
logger.info('Replay engine using segment root', { segmentRoot: activeSegmentRoot });
|
||||||
await bootstrapIndexFromDisk();
|
await bootstrapIndexFromDisk();
|
||||||
await tick();
|
await tick();
|
||||||
if (cleanupTimer) clearInterval(cleanupTimer);
|
if (cleanupTimer) clearInterval(cleanupTimer);
|
||||||
@@ -697,7 +711,7 @@ module.exports = {
|
|||||||
buildReplayVideo,
|
buildReplayVideo,
|
||||||
getReplayHealthSnapshot,
|
getReplayHealthSnapshot,
|
||||||
replayEngineEvents: events,
|
replayEngineEvents: events,
|
||||||
replaySegmentRootDir: SEGMENT_ROOT,
|
replaySegmentRootDir: () => activeSegmentRoot,
|
||||||
replaySegmentSeconds: SEGMENT_SECONDS,
|
replaySegmentSeconds: SEGMENT_SECONDS,
|
||||||
replayBufferSeconds: BUFFER_SECONDS,
|
replayBufferSeconds: BUFFER_SECONDS,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user