A Windows desktop app for extracting tracks, chapters, attachments, tags, cue sheets, and timestamps from MKV and MP4 files.
StreamExtract is a WinForms application built with .NET 10. It wraps
MKVToolNix (mkvmerge, mkvextract) and
GPAC (mp4box) to extract individual streams and
metadata from media containers. All extraction runs the bundled native tools
directly — no shell, no scripting.
- Extract audio, video, and subtitle tracks from MKV/MKA and MP4/M4V/M4A/M4B files
- Extract chapters, attachments, tags, cue sheets, timestamp files, and per-track cue sheets from MKV containers
- Drag-and-drop multiple files or pick them with the file dialog
- Per-file track and feature selection with a checkbox tree
- Sequential, progress-tracked extraction
- Output paths are validated and contained — untrusted attachment names cannot escape the output directory
- Startup validation that fails closed when a bundled tool is missing or does not match its expected SHA-256 hash
- Checks for updates on startup and shows a button linking to the download page when a newer version is available
- .NET 10 SDK to build from source
- Windows (the app is
net10.0-windowsand uses WinForms)
The three native tools are committed in tools/ and are required at runtime:
tools/mkvextract.exeandtools/mkvmerge.exe— from MKVToolNixtools/mp4box.exe— from GPAC
No installer is provided. To run from source:
git clone https://github.com/CodeByVibes/stream-extract.git
cd stream-extract
dotnet run --project stream-extract-winforms.csprojTo build a release:
dotnet build -c ReleaseThe build copies tools/ and licenses/ into the output directory. Launch the
app from there, or run the produced stream-extract-winforms.exe.
Note
If you delete or relocate a bundled tool — or replace it with one whose
SHA-256 hash does not match — the app refuses to start and reports the
problem. Keep the tools/ folder next to the executable and leave the
bundled executables untouched.
- Add files — drag media files onto the tree, or click Open files.
- Select output folder — choose a folder, or keep Use source checked to write next to the first imported file.
- Select what to extract — check the tracks and features you want under each file. Checking a file node checks all of its children.
- Extract — click Extract. Progress is shown on the progress bar and in the log pane.
Supported extraction options per file type:
| Option | MKV/MKA | MP4/M4V/M4A/M4B |
|---|---|---|
| Tracks (audio/video/subtitles) | yes | yes |
| Chapters | yes | yes |
| Attachments | yes | no |
| Tags | yes | no |
| Cue sheets | yes | no |
| Cues for selected tracks | yes | no |
| Timestamps | yes | no |
Output naming follows the source file name. For example, extracting a video
track from movie.mkv writes movie_Track1.h264 into the output folder;
chapters write movie_chapters.xml; timestamps write
movie_Track1_timestamps.txt; cue sheets for selected tracks write
movie_Track1_cues.cue; attachments keep their original names.
dotnet buildThe build is warning-free.
dotnet testTests are headless xUnit tests targeting the pure helpers — path containment,
request building, selection snapshotting, cue sheet generation, progress math,
plugin command builders, update parsing, and the process failure/cancellation
contracts. The bundled native tools are never invoked during tests; the process
contracts are exercised against cmd.exe.
The solution is split into three layers:
Form1— WinForms UI. Import and extraction run as async methods on the UI thread (WinFormsSynchronizationContext). Selection is snapshotted fromTreeNode.Tagvalues into immutableImportedFile/FileSelectionrecords.Plugins/—IExtractorPluginimplementations (MkvExtractorPlugin,Mp4ExtractorPlugin) that analyze files and build per-mode native-tool commands, registered by extension inPluginRegistry.Services/—IProcessRunner/ProcessRunner(process execution with kill-on-cancel and throw-on-non-zero-exit),ExternalToolException(tool failures with exit code and captured output),OutputPathGuard(path containment),ExtractionRequestBuilder(selection to request mapping), andUpdateChecker/BrowserLauncher.
Key design decisions:
- A non-zero exit code from a native tool is captured as a per-mode failure in the
returned
ExtractOutcome; the UI logs each failure and keeps going with the remaining modes instead of a false "Done". Cancellation still aborts everything. - Attachment output paths pass through
OutputPathGuard.ResolveContainedPath, so a malicious file name inside an MKV cannot escape the selected output directory. - One
mkvextractinvocation per extraction mode keeps failures attributable and matches the tool's command syntax. The exception is per-track cue sheets, which are generated from the extracted chapter XML instead of callingmkvextract's cuesheet mode (that mode has no per-track option). - At startup the app verifies the SHA-256 hash of every bundled tool and refuses to start if one is missing or modified.
This project uses Conventional Commits
for commit messages. Please keep the build warning-free and run dotnet test
before submitting a pull request.
This project is licensed under the MIT License. The bundled native
tools are the property of their respective authors and are distributed under
their original licenses — see licenses/GPAC-LICENSE.txt and
licenses/MKVToolNix-LICENCE.txt.