MediaToolkitNet.Windows
0.1.2
See the version list below for details.
dotnet add package MediaToolkitNet.Windows --version 0.1.2
NuGet\Install-Package MediaToolkitNet.Windows -Version 0.1.2
<PackageReference Include="MediaToolkitNet.Windows" Version="0.1.2" />
<PackageVersion Include="MediaToolkitNet.Windows" Version="0.1.2" />
<PackageReference Include="MediaToolkitNet.Windows" />
paket add MediaToolkitNet.Windows --version 0.1.2
#r "nuget: MediaToolkitNet.Windows, 0.1.2"
#:package MediaToolkitNet.Windows@0.1.2
#addin nuget:?package=MediaToolkitNet.Windows&version=0.1.2
#tool nuget:?package=MediaToolkitNet.Windows&version=0.1.2
MediaToolkit.NET
Low-level wrappers over the native media stacks for .NET 10, plus one cross-platform API on top of them: device enumeration, camera and microphone capture, audio playback, decoding and recording.
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, so the assemblies stay AOT- and trim-safe.
Install
dotnet add package MediaToolkitNet.All
MediaToolkitNet.All pulls in every backend and selects one at runtime. Take a
single backend instead when you do not want the rest:
| 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, 8.x or 9.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 |
Quick start
using MediaToolkitNet;
using MediaToolkitNet.Abstractions.Capture;
using MediaToolkitNet.Abstractions.Frames;
// Whichever backend this machine actually has.
using var capture = MediaToolkitNetBackends.CreateVideoCapture(VideoCaptureSettings.Default);
capture.FrameCaptured += (in VideoFrame frame) =>
{
// The frame is borrowed: it is valid only inside this handler.
// Copy the data out if you need to keep it.
ReadOnlySpan<byte> luma = frame.GetPlane(0);
};
capture.Start();
List what a machine can do:
foreach (var backend in MediaToolkitNetBackends.Registered)
{
Console.WriteLine($"{backend.Name}: {backend.IsAvailable}, {backend.Capabilities}");
}
foreach (var device in MediaToolkitNetBackends.EnumerateDevices())
{
Console.WriteLine($"{device.Kind} {device.Name}");
}
What each backend provides
| 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, and a 64-bit process: every mapped struct layout assumes a 64-bit pointer.
- No native binary ships in any package. The platform backends only call
libraries that are already part of the operating system, but:
MediaToolkitNet.FFmpegneeds FFmpeg 7.x, 8.x or 9.x at runtime (avutil 59 / avcodec 61 / avformat 61);MediaToolkitNet.Mpvneeds libmpv at runtime.
A backend whose libraries are missing reports IsAvailable == false instead of
throwing, so probing is always safe.
Status
This is an early release. On Windows, device enumeration, camera capture, WASAPI audio capture and audio recording to AAC/MP4 have been exercised against real hardware. The Linux, macOS, FFmpeg and mpv backends compile but have not been run yet, and the public API may still change. See the release notes for the full picture before depending on it.
Links
MIT licensed.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- MediaToolkitNet.Abstractions (>= 0.1.2)
- MediaToolkitNet.Interop (>= 0.1.2)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on MediaToolkitNet.Windows:
| Package | Downloads |
|---|---|
|
MediaToolkitNet.All
MediaToolkit.NET: one API over the native media stacks. This package pulls in every backend and selects the right one for the current operating system. Install a single backend package instead if you only need one. |
GitHub repositories
This package is not used by any popular GitHub repositories.
MediaToolkit.NET 0.1.2 - the FFmpeg backend release.
Audio encoding did not work at all in 0.1.1, on any FFmpeg version, and fixing
that uncovered a second defect underneath it in the struct offsets themselves.
Both are fixed here, FFmpeg 8.x and 9.x are supported alongside 7.x, and a test
suite now checks every offset against the library that is actually installed.
The README on this page covers what the library does and what it needs at
runtime. These notes cover only what is specific to this release.
FIXED
- Audio encoding never worked. The channel count was set through the "ac"
AVOption, which has not existed on AVCodecContext since FFmpeg 7 removed the
old channel API; the encoder then refused to open for want of a layout. The
same mistake sat in the startup probe of the AVFrame audio fields, which
switched audio encoding off wholesale. The layout now travels through
ch_layout.
- The AVStream offsets were wrong in every FFmpeg from 6 to 9. codecpar was read
at 208 where it lives at 16, and time_base, start_time, duration and
avg_frame_rate were each eight bytes short. The muxer writes codec parameters
through codecpar, so adding a stream to an output wrote through a wild pointer.
A new stream is now checked before anything is written through it.
- Channel layouts were guessed as (1 << channels) - 1, which gives 3.1 for four
channels rather than quad. The layout of a bare channel count now comes from
av_channel_layout_default.
- Encoder flags were assigned rather than accumulated, dropping the global header
bit whenever a second flag was set.
- .mka and .mks are the same muxer as .mkv and now ask for a global header too.
ADDED
- FFmpeg 8.x and 9.x beside 7.x. The loader matches the versions it got against a
table of release series and refuses a mixture belonging to none of them.
- AC-3 and DTS. The DCA encoder is experimental in FFmpeg and is opened as such
without the caller having to say so.
- PCM at 8, 16, 24 and 32 bits.
- Variable bitrate, through AudioEncodingSettings.Quality, on the scale -q:a uses.
- Per-stream EncoderName and Options, which name an encoder outright and pass
AVOptions to that stream alone.
- Stated channel layouts: the ChannelLayout constants and AudioFormat.ChannelMask.
Six channels are 5.1 twice over, the back arrangement and the side one, and
only a mask tells an encoder which.
- 134 unit tests and 43 integration tests, the latter checking every struct field
read by offset against the installed library.
CHANGED
- Six channels with no stated layout now default to 5.1 side, as
av_channel_layout_default does, rather than 5.1 back. Ask for
ChannelLayout.FivePoint1Back where the back arrangement is meant.
- AudioFormat takes a fourth, optional ChannelMask. Source-compatible.
- AbiLayout.CodecContextTimeBase and CodecContextPixFmt are properties rather
than constants, and PrepareAudioFrame takes the channel mask.
- FFmpegLibraries.AvUtilMajor, AvCodecMajor and AvFormatMajor are gone;
FFmpegLibraries.Generation and FFmpegGeneration.Known replace them.
VERIFIED BY RUNNING
On Windows 11 against FFmpeg 9.0.1: AC-3 at one, four and six channels, DTS, AAC
at a fixed rate and at a quality, and PCM at 8, 16, 24 and 32 bits, each encoded
into Matroska and read back as the codec, rate and channel count it was given;
MJPEG video encoded and muxed, which is the path that writes through
AVStream::codecpar; and every hard-coded offset checked against the running
library. The offset tests were themselves checked by breaking three offsets on
purpose, each of which failed loudly and corrupted nothing.
NOT EXERCISED YET
- FFmpeg 7.x and 8.x have not been run. Their entries in the series table were
read with offsetof against the headers of n7.1.5 and n8.1.2, and they name the
same fields 9.x uses, but no library of those series was loaded. Running
"dotnet test" on a machine that has one confirms them.
- The Linux, macOS and mpv backends have still never been run.
- Media Foundation video recording is still untested; audio recording works.
That is why this is still 0.1.x. The public API may still change.
KNOWN LIMITATIONS
- An encoder's own constraints are the caller's to meet: DCA takes only the side
arrangement of 5.1 and refuses stereo below 384 kbps, and AC-3 does not do 7.1.
The failure names the encoder, the sample rate and the layout asked for. The
FFmpeg command line hides this behind an automatic conversion filter; this API
does not.
- Matroska stores no channel mask, so PCM read back from it reports an
unspecified layout. The mask matters for encoding, not for what the container
records.
- MacOSBackend cannot write files, because AVAssetWriter is not wrapped.
- FFmpegPlayer only decodes: no renderer and no audio output.
- Only the mpv client API is wrapped; the render API is not.
- DirectShow is wrapped for device enumeration only, with no filter graph.
Full notes: https://github.com/yartat/MediaToolkit.NET/releases/tag/v0.1.2
Issues: https://github.com/yartat/MediaToolkit.NET/issues