fix: prevent RAM spike from large PCM files (e.g. 2h elevator)

- Check file size with statSync BEFORE reading into memory
- Files >50MB (~4.5min PCM) are never loaded into RAM, always streamed
- Also skip if total cache would exceed limit (no more read-then-discard)
- Fixes 1GB+ RAM spike when playing long audio files
This commit is contained in:
Claude Code 2026-03-05 21:29:43 +01:00
parent 390d6eb575
commit ac96896055

View file

@ -162,19 +162,20 @@ fs.mkdirSync(NORM_CACHE_DIR, { recursive: true });
// Danach kein Disk-I/O mehr bei Cache-Hits -> nahezu instant playback. // Danach kein Disk-I/O mehr bei Cache-Hits -> nahezu instant playback.
const pcmMemoryCache = new Map<string, Buffer>(); const pcmMemoryCache = new Map<string, Buffer>();
const PCM_MEMORY_CACHE_MAX_MB = Number(process.env.PCM_CACHE_MAX_MB ?? '512'); const PCM_MEMORY_CACHE_MAX_MB = Number(process.env.PCM_CACHE_MAX_MB ?? '512');
const PCM_PER_FILE_MAX_MB = 50; // Max 50 MB pro Datei (~4.5 min PCM) - groessere werden gestreamt
let pcmMemoryCacheBytes = 0; let pcmMemoryCacheBytes = 0;
function getPcmFromMemory(cachedPath: string): Buffer | null { function getPcmFromMemory(cachedPath: string): Buffer | null {
const buf = pcmMemoryCache.get(cachedPath); const buf = pcmMemoryCache.get(cachedPath);
if (buf) return buf; if (buf) return buf;
// Erste Anfrage: von Disk in RAM laden
try { try {
// Dateigroesse VORHER pruefen - keine grossen Files in den RAM laden
const stat = fs.statSync(cachedPath);
if (stat.size > PCM_PER_FILE_MAX_MB * 1024 * 1024) return null;
if (pcmMemoryCacheBytes + stat.size > PCM_MEMORY_CACHE_MAX_MB * 1024 * 1024) return null;
const data = fs.readFileSync(cachedPath); const data = fs.readFileSync(cachedPath);
const newTotal = pcmMemoryCacheBytes + data.byteLength;
if (newTotal <= PCM_MEMORY_CACHE_MAX_MB * 1024 * 1024) {
pcmMemoryCache.set(cachedPath, data); pcmMemoryCache.set(cachedPath, data);
pcmMemoryCacheBytes = newTotal; pcmMemoryCacheBytes += data.byteLength;
}
return data; return data;
} catch { return null; } } catch { return null; }
} }