# Known issue: stream frames make browser memory grow **Status: not fixed yet** — noted on Olivia's request, 2026-09-29 (camera-sensing R13). No code was changed in this repo. ## The defect For **every frame**, the GUI builds a `new Image()` from a `data:image/...;base64,...` URL and reassigns the canvas `width`/`height`. Left open, the page's memory keeps growing: on 2026-09-28 hostpc (32 GB) ran out of RAM and the kernel killed a Firefox process holding ~19.8 GB of shared memory, with several camera GUIs open. ## Where, in this repo - `src/frontend/react/src/components/StreamView.jsx` — the `useEffect` on `frame` (RGB JPEG or depth PNG): `new Image()` per frame, canvas resized per frame, then detections / the measurement marker drawn on top. - `src/frontend/react/src/components/DepthView.jsx` — same pattern for the depth colormap (JPEG) or depth PNG. When applying the fix to `StreamView.jsx`, keep drawing the detections and the marker **after** `drawImage`, and pass the MIME type (`image/jpeg` for RGB, `image/png` for depth) to the `Blob`. **The running copy of this service is on PC2**, not on this PC: fixing this local copy does not fix the GUI in use until it is deployed there. ## The fix (same as multi-camera_service, commit `dfa0fec`) 1. Decode with `createImageBitmap`: base64 -> `Uint8Array` -> `Blob` -> `createImageBitmap(blob)`, then `drawImage(bitmap, 0, 0)`. 2. Call `bitmap.close()` **right after** drawing (also on error). 3. Resize the canvas **only when the frame size changes** (`if (canvas.width !== bmp.width || ...)`). 4. **Drop** a frame that arrives while the previous one is still decoding (a `decoding` flag, no queue). Reference implementation (a React hook, 40 lines): `/opt/docker/sensing/multi-camera_service/src/frontend/react/src/hooks/useJpegCanvas.js`. ## Measured (multi-camera_service, camera-sensing R11, 2026-09-28) Headless Chromium, roof stream 1920x1080 at ~15 fps: renderer memory **+838 MB between minute 1 and minute 5** with the old code; **+5 MB between minute 1 and minute 10** with the fix (+17 MB with a second, 640x480 stream). Probe: `/opt/docker/sensing/multi-camera_service/scripts/gui_memprobe.py` — it kills the browser above 2 GB of renderer memory or below 6 GB of system MemAvailable; keep that cap when measuring on hostpc.