# 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/TeamsISO.Engine/Pipeline/MediaFoundationRecorderSink.cs`. ## Status — May 2026 **Activation deferred.** The Vortice.MediaFoundation 3.6.2 NuGet package is referenced from `TeamsISO.Engine.csproj`, but the `MF_AVAILABLE` symbol is *not* defined. The scaffold in `src/TeamsISO.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 `TeamsISO.Engine.csproj`: ```xml $(DefineConstants);MF_AVAILABLE ``` 3. **Swap the recorder factory** in `IsoController.EnableIsoAsync`: ```csharp // Old: recorder = new RawBgraRecorderSink(_loggerFactory.CreateLogger()); // New: recorder = new MediaFoundationRecorderSink(_loggerFactory.CreateLogger()); ``` 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: - `//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). - `//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.