Repository navigation
First public release
MediaToolkit.NET 0.1.1
First usable release: low-level wrappers over the native media stacks for
.NET 10, plus one cross-platform API on top of them.
There is no 0.1.0. Two packages of that version reached nuget.org before
the rest of the set was rejected. nuget.org refuses an id that matches an
existing one once.and-are stripped, soMediaToolkitNet.Corecollided
withMediaToolkit.NetCoreand the facadeMediaToolkitNetcollided with
MediaToolkit.NET. They are nowMediaToolkitNet.Abstractionsand
MediaToolkitNet.All.MediaToolkitNet.Interop0.1.0 and
MediaToolkitNet.FFmpeg0.1.0 depend on an id that never shipped, so they are
unlisted and must not be used.
All interop goes through [LibraryImport] and unmanaged function pointers. COM
on Windows is called directly through vtable slots, without [ComImport] or the
built-in COM marshaller, which keeps the assemblies AOT- and trim-safe and keeps
the exact native signature visible at every call site.
Install
dotnet add package MediaToolkitNet.AllThat pulls in every backend and picks one at runtime. Take a single backend
instead when you do not want the rest:
dotnet add package MediaToolkitNet.Windows| Package | Contents |
|---|---|
MediaToolkitNet.All |
Facade: backend registry and per-platform selection |
MediaToolkitNet.Abstractions |
Abstractions only; no native code, no dependencies |
MediaToolkitNet.Interop |
Native loading, UTF-8 marshalling, COM vtable access |
MediaToolkitNet.FFmpeg |
FFmpeg 7.x: demux, decode, encode, mux |
MediaToolkitNet.Mpv |
libmpv client API |
MediaToolkitNet.Windows |
Media Foundation, WASAPI, DirectShow |
MediaToolkitNet.Linux |
V4L2, ALSA, PulseAudio |
MediaToolkitNet.MacOS |
AVFoundation, CoreAudio |
What is in it
| Capability | Windows | Linux | macOS | FFmpeg | mpv |
|---|---|---|---|---|---|
| Device enumeration | MF + WASAPI + DShow | ALSA + V4L2 | CoreAudio + AVF | avdevice | — |
| Video capture | IMFSourceReader |
V4L2 mmap | AVCaptureSession |
— | — |
| Audio capture | WASAPI (+ loopback) | ALSA / PulseAudio | AudioQueue | — | — |
| Audio render | WASAPI | ALSA / PulseAudio | AudioQueue | — | — |
| Playback | — | — | AVPlayer |
decode to frames | full |
| Recording to file | IMFSinkWriter |
— | — | encode + mux | — |
A dash means the backend does not take that role: FFmpeg owns no audio output,
mpv never hands frames back, and on Linux and macOS writing files is the FFmpeg
backend's job.
Requirements
- .NET 10
- A 64-bit process. Every mapped struct layout assumes a 64-bit pointer.
MediaToolkitNet.FFmpegneeds FFmpeg 7.x present at runtime
(avutil 59 / avcodec 61 / avformat 61). No native binary ships in any package.MediaToolkitNet.Mpvneeds libmpv present at runtime.- The platform backends only call libraries that are already part of the
operating system.
Verified by running
Exercised against real hardware on Windows 11:
- device enumeration through Media Foundation, WASAPI and DirectShow, including
default-endpoint flags; - video capture from a USB camera, 640x480 NV12 at 30 fps, sustained ~23 fps
delivered to the frame handler; - audio capture through WASAPI at 48 kHz stereo float;
- recording live audio to AAC/MP4 through
IMFSinkWriter, producing a
structurally complete MP4 —ftyp/mdat/moov, brandmp42— which
confirms the writer was finalised rather than merely fed.
The Windows COM vtable slot tables were corrected twice during development by
running them, not by reading them: a wrong slot number compiles, raises no
exception, and silently calls the neighbouring method.
Not exercised yet
Please read this before depending on it.
- The Linux and macOS backends have never been run. They compile and are
guarded at runtime, but the V4L2 struct sizes and the Objective-C runtime
layout have not been confirmed on real hardware. - The FFmpeg and mpv backends have never been run, because those native
libraries were not installed on the development machine. The FFmpeg ABI
self-check refuses to proceed on a layout it cannot confirm, so a mismatch
should produce a clear error rather than memory corruption, but that path is
untested too. - Media Foundation video recording is untested: the development machine has
no video encoder MFT registered at all.MediaFoundationRecorderdetects that
case and reports it plainly. Audio recording on that path does work.
This is why the release is 0.1.1. The public API may still change.
Known limitations
- Media Foundation video recording needs a video encoder MFT registered on the
machine. Editions such as Windows N without the Media Feature Pack have none;
theencoderssample command reports what a machine actually has. MacOSBackendcannot write files —AVAssetWriteris not wrapped. Use FFmpeg.FFmpegPlayeronly decodes: no renderer, no audio output.- Only the mpv client API is wrapped; the render API is not.
- DirectShow is wrapped for device enumeration only; no filter graph.
Design notes
Frames are borrowed. VideoFrame and AudioFrame are ref structs over
memory the backend owns, valid only inside the handler that received them. The
compiler refuses to let you store one. Zero copies and zero allocations per
frame; copy the data out if you need to keep it.
FFmpeg is pinned to 7.x, and checks itself. FFmpeg keeps no stable ABI for
its public structs across majors, so every direct field access lives in a single
file, the loader gates on the major versions, and the layout is validated at
startup against documented post-allocation defaults. The AVCodecParameters
offsets and the AVFrame audio fields are discovered by runtime probing rather
than hard-coded, and codecs are resolved by name instead of by the unstable
AVCodecID values.
Trying it
The sample CLI covers every capability and is how the library was validated:
dotnet run --project samples/MediaToolkitNet.Sample.Cli -- backends
dotnet run --project samples/MediaToolkitNet.Sample.Cli -- devices
dotnet run --project samples/MediaToolkitNet.Sample.Cli -- rec-video 2
dotnet run --project samples/MediaToolkitNet.Sample.Cli -- rec-audio-file 3 out.m4aReports from Linux and macOS are especially welcome.
Full documentation: README