|
All checks were successful
CI / build-and-test (push) Successful in 27s
RebuildFinder disposed the live finder *before* creating the replacement. If CreateFinder threw (the documented failure mode the catch handles), the service was left holding a disposed _finder, and every subsequent PollOnce called GetCurrentSources on a dead handle — so the self-heal path could permanently brick discovery, the exact outcome it exists to prevent. The log even claimed "continuing with existing finder" while the finder was gone. Now we build the replacement into a local first and only dispose the old finder once the new one is in hand. On failure the original finder stays live and the seen-set is left intact (no spurious re-Add storm). Made the method internal + bool-returning so the failure path is unit-testable. |
||
|---|---|---|
| .forgejo/workflows | ||
| docs | ||
| installer | ||
| src | ||
| .editorconfig | ||
| .gitignore | ||
| build-and-test.ps1 | ||
| CHANGELOG.md | ||
| coverlet.runsettings | ||
| Directory.Build.props | ||
| Dragon-ISO.Linux.slnf | ||
| Dragon-ISO.sln | ||
| Dragon-ISO.Windows.slnf | ||
| README.md | ||
TeamsISO
Per-participant NDI ISO controller for Microsoft Teams.
TeamsISO sits between Microsoft Teams' raw NDI broadcast output and a live-production environment. It receives each participant's NDI stream, normalizes framerate / resolution / aspect / audio per a configured target, and re-emits clean, individually-addressable NDI sources for ingestion by a switcher — vMix, OBS, Ross, hardware capture.
Status: v1.0.0 — first general release. Windows only. Requires Microsoft Teams (with NDI broadcast enabled) and the NDI 6 runtime.
What it does
- Discovers participants as Teams broadcasts each one over NDI. Cleans the Teams-prefixed source name down to a readable display name.
- Normalizes feeds to a consistent framerate, resolution, aspect mode, and audio routing — so the downstream switcher gets predictable inputs regardless of what each participant's webcam is doing.
- Routes per-participant as separate NDI sources with a configurable per-row output name. Default is the speaker's display name; override inline in the participants table.
- Records each ISO to disk simultaneously — raw BGRA +
manifest.json- FFmpeg
convert.cmd— so post-production gets a clean per-guest archive.
- FFmpeg
- Embeds Teams orchestration: launch / stop Teams, hide its UI windows during a show, drive in-call controls (mute, camera, share, leave, raise hand) without leaving the operator console.
- Operator presets save the current per-participant ISO assignment and custom output names, applicable on next launch automatically.
- Live preview thumbnails in the participants table, plus pop-out floating preview windows for multi-monitor monitoring.
- External control surface — REST + WebSocket on
127.0.0.1:9755and OSC on UDP127.0.0.1:9000for Bitfocus Companion / Stream Deck / TouchOSC. Self-contained HTML panel at/uifor phone-as-controller. - Theme-aware — dark and light palettes, system-following or pinned. The Wild Dragon mark and watermark flip to match.
Install
Grab the latest MSI from the
Releases page,
double-click, and accept the install prompts. Per-machine install under
C:\Program Files\Wild Dragon\TeamsISO.
Prerequisites:
- Windows 10 / 11, 64-bit
- .NET 8 Desktop Runtime
- NDI 6 Runtime (the installer warns if missing but does not block — operators can stage the app before NDI is rolled out)
- Microsoft Teams (NDI broadcast enabled in admin policy)
Configure
First-run defaults work for most setups. If your downstream switcher needs a particular framerate / resolution / NDI group routing, open the gear icon in the header to access the settings drawer:
- Output — framerate, resolution, aspect mode, audio routing
- Network — NDI discovery and output group names
- App — recording paths, startup behavior, theme
Per-participant overrides — click the CFG column gear on any row to override framerate / resolution / aspect / audio for just that participant.
Keyboard shortcuts
| Key | Action |
|---|---|
F1 |
Open help / cheat sheet |
Ctrl + K (or Ctrl + P) |
Open the command palette |
Ctrl + T |
Toggle theme (dark ↔ light) |
Ctrl + M |
Drop a timestamped marker into every active recording |
Ctrl + Shift + S |
Stop every running ISO (emergency) |
Ctrl + R |
Refresh NDI discovery (rebuild finder) |
1–9 / NumPad 1–9 |
Toggle the Nth visible participant's ISO |
File locations
| Path | Contents |
|---|---|
%APPDATA%\TeamsISO\config.json |
Engine settings (framerate, NDI groups, etc.) |
%LOCALAPPDATA%\TeamsISO\presets.json |
Saved operator presets + auto-apply preference |
%LOCALAPPDATA%\TeamsISO\logs\ |
Rolling daily diagnostic logs |
%LOCALAPPDATA%\TeamsISO\Notes\ |
Per-day show-notes markdown files |
%USERPROFILE%\Videos\TeamsISO\<date>\ |
Default recording output |
%APPDATA%\NDI\ndi-config.v1.json |
NDI Access Manager group routing |
Documentation
- Control surface API — REST, WebSocket, and OSC reference with curl recipes and a Companion config example.
- Real-time recording — recorder format, manifest schema, and the FFmpeg conversion path.
- Releasing — tag-push workflow and MSI signing.
Build from source
Requires the .NET 8 SDK on Windows. WPF is the only host.
dotnet restore TeamsISO.Windows.slnf
dotnet build TeamsISO.Windows.slnf -c Release
dotnet test TeamsISO.Windows.slnf --filter "Category!=ndi&requires!=ndi"
Or use the included helper:
pwsh -File .\build-and-test.ps1
To produce a fresh MSI:
dotnet publish src\TeamsISO.App\TeamsISO.App.csproj `
-c Release -r win-x64 --self-contained false `
-o publish\TeamsISO
dotnet build installer\TeamsISO.Installer.wixproj -c Release
# Output: installer\bin\x64\Release\TeamsISO-Setup-<version>.msi
License
Proprietary, © Wild Dragon LLC 2026. All rights reserved.