FFMpegCore/README.md

218 lines
6.9 KiB
Markdown
Raw Normal View History

2019-05-09 22:12:16 +02:00
# FFMpegCore
[![NuGet Badge](https://buildstats.info/nuget/FFMpegCore)](https://www.nuget.org/packages/FFMpegCore/)
2020-05-24 19:38:48 +02:00
[![CI](https://github.com/rosenbjerg/FFMpegCore/workflows/CI/badge.svg)](https://github.com/rosenbjerg/FFMpegCore/actions?query=workflow%3ACI)
2019-02-08 11:19:40 +01:00
2019-05-10 18:34:30 +02:00
# Setup
2019-02-08 11:19:40 +01:00
#### NuGet:
```
Install-Package FFMpegCore
```
2020-05-24 19:28:00 +02:00
A great way to use FFMpeg encoding when writing video applications, client-side and server-side. It has wrapper methods that allow conversion to popular web formats, such as Mp4, WebM, Ogv, TS, and methods for capturing screenshots from videos, among other.
2019-02-08 11:19:40 +01:00
2020-05-24 19:28:00 +02:00
# API
2019-05-10 18:34:30 +02:00
2020-05-24 19:28:00 +02:00
## FFProbe
2019-05-10 18:34:30 +02:00
2020-05-24 19:28:00 +02:00
FFProbe is used to gather media information:
2020-05-24 19:28:00 +02:00
```csharp
var mediaInfo = FFProbe.Analyse(inputFile);
```
2020-05-24 19:28:00 +02:00
or
```csharp
var mediaInfo = await FFProbe.AnalyseAsync(inputFile);
```
2020-05-24 19:28:00 +02:00
## FFMpeg
FFMpeg is used for converting your media files to web ready formats.
Easily build your FFMpeg arguments using the fluent argument builder:
2019-02-08 11:19:40 +01:00
2020-05-24 19:28:00 +02:00
Convert input file to h264/aac scaled to 720p w/ faststart, for web playback
2019-02-08 11:19:40 +01:00
```csharp
2020-05-24 19:28:00 +02:00
FFMpegArguments
2020-10-24 23:03:25 +02:00
.FromFileInput(inputPath, true, options => options
.WithVideoCodec(VideoCodec.LibX264)
.WithConstantRateFactor(21)
.WithAudioCodec(AudioCodec.Aac)
.WithVariableBitrate(4)
.WithFastStart()
.Scale(VideoSize.Hd))
.OutputToFile(outputPath)
.ProcessSynchronously();
2019-02-08 11:19:40 +01:00
```
2020-05-24 19:28:00 +02:00
Easily capture screens from your videos:
2019-02-08 11:19:40 +01:00
```csharp
2020-10-24 23:03:25 +02:00
var mediaFileAnalysis = FFProbe.Analyse(inputPath);
2019-02-08 11:19:40 +01:00
2020-05-24 19:28:00 +02:00
// process the snapshot in-memory and use the Bitmap directly
var bitmap = FFMpeg.Snapshot(mediaFileAnalysis, new Size(200, 400), TimeSpan.FromMinutes(1));
2019-02-08 11:19:40 +01:00
2020-05-24 19:28:00 +02:00
// or persists the image on the drive
FFMpeg.Snapshot(mediaFileAnalysis, outputPath, new Size(200, 400), TimeSpan.FromMinutes(1))
2019-02-08 11:19:40 +01:00
```
2020-05-24 19:28:00 +02:00
Convert to and/or from streams
2019-02-08 11:19:40 +01:00
```csharp
2020-05-24 19:28:00 +02:00
await FFMpegArguments
2020-10-24 23:03:25 +02:00
.FromPipeInput(new StreamPipeSource(inputStream))
.OutputToPipe(new StreamPipeSink(outputStream), options => options
.WithVideoCodec("vp9")
.ForceFormat("webm"))
2020-05-24 19:28:00 +02:00
.ProcessAsynchronously();
2019-02-08 11:19:40 +01:00
```
2020-05-24 19:28:00 +02:00
Join video parts into one single file:
2019-02-08 11:19:40 +01:00
```csharp
2020-05-24 19:28:00 +02:00
FFMpeg.Join(@"..\joined_video.mp4",
@"..\part1.mp4",
@"..\part2.mp4",
@"..\part3.mp4"
);
2019-02-08 11:19:40 +01:00
```
2020-05-24 19:28:00 +02:00
Join images into a video:
2019-02-08 11:19:40 +01:00
```csharp
2020-05-24 19:28:00 +02:00
FFMpeg.JoinImageSequence(@"..\joined_video.mp4", frameRate: 1,
ImageInfo.FromPath(@"..\1.png"),
ImageInfo.FromPath(@"..\2.png"),
ImageInfo.FromPath(@"..\3.png")
);
2019-02-08 11:19:40 +01:00
```
2020-05-24 19:28:00 +02:00
Mute videos:
2019-02-08 11:19:40 +01:00
```csharp
2020-05-24 19:28:00 +02:00
FFMpeg.Mute(inputFilePath, outputFilePath);
2019-02-08 11:19:40 +01:00
```
Save audio track from video:
```csharp
2020-05-24 19:28:00 +02:00
FFMpeg.ExtractAudio(inputVideoFilePath, outputAudioFilePath);
2019-02-08 11:19:40 +01:00
```
2020-05-24 19:28:00 +02:00
Add or replace audio track on video:
2019-02-08 11:19:40 +01:00
```csharp
2020-05-24 19:28:00 +02:00
FFMpeg.ReplaceAudio(inputVideoFilePath, inputAudioFilePath, outputVideoFilePath);
2019-02-08 11:19:40 +01:00
```
Add poster image to audio file (good for youtube videos):
```csharp
2020-05-24 19:28:00 +02:00
FFMpeg.PosterWithAudio(inputImageFilePath, inputAudioFilePath, outputVideoFilePath);
// or
var image = Image.FromFile(inputImageFile);
image.AddAudio(inputAudioFilePath, outputVideoFilePath);
2019-02-08 11:19:40 +01:00
```
2020-05-24 19:28:00 +02:00
Other available arguments could be found in `FFMpegCore.Arguments` namespace.
2019-02-08 11:19:40 +01:00
2020-05-24 19:28:00 +02:00
### Input piping
With input piping it is possible to write video frames directly from program memory without saving them to jpeg or png and then passing path to input of ffmpeg. This feature also allows us to convert video on-the-fly while frames are being generated or received.
2019-02-08 11:19:40 +01:00
2020-05-24 19:28:00 +02:00
The `IPipeSource` interface is used as the source of data. It could be represented as encoded video stream or raw frames stream. Currently, the `IPipeSource` interface has single implementation, `RawVideoPipeSource` that is used for raw stream encoding.
2019-02-08 11:19:40 +01:00
2020-05-24 19:28:00 +02:00
For example:
2019-02-08 11:19:40 +01:00
2020-05-24 19:28:00 +02:00
Method that is generating bitmap frames:
2019-02-08 11:19:40 +01:00
```csharp
2020-05-24 19:28:00 +02:00
IEnumerable<IVideoFrame> CreateFrames(int count)
2019-02-08 11:19:40 +01:00
{
2020-05-24 19:28:00 +02:00
for(int i = 0; i < count; i++)
{
yield return GetNextFrame(); //method of generating new frames
}
2019-02-08 11:19:40 +01:00
}
```
2020-05-24 19:28:00 +02:00
Then create `ArgumentsContainer` with `InputPipeArgument`
2019-02-08 11:19:40 +01:00
```csharp
2020-05-24 19:28:00 +02:00
var videoFramesSource = new RawVideoPipeSource(CreateFrames(64)) //pass IEnumerable<IVideoFrame> or IEnumerator<IVideoFrame> to constructor of RawVideoPipeSource
2019-02-08 11:19:40 +01:00
{
2020-05-24 19:28:00 +02:00
FrameRate = 30 //set source frame rate
};
FFMpegArguments
2020-10-24 23:03:25 +02:00
.FromPipeInput(videoFramesSource, <input_stream_options>)
.OutputToFile("temporary.mp4", false, <output_options>)
2020-05-24 19:28:00 +02:00
.ProcessSynchronously();
2019-02-08 11:19:40 +01:00
```
2020-05-24 19:28:00 +02:00
if you want to use `System.Drawing.Bitmap` as `IVideoFrame`, there is a `BitmapVideoFrameWrapper` wrapper class.
2019-02-08 11:19:40 +01:00
2020-05-24 19:28:00 +02:00
## Binaries
2019-02-08 11:19:40 +01:00
2020-05-24 19:28:00 +02:00
If you prefer to manually download them, visit [ffbinaries](https://ffbinaries.com/downloads) or [zeranoe Windows builds](https://ffmpeg.zeranoe.com/builds/).
2019-02-08 11:19:40 +01:00
2020-05-24 19:28:00 +02:00
#### Windows
2019-02-08 11:19:40 +01:00
2020-05-24 19:28:00 +02:00
command: `choco install ffmpeg -Y`
2020-04-30 14:23:55 +02:00
2020-05-24 19:28:00 +02:00
location: `C:\ProgramData\chocolatey\lib\ffmpeg\tools\ffmpeg\bin`
2019-02-08 11:19:40 +01:00
2020-05-24 19:28:00 +02:00
#### Mac OSX
2019-02-08 11:19:40 +01:00
2020-05-24 19:28:00 +02:00
command: `brew install ffmpeg mono-libgdiplus`
location: `/usr/local/bin`
#### Ubuntu
command: `sudo apt-get install -y ffmpeg libgdiplus`
location: `/usr/bin`
## Path Configuration
#### Behavior
If you wish to support multiple client processor architectures, you can do so by creating a folder `x64` and `x86` in the `root` directory.
Both folders should contain the binaries (`ffmpeg.exe` and `ffprobe.exe`) for build for the respective architectures.
By doing so, the library will attempt to use either `/root/{ARCH}/(ffmpeg|ffprobe).exe`.
If these folders are not defined, it will try to find the binaries in `/root/(ffmpeg|ffprobe.exe)`
#### Option 1
The default value (`\\FFMPEG\\bin`) can be overwritten via the `FFMpegOptions` class:
```c#
public Startup()
2019-02-08 11:19:40 +01:00
{
2020-05-24 19:28:00 +02:00
FFMpegOptions.Configure(new FFMpegOptions { RootDirectory = "./bin", TempDirectory = "/tmp" });
2019-02-08 11:19:40 +01:00
}
```
2020-04-27 19:16:08 +02:00
2020-05-24 19:28:00 +02:00
#### Option 2
2020-04-27 19:16:08 +02:00
2020-05-24 19:28:00 +02:00
The root and temp directory for the ffmpeg binaries can be configured via the `ffmpeg.config.json` file.
2020-04-27 19:16:08 +02:00
2020-05-24 19:28:00 +02:00
```json
2020-04-27 19:16:08 +02:00
{
2020-05-24 19:28:00 +02:00
"RootDirectory": "./bin",
"TempDirectory": "/tmp"
2020-04-27 19:16:08 +02:00
}
```
2020-05-24 19:28:00 +02:00
# Compatibility
Some versions of FFMPEG might not have the same argument schema. The lib has been tested with version `3.3` to `4.2`
2020-04-27 19:16:08 +02:00
2019-02-08 11:19:40 +01:00
## Contributors
2019-03-28 00:27:59 +01:00
<a href="https://github.com/vladjerca"><img src="https://avatars.githubusercontent.com/u/6339681?v=4" title="vladjerca" width="80" height="80"></a>
<a href="https://github.com/max619"><img src="https://avatars.githubusercontent.com/u/26447324?v=4" title="max619" width="80" height="80"></a>
2019-05-03 15:58:54 +02:00
<a href="https://github.com/kyriakosio"><img src="https://avatars3.githubusercontent.com/u/6959989?v=4" title="kyriakosio" width="80" height="80"></a>
<a href="https://github.com/winchesterag"><img src="https://avatars3.githubusercontent.com/u/47878681?v=4" title="winchesterag" width="80" height="80"></a>
2019-09-30 13:07:10 +02:00
<a href="https://github.com/devlev"><img src="https://avatars3.githubusercontent.com/u/2109995?v=4" title="devlev" width="80" height="80"></a>
2020-01-29 12:03:20 +01:00
<a href="https://github.com/tugrulelmas"><img src="https://avatars3.githubusercontent.com/u/3829187?v=4" title="tugrulelmas" width="80" height="80"></a>
<a href="https://github.com/rosenbjerg"><img src="https://avatars3.githubusercontent.com/u/11181960?v=4" title="rosenbjerg" width="80" height="80"></a>
2019-02-08 11:19:40 +01:00
### License
2020-05-24 19:28:00 +02:00
Copyright © 2020
Released under [MIT license](https://github.com/rosenbjerg/FFMpegCore/blob/master/LICENSE)