MediaFileProcessor
C# library for processing various files (videos, photos, documents, images). It is a wrapper for FFmpeg, ImageMagick, Pandoc processes.
Install / Use
/learn @askatmaster/MediaFileProcessorREADME
- Overview
- FFmpeg instruction
- ImageMagick instruction
- Pandoc instruction
- Useful Features
- Special thanks to
Overview
C# (.NET Standard 2.1) OpenSource library for processing various files (videos, photos, documents, images).
dotnet add package MediaFileProcessor --version 1.0.3
This library is a universal wrapper for executable processes in the operating system (Windows/Linux). The library allows files to communicate with processes through named pipes, streams, byte arrays, and directory paths. It also has some useful features, such as the ability to decode a stream on the fly and get a set of files from it by their signatures.
In this version, wrappers are implemented in the libraries over such projects as FFmpeg, ImageMagick and Pandoc. This library can also be used to interact with third-party processes.
Below the presentation is an instruction for using this library and its description.
After reading the instructions, you can study the source code. it is extensively commented and has a simple architecture.
The first step is to define the data to be processed. The data to be processed is the MediaFile class.
You can create an instance of this class from a stream, a file path, an array of bytes, a named pipe, a naming pattern:
var fromPath = new MediaFile(@"C:\fileTest.avi");
var fromNamedPipe = new MediaFile("fileTestPipeName");
var fromPipe = new MediaFile("pipeName");
var fs = @"C:\fileTest.avi".ToFileStream();
var fromStream = new MediaFile(fs);
var bytes = @"C:\fileTest.avi".ToBytes();
var fromBytes = new MediaFile(bytes);
FFmpeg instruction
To process video files with FFmpeg, you must have its executable file ffmpeg.exe. If you don't want to download it yourself, you can use the following code:
await VideoFileProcessor.DownloadExecutableFilesAsync();
This code will download the archive from https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.zip and unzip the required ffmpeg.exe to the root directory.
File Processing Example
Below is an example of getting a frame from a video.
The VideoFileProcessor class is responsible for processing video files using ffmpeg.
You should create an instance of it:
var videoFileProcessor = new VideoFileProcessor();
Creation through the constructor without parameters implies that the executable files ffmpeg.exe and ffprobe.exe are located in the root folder.
If you have defined executable files in another directory, then you should create an instance of the processor by setting the paths to the executable files through the constructor:
var videoFileProcessor = new VideoFileProcessor("pathToFFmpeg.exe", "pathToFFprobe.exe");
To specify how a file should be processed, we need to instantiate VideoProcessingSettings.
Next, define the configuration for processing:
var settings = new VideoProcessingSettings();
var mediaFile = new MediaFile("pathToOutputFile");
settings.ReplaceIfExist() //Overwrite Output Files Without Prompting.
.Seek(TimeSpan.FromMilliseconds(47500)) //A frame to start your search with.
.SetInputFiles(mediaFile) //Install Input Files
.FramesNumber(1) //Number of Video Frames to Output
.Format(FileFormatType.JPG) //Force Input or Output File Format.
.SetOutputArguments(@"pathToInputFile"); //Configuring Output Arguments
Next, you just need to pass the configuration to the method ExecuteAsync:
var result = await videoFileProcessor.ExecuteAsync(settings, new CancellationToken());
The specified configuration methods will give us the following arguments to start the ffmpeg process:
-y -ss 00:00:47.500 -i pathToOutputFile -frames:v 1 -f image2 pathToInputFile.
It is necessary to OBSERVE the ORDER of the configurations, because some arguments must be given before the input argument and some after.
Get Video File Info
var videoProcessor = new VideoFileProcessor();
var stream = "pathToOutputFile".ToFileStream();
var data = await videoProcessor.GetVideoInfo(new MediaFile(stream));
var info = JsonConvert.DeserializeObject<VideoFileInfo>(data, _jsonSnakeCaseSerializerSettings)!;
Attention!
When setting the process configuration, you can set the input data using the SetInputFiles method, which accepts an array of parameters in the form of instances of the MediaFile class.
You just need to create instances of this class from data presented in any form (path, stream, bytes, pipes, patterns) and pass it to the SetInputFiles method.
The SetOutputArguments method is responsible for setting the output file argument. Through this method, you can set the path of the output file, the rtp address of the server for broadcasting, etc.
If this method is not called, it means that the result of processing will be issued to StandardOutput as a stream. And the ExecuteAsync method will return the result on the thread.
If you set your own output argument, then StandardOutput will be empty and ExecuteAsync will return null.
If you need to set an argument that is not present in the configuration methods, then you can set custom arguments using the CustomArguments method.
Full code:
var mediaFile = new MediaFile(@"pathToOutputFile");
var videoFileProcessor = new VideoFileProcessor();
var settings = new VideoProcessingSettings();
settings.ReplaceIfExist() //Overwrite output files without asking.
.Seek(TimeSpan.FromMilliseconds(47500)) //The frame to begin seeking from.
.SetInputFiles(mediaFile) //Set input files
.FramesNumber(1) //Number of video frames to output
.Format(FileFormatType.JPG) //Force input or output file format.
.SetOutputArguments(@"pathToInputFile"); //Setting Output Arguments
var result = await videoFileProcessor.ExecuteAsync(settings, new CancellationToken());
Important Note When Processing MP4 Files!
When processing MP4 video files into a video stream or byte set, use this method.
public async Task<MemoryStream?> SetStartMoovAsync(MediaFile file, string? outputFile = null, CancellationToken cancellationToken = default)
This method moves the MOOV atom of the MP4 format to the beginning because FFmpeg must know how to process this file when reading files from a stream. The MP4 file processing information is usually at the end and FFmpeg cannot process it as a stream. When moving a MOOV atom, ffmpeg cannot retrieve a file from a stream and output the result as a stream. To move an atom, it is necessary to have a file physically in the directory, the result of processing must also be written to the directory. If the MP4 file is in your stream form and needs to shift the MOOV atom, and get the result in wanting necessarily in the video stream. Then this method will create a physical file from your input stream and pass it to FFmpeg for processing and convert the result from the file to a stream and return this stream. All intermediate files created will then be deleted.
The current version of the library has already implemented some options for processing video files using ffmpeg:
- Extract frame from video
- Trim video
- Convert video to image set frame by frame
- Convert images to video
- Extract audio track from video file
- Convert to another format
- Add Watermark
- Remove sound from video
- Add audio file to video file
- Convert video to Gif animation
- Compress video
- Compress image
- Combine a set of video files into a single video file
- Add subtitles
- Get detailed information on video file metadata
These functions I tested with some of the most requested formats mp4 avi png jpg bmp wav and mpeg Other formats may require additional settings. In the future, I'm going to develop the library to possibly install settings under the hood for any format.
Example "Extract frame from video"
Below is an example of using frame extraction from a video file at a certain timing, provided that the file exists PHYSICALLY in the directory
var videoFileProcessor = new VideoFileProcessor();
//Test block with physical paths to input and output files
await videoFileProcessor.ExtractFrameFromVideoAsync(TimeSpan.FromMilliseconds(47500),
new MediaFile(@"C:\inputFile.avi"),
@"C:\resultPath.jpg",
Related Skills
docs-writer
99.6k`docs-writer` skill instructions As an expert technical writer and editor for the Gemini CLI project, you produce accurate, clear, and consistent documentation. When asked to write, edit, or revie
model-usage
341.8kUse CodexBar CLI local cost usage to summarize per-model usage for Codex or Claude, including the current (most recent) model or a full model breakdown. Trigger when asked for model-level usage/cost data from codexbar, or when you need a scriptable per-model summary from codexbar cost JSON.
ddd
Guía de Principios DDD para el Proyecto > 📚 Documento Complementario : Este documento define los principios y reglas de DDD. Para ver templates de código, ejemplos detallados y guías paso
arscontexta
2.9kClaude Code plugin that generates individualized knowledge systems from conversation. You describe how you think and work, have a conversation and get a complete second brain as markdown files you own.
