video was too bigs

This commit is contained in:
legop3
2026-01-03 23:26:47 -05:00
parent 5b8fb30e71
commit 2f726035c9
+56 -1
View File
@@ -298,13 +298,60 @@ async function buildReplayVideo({ cameraId = null } = {}) {
}
const tmpDir = await fsp.mkdtemp(path.join(os.tmpdir(), 'rover-replay-'));
try {
const firstFrameByCamera = new Map();
for (let i = 0; i < frames.length; i += 1) {
const filename = `frame-${String(i + 1).padStart(4, '0')}.jpg`;
await fsp.writeFile(path.join(tmpDir, filename), frames[i].buffer);
const cameraId = frames[i].camera?.id;
if (cameraId && !firstFrameByCamera.has(cameraId)) {
firstFrameByCamera.set(cameraId, filename);
}
}
const outPath = path.join(tmpDir, 'replay.mp4');
const delayMs = getRoomCameraReplayDelayMs();
const fps = (1000 / delayMs).toFixed(3);
const fpsValue = 1000 / delayMs;
const fps = fpsValue.toFixed(3);
let maxWidth = 0;
let maxHeight = 0;
for (const filename of firstFrameByCamera.values()) {
try {
const { stdout } = await execFileAsync('ffprobe', [
'-v',
'error',
'-select_streams',
'v:0',
'-show_entries',
'stream=width,height',
'-of',
'csv=p=0',
path.join(tmpDir, filename),
]);
const [widthRaw, heightRaw] = stdout.trim().split(',');
const width = Number(widthRaw);
const height = Number(heightRaw);
if (Number.isFinite(width) && Number.isFinite(height)) {
maxWidth = Math.max(maxWidth, width);
maxHeight = Math.max(maxHeight, height);
}
} catch (err) {
logger.warn('Failed to probe replay frame size', err.message);
}
}
const MAX_REPLAY_WIDTH = 1280;
const MAX_REPLAY_HEIGHT = 720;
let targetWidth = maxWidth || MAX_REPLAY_WIDTH;
let targetHeight = maxHeight || MAX_REPLAY_HEIGHT;
if (targetWidth > MAX_REPLAY_WIDTH || targetHeight > MAX_REPLAY_HEIGHT) {
const scale = Math.min(MAX_REPLAY_WIDTH / targetWidth, MAX_REPLAY_HEIGHT / targetHeight);
targetWidth = Math.max(2, Math.floor((targetWidth * scale) / 2) * 2);
targetHeight = Math.max(2, Math.floor((targetHeight * scale) / 2) * 2);
}
const sizeFilter = `scale=${targetWidth}:${targetHeight}:force_original_aspect_ratio=decrease:flags=lanczos,pad=${targetWidth}:${targetHeight}:(ow-iw)/2:(oh-ih)/2:color=black,setsar=1`;
const maxBytes = Math.floor(9.5 * 1024 * 1024);
const durationSec = Math.max(1, frames.length / fpsValue);
const targetBitrateKbps = Math.max(300, Math.floor((maxBytes * 8) / durationSec / 1000));
const maxrateKbps = Math.floor(targetBitrateKbps * 1.1);
const bufsizeKbps = Math.floor(targetBitrateKbps * 2);
await execFileAsync('ffmpeg', [
'-y',
'-hide_banner',
@@ -314,8 +361,16 @@ async function buildReplayVideo({ cameraId = null } = {}) {
fps,
'-i',
'frame-%04d.jpg',
'-vf',
sizeFilter,
'-c:v',
'libx264',
'-b:v',
`${targetBitrateKbps}k`,
'-maxrate',
`${maxrateKbps}k`,
'-bufsize',
`${bufsizeKbps}k`,
'-pix_fmt',
'yuv420p',
outPath,