Skip to content

[Frameforge 5] Implement canvas capture, MediaStream tracks and real MediaRecorder export #58

Description

@danwalmsley

Outcome and dependencies

Depends on #54, #55, #57, #34 and #40. Export the original app's composited movie plus mixed audio, including cancellation. MediaRecorder and the media stream path need implementation/qualification; this is not offline deterministic mastering.

Specification and implementation

  • Implement canvas.captureStream(frameRate), CanvasCaptureMediaStreamTrack as applicable, MediaStream getTracks/getAudioTracks/addTrack and MediaStreamTrack clone/stop/enabled/readyState. Connect the Web Audio destination track from [Frameforge 2] Implement Web Audio mixing, media sources and waveform decoding #55; one clone stopping must not terminate its siblings.
  • Implement MediaRecorder constructor/options, isTypeSupported, mimeType/state, start(timeslice), stop, pause/resume/requestData and required dataavailable/stop/error events and BlobEvent bytes. Follow state/error and final-chunk ordering; capability probing reflects an available codec/container encoder and muxer, not a hardcoded list.
  • Qualify at least one actual Frameforge-probed format on macOS (e.g. H.264/AAC MP4 if supported by the chosen backend). Explicitly list supported codec/profile/container combinations and fail others. Reuse a cross-platform encoder interface with backend-specific acceleration; document licenses, pinned dependencies and runtime package contents.
  • Preserve frame generations across GPU -> Canvas2D drawImage -> capture -> encoder. Prefer shared GPU surfaces or GPU conversion into encoder-compatible surfaces; do not introduce per-frame CPU readback into preview. Count unavoidable copy/conversion costs separately. Explicit PNG readback is separate from the video capture path.
  • Use timestamped bounded video/audio queues, backpressure, a shared recording timebase and cancellation. Encoding/muxing must not block JS/UI or realtime audio. Correctly settle recorder events when tracks end, device/encoder errors occur, document hides/closes or source size changes.
  • Exercise Frameforge's timeslice=1000, final tail, hidden-tab cancellation, repeated exports, resolution/playhead restoration and cleanup. App chunks remain memory-resident by upstream design; measure and respect that limitation rather than claim unlimited export duration.

Tests and verification

Record known moving color bars plus click track. Independently demux/decode output and inspect dimensions, codecs, monotonic timestamps, duration, non-repeated content and A/V alignment. Test unsupported MIME, no tracks, state misuse, stop-before-first-frame, mid-export cancellation, device loss and closing window. Run two consecutive original app exports and verify playback plus restored preview state. Add MediaRecorder/capture WPT contracts and native queue/muxer tests.

Acceptance

  • Original export produces a playable composited movie with mixed audio in a honestly advertised format.
  • Cancel/stop/error deliver correct events and release tracks, encoders and frame leases.
  • Preview remains GPU resident; measured export cost and A/V/drop results are attached.
  • Native AOT bundle contains all non-system dependencies and passes recording regressions.

References

MediaStream Recording and capture from DOM elements.

Original application references

Shared delivery requirements

Parent: #53. Baseline: PR #43 / ce56d49; sample experiments/WebScene.Frameforge.
Reference application: https://github.com/wieslawsoltes/Frameforge (pin f414cd44896b659a5c6da2e4fc596a2ded055f2a, includes demo media and THIRD_PARTY_NOTICES.md).
Implement in WebScene, leaving original application JavaScript/WGSL unchanged. No fake capability objects, synthetic successful events or swallowed errors. Keep public contracts cross-platform with isolated backend implementations; qualify macOS arm64 first and explicitly track Windows/Linux follow-up. Production Avalonia 11 must remain supported; only samples opt into Avalonia 12. Native AOT/trim safety is mandatory.
Add focused native/managed regression coverage and a pinned WPT subset or clearly labeled project-owned contract for non-WebGPU behavior. Applicable WebGPU CTS cases belong with GPU work. Record exact revisions, test commands, negative cases and reproducible evidence in the implementation PR. Unsupported functionality cannot be marked passed; distinguish app coverage from standards conformance. Review existing implementation before adding overlapping infrastructure.

Native Save integration

The exported movie Blob must flow through #57 into the hosting Avalonia/Uno native Save workflow, with suggested filename and format, user-selected destination and platform overwrite/cancellation handling. There is no browser download manager or automatic Downloads destination. Verify the resulting on-disk/provider file independently; a completed encoder or created Blob alone is not a successful native save. Keep original application code unchanged and implement the compatibility bridge in WebScene.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions