dragon-iso/docs/REAL-TIME-RECORDING.md
Zac Gaetano edb7975039
Some checks failed
CI / build-and-test (push) Failing after 29s
rebrand: rename all TeamsISO source paths to Dragon-ISO
- Rename solution files: TeamsISO.sln/slnf -> Dragon-ISO.sln/slnf
- Rename all src/TeamsISO.* directories and project files
  to src/Dragon-ISO.* equivalents
- Update .gitignore to exclude build/test output logs
- Update ci.yml, CHANGELOG.md, build-and-test.ps1, docs references

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 11:18:27 -04:00

4.3 KiB

Real-time H.264 recording

The default recorder (RawBgraRecorderSink) writes uncompressed BGRA to disk and ships a convert.cmd for post-recording FFmpeg encoding. That's safe (no extra dependencies, works without an encoder installed) but disk-heavy: 1080p60 = ~500 MB/s, 720p30 = ~88 MB/s.

For long shows or operators on slower disks, the engine ships a MediaFoundationRecorderSink that encodes to H.264 in real time using Windows Media Foundation. Inline encoding cuts disk pressure ~10× and produces a finished .mp4 without the convert step.

It's behind a build flag because activating it requires adding a NuGet dependency. The structural code is already in src/Dragon-ISO.Engine/Pipeline/MediaFoundationRecorderSink.cs.

Status — May 2026

Activation deferred. The Vortice.MediaFoundation 3.6.2 NuGet package is referenced from Dragon-ISO.Engine.csproj, but the MF_AVAILABLE symbol is not defined. The scaffold in src/Dragon-ISO.Engine/Pipeline/MediaFoundationRecorderSink.cs was written against an older Vortice API and needs a port pass before activation:

  • MFVersion → not on MediaFactory in 3.6.2; pass the SDK version directly to MFStartup.
  • MediaFactory.MF_LOW_LATENCY → relocated to a different attribute constants class.
  • IMFAttributes.SetUINT32 → replaced with a generic Set overload.
  • IMFMediaType.MajorType / .SubType / .AvgBitrate properties → now use SetGUID(MFAttributeKeys.MajorType, ...) etc.
  • VideoFormatGuids.RGB32 → renamed (likely Rgb32).
  • IMFMediaBuffer.Lock(out IntPtr, out int, out int) → explicit out-param signature, no longer returns a locked-buffer wrapper.
  • IMFSinkWriter.Finalize_ → renamed (likely Finalize).

Until the port lands, the RawBgraRecorderSink is the only IRecorderSink production uses. The raw recorder is reliable and FFmpeg post-processing via the emitted convert.cmd produces equivalent .mp4s; you just pay the disk pressure during the show.

Activating it (after the port)

  1. Update the scaffold to match Vortice 3.6.2's API surface. A clean reference implementation lives in the Vortice samples repo under samples/MediaFoundationSamples.

  2. Define the MF_AVAILABLE build symbol in Dragon-ISO.Engine.csproj:

    <PropertyGroup>
      <DefineConstants>$(DefineConstants);MF_AVAILABLE</DefineConstants>
    </PropertyGroup>
    
  3. Swap the recorder factory in IsoController.EnableIsoAsync:

    // Old:
    recorder = new RawBgraRecorderSink(_loggerFactory.CreateLogger<RawBgraRecorderSink>());
    // New:
    recorder = new MediaFoundationRecorderSink(_loggerFactory.CreateLogger<MediaFoundationRecorderSink>());
    

    Both classes implement IRecorderSink so the rest of the pipeline is unchanged.

  4. Build and smoke-test. Existing unit tests don't touch the recorder; the integration tier covers it once you've enabled MF.

What the MF recorder produces

For each enabled ISO with recording on:

  • <recordings>/<participant>/output.mp4 — H.264 video at the engine's configured resolution / framerate, target bitrate ~0.07 bits/pixel (~7 Mbps for 1080p30, ~3 Mbps for 720p30).
  • <recordings>/<participant>/markers.txt — tab-separated marker offsets from IIsoController.AddRecordingMarker. Manually chapter the .mp4 with mp4chaps -c -i markers.txt output.mp4 (mp4chaps from the mp4v2 tools).

Trade-offs vs. RawBgraRecorderSink

Raw BGRA Media Foundation H.264
Dependencies None Vortice.MediaFoundation NuGet
Disk @ 1080p60 ~500 MB/s ~50 MB/s
Disk @ 720p30 ~88 MB/s ~9 MB/s
CPU Negligible Moderate (inline encode)
Output .bgra + convert.cmd for FFmpeg post-pass Finished .mp4
Markers in container No (sidecar JSON) Sidecar .txt, chapter via mp4chaps
Reliable on legacy GPUs Yes Yes (MF falls back to software encoder if no hw H.264)

If your target machines have NVIDIA NVENC / Intel QuickSync, MF will use the hardware encoder transparently — that's the path that gives you multi-stream realtime H.264 with low CPU.