Luxar Viewer API Documentation - v2026.9.22
    Preparing search index...

    Module ui/recording-panel/live-overlay-compositor

    Live overlay compositing for the REAL-TIME (MediaRecorder) capture path.

    The offline loop composites overlays by re-reading the framebuffer per frame (renderFrameToCanvas), which the real-time path cannot afford — it films at wall-clock speed. So instead of handing canvas.captureStream() the WebGL canvas (which carries no DOM overlays), the recorder captures a MIRROR 2D canvas that this class refreshes once per rendered frame: blit the GL canvas, then run the same compositeOverlays() the screenshot path uses.

    The renderer runs with preserveDrawingBuffer: false (see config/sections/webgl/data.ts), so the drawing buffer is cleared once the browser composites the frame. drawImage(glCanvas) therefore only sees pixels while still inside the SAME task that issued the draw calls. frame-end is emitted by AnimationController.animate() on the line after postProcessing.render(), which is exactly that window. A plain rAF callback runs in a later task and blits a fully black frame — measured, not assumed.

    One drawImage of the whole canvas plus the canvas-2D overlay draws. Measured at 0.1 ms median / 0.3 ms max on a 2942x1602 (4.7 Mpx) canvas, i.e. below the noise floor of a 60 FPS budget. It is only attached when the capture actually has overlays to draw.

    HTML overlays are rasterized through an async <svg><foreignObject> data URL, and compositeHtmlOverlay only draws one that already happens to be decoded — the same best-effort behaviour the screenshot and offline paths have. Text, image, and video overlays are exact.

    LiveOverlayCompositor
    createLiveOverlayCompositor