Bernat Guitart - Feb 7th, 2022
FFMPEG is the de-facto standard software for video and audio manipulation. It's used under the hood by hundreds of other software tools and applications, from desktop or mobile apps to websites and SaaS products.
One of the reasons for this is that FFMPEG is quite easy to call from other applications as a background process, from most of the popular programming languages.
During the last few years, dozens of developers and communities have created libraries (also called wrappers or SDKs). These wrappers usually create language native interfaces (object-oriented in most cases) trying to simplify the calls to FFMPEG and avoid the learning curve of the FFMPEG command-line parameters.
In my personal opinion, these wrappers save you from the pain of the FFMPEG parameters but give you the pain of learning their syntax. If I have to choose between these two pains, I prefer learning FFMPEG: at least, is something I can reuse in other contexts and programming languages.
For those who are more comfortable with these wrappers, here is my curated list, broken down by language:
- Python wrappers
- PHP wrappers
- Node JS wrappers
- Java FFMPEG wrappers
- Mobile FFMPEG wrappers
- Android FFMPEG wrappers
- iOS FFMPEG wrappers
- .NET FFMPEG wrappers
- Other languages
Best Python FFMPEG wrappers
Python is one of the preferred languages to automate FFMPEG, and part of the benefit comes from ffmpeg-python
wrapper.
There are other wrappers and libraries, but if you don't know where to start from, I recommend giving ffmpeg-python
a try.
ffmpeg-python
As said, ffmpeg-python is probably the most popular and used Python wrappers out there. This one claims to be the best in terms of complex filter support, working really well for simple and complex operations.
This is an example code of ffmpeg-python flipping horizontally a video:
import ffmpeg
stream = ffmpeg.input('input.mp4')
stream = ffmpeg.hflip(stream)
stream = ffmpeg.output(stream, 'output.mp4')
ffmpeg.run(stream)
You can install ffmpeg-python
using pip
package manager.
pip install ffmpeg-python
Github: ffmpeg-python
ffmpy
ffmpy is another Python wrapper far less used and known than ffmpeg-python
.
It has a completely different approach, relying on you to know the FFMPEG syntax, and just working as an FFMPEG command generator.
Here there is an example:
>>> ff = FFmpeg(
... inputs={'input.ts': None},
... outputs={'output.ts': ['-vf', 'adif=0:-1:0, scale=iw/2:-1']}
... )
>>> ff.cmd
'ffmpeg -i input.ts -vf "adif=0:-1:0, scale=iw/2:-1" output.ts'
>>>
>>> ff = FFmpeg(
... inputs={'input.ts': None},
... outputs={'output.ts': '-vf "adif=0:-1:0, scale=iw/2:-1"'}
... )
>>> ff.cmd
'ffmpeg -i input.ts -vf "adif=0:-1:0, scale=iw/2:-1" output.ts'
You can install ffmpy
using pip
package manager.
pip install ffmpy
Github: ffmpy Further documentation: FFMPY
python-ffmpeg-video-streaming
This wrapper again offers a different approach than the other two regarding FFMPEG. python-ffmpeg-video-streaming uses the FFmpeg to package media content for online streaming such as DASH and HLS. You can also use DRM for HLS packaging. There are several options to open a file from a cloud and save files to clouds as well.
With python-ffmpeg-video-streaming
you can also capture video from your
webcam, from a live stream or an S3 bucket.
Here is a code example:
from ffmpeg_streaming import Formats, Bitrate, Representation, Size
_360p = Representation(Size(640, 360), Bitrate(276 * 1024, 128 * 1024))
_480p = Representation(Size(854, 480), Bitrate(750 * 1024, 192 * 1024))
_720p = Representation(Size(1280, 720), Bitrate(2048 * 1024, 320 * 1024))
hls = video.hls(Formats.h264())
hls.representations(_360p, _480p, _720p)
hls.output('/var/media/hls.m3u8')
You can install python-ffmpeg-video-streaming
using pip
package manager.
pip install python-ffmpeg-video-streaming
Github: python-ffmpeg-video-streaming
Best PHP FFMPEG wrappers
The PHP language also has several FFMPEG wrappers, and among them is PHP-FFmpeg, a library with more than 4,000 stars on Github.
If you are interested in developing FFMPEG PHP applications, it's worth reading this page first from FFMPEG.org. It discusses the best options for running FFMPEG in the background with PHP, and the proper way of redirecting the stdout and stderr streams.
PHP-FFmpeg
As most if not all of the wrappers, PHP-FFmpeg requires you to install FFMPEG in your machine to do the magic. In the end, this and the other wrappers use FFMPEG in the background. If you have FFMPEG and FFPROBE in your system PATH variable, everything will work smoothly.
PHP-FFmpeg was frozen for a few years, with almost no contributions from 2007 to 2016, but recently it caught up and now is publishing new releases every few weeks/months.
This new version is forward-looking and requires PHP version 8 and supports FFMPEG 4.x and 5.
A basic usage example, so you can get a flavour of it:
require 'vendor/autoload.php';
$ffmpeg = FFMpeg\FFMpeg::create();
$video = $ffmpeg->open('video.mpg');
$video
->filters()
->resize(new FFMpeg\Coordinate\Dimension(320, 240))
->synchronize();
$video
->frame(FFMpeg\Coordinate\TimeCode::fromSeconds(10))
->save('frame.jpg');
$video
->save(new FFMpeg\Format\Video&4(), 'export-x264.mp4')
->save(new FFMpeg\Format\Video\WMV(), 'export-wmv.wmv')
->save(new FFMpeg\Format\Video\WebM(), 'export-webm.webm');
You can install PHP-FFmpeg
using composer
package manager.
composer require php-ffmpeg/php-ffmpeg
Github: PHP-FFmpeg
FFmpegPHP
There is little originality in naming these wrappers, and this one is not an exception.
FFmpegPHP can be used as a drop-in replacement for the ffmpeg-php library, with the advantage that this wrapper is still using PHP 7.x.
If hadn't switched yet to PHP8, FFmpegPHP can be a good option for you.
FFmpegPHP claims to be a pure object-oriented PHP port of the ffmpeg-php
library.
It has methods for returning frames from movie files as images that can be manipulated using
PHP image functions. This works well for automatically creating thumbnail images from movies.
FFmpegPHP makes it easy to retrieve information from video and audio files like
duration, bitrate, video formats, etc.
FFmpegPHP is compatible with composer
package manager.
Github: PHP-FFmpeg
FFmpegPHP API documentation can be found here http://char0n.github.io/ffmpeg-php/.
Laravel FFMpeg
Laravel is an extended PHP framework for building complex applications. If you are using Laravel, you can find this wrapper useful, as it provides integration with FFmpeg for Laravel 9.
A few of its features include:
- Super easy wrapper around PHP-FFMpeg, including support for filters and other advanced features
- Integration with Laravel's Filesystem, configuration system and logging handling
- Built-in support for HLS
- Built-in support for encrypted HLS (AES-128) and rotating keys (optional)
Laravel FFMpeg requires PHP8 and FFMPEG 4.4 or FFMPEG 5.
Installation is pretty straight-forward:
composer require pbmedia/laravel-ffmpeg
A code example:
FFMpeg::fromDisk('songs')
->open('yesterday.mp3')
->export()
->toDisk('converted_songs')
->inFormat(new \FFMpeg\Format\Audio\Aac)
->save('yesterday.aac');
The syntax is pretty cool, and very simple to read and mantain, and what I really love is how you can create several exports to different destinations in a very easy way:
FFMpeg::open('my_movie.mov')
// export to FTP, converted in WMV
->export()
->toDisk('ftp')
->inFormat(new \FFMpeg\Format\Video\WMV)
->save('my_movie.wmv')
// export to Amazon S3, converted in X264
->export()
->toDisk('s3')
->inFormat(new \FFMpeg\Format\Video&4)
->save('my_movie.mkv');
// you could even discard the 'toDisk()' method,
// now the converted file will be saved to
// the same disk as the source!
->export()
->inFormat(new FFMpeg\Format\Video\WebM)
->save('my_movie.webm')
// optionally you could set the visibility
// of the exported file
->export()
->inFormat(new FFMpeg\Format\Video\WebM)
->withVisibility('public')
->save('my_movie.webm');
Github: https://github.com/protonemedia/laravel-ffmpeg
Best Node JS FFMPEG wrappers
Lately, Node JS is becoming one of the preferred languages for developing FFMPEG applications. If you are thinking of developing an FFMPEG application in Node JS, this Digital Ocean tutorial is a gem.
node-ffmpeg
So as not to break tradition, this wrapper is called node-ffmpeg.
node-ffmpeg
provides a set of functions and utilities to abstract commands-line usage of FFMPEG.
You can install it with npm
:
npm install ffmpeg
node-ffmpeg
comes with a long list of preset functions to perform the most common task:
- Extract sound to MP3
- Extract frame to JPEG
- Add a watermark
- etc.
An example of code:
try {
var process = new ffmpeg('/path/to/your_movie.avi');
process.then(function (video) {
video
.setVideoSize('640x?', true, true, '#fff')
.setAudioCodec('libfaac')
.setAudioChannels(2)
.save('/path/to/save/your_movie.avi', function (error, file) {
if (!error)
console.log('Video file: ' + file);
});
}, function (err) {
console.log('Error: ' + err);
});
} catch (e) {
console.log(e.code);
console.log(e.msg);
}
Github: https://github.com/damianociarla/node-ffmpeg
NPM: https://www.npmjs.com/package/ffmpeg
node-fluent-ffmpeg
node-fluent-ffmpeg used to be a very nice FFMPEG wrapper in the past. Unfortunately, it's currently outdated and had no updates in 2 years. If you want to collaborate on a good project, they are looking for a new maintener.
This library wants to abstract the complex command-line usage of ffmpeg into a fluent, easy to use node.js module. In order to be able to use this module, make sure you have ffmpeg installed on your system (including all necessary encoding libraries like libmp3lame or libx264).
Sample code:
// Note that all fluent-ffmpeg methods are chainable
ffmpeg('/path/to/input1.avi')
.input('/path/to/input2.avi')
.input(fs.createReadStream('/path/to/input3.avi'));
// Passing an input to the constructor is the same as calling .input()
ffmpeg()
.input('/path/to/input1.avi')
.input('/path/to/input2.avi');
// Most methods have several aliases, here you may use addInput or mergeAdd instead
ffmpeg()
.addInput('/path/to/frame%02d.png')
.addInput('/path/to/soundtrack.mp3');
ffmpeg()
.mergeAdd('/path/to/input1.avi')
.mergeAdd('/path/to/input2.avi');
Installation is easy with npm
:
$ npm install fluent-ffmpeg
Github: https://github.com/fluent-ffmpeg/node-fluent-ffmpeg
Best Java FFMPEG wrappers
Java is no slouch when it comes to FFMPEG wrappers.
The most popular Java SDK is currently ffmpeg-cli-wrapper but again it's unfortunately discontinued, with no updates in the past 2 years.
Luckily, two other Java libraries have come to the rescue: Jave2 and Jaffree.
ffmpeg-cli-wrapper
As said, ffmpeg-cli-wrapper seems to be discontinued, even it had a good popularity and many contributors in the past.
Example of code using ffmpeg-cli-wrapper:
FFmpeg ffmpeg = new FFmpeg("/path/to/ffmpeg");
FFprobe ffprobe = new FFprobe("/path/to/ffprobe");
FFmpegBuilder builder = new FFmpegBuilder()
.setInput("input.mp4") // Filename, or an FFMPEGProbeResult
.overrideOutputFiles(true) // Override the output if it exists
.addOutput("output.mp4") // Filename for the destination
.setFormat("mp4") // Format is inferred from filename, or can be set
.setTargetSize(250_000) // Aim for a 250KB file
.disableSubtitle() // No subtiles
.setAudioChannels(1) // Mono audio
.setAudioCodec("aac") // using the aac codec
.setAudioSampleRate(48_000) // at 48KHz
.setAudioBitRate(32768) // at 32 kbit/s
.setVideoCodec("libx264") // Video using x264
.setVideoFrameRate(24, 1) // at 24 frames per second
.setVideoResolution(640, 480) // at 640x480 resolution
.setStrict(FFmpegBuilder.Strict.EXPERIMENTAL) // Allow FFmpeg to use experimental specs
.done();
FFmpegExecutor executor = new FFmpegExecutor(ffmpeg, ffprobe);
// Run a one-pass encode
executor.createJob(builder).run();
// Or run a two-pass encode (which is better quality at the cost of being slower)
executor.createTwoPassJob(builder).run();
You can install it using Maven:
<dependency>
<groupId>net.bramp.ffmpeg</groupId>
<artifactId>ffmpeg</artifactId>
<version>0.6.2</version>
</dependency>
Github: https://github.com/bramp/ffmpeg-cli-wrapper
Documentation: https://bramp.github.io/ffmpeg-cli-wrapper/
JAVE2
JAVE2 (Java Audio Video Encoder) is a Javan FFMPEG wrapper focused on transcoding audio and video files from a format to another, resize videos, separating audio and video tracks.
JAVE2 requires Java 8 or higher to run, plus FFMPEG and FFPROBE, and works on Windows 32 bits, Windows 64 bits, Mac OSX, Linux 32 bits and Linux 64 bits.
Sample code:
boolean succeeded;
try {
File source = new File("file path");
File target = new File("file path");
//Audio Attributes
AudioAttributes audio = new AudioAttributes();
audio.setCodec("libmp3lame");
audio.setBitRate(128000);
audio.setChannels(2);
audio.setSamplingRate(44100);
//Encoding attributes
EncodingAttributes attrs = new EncodingAttributes();
attrs.setFormat("mp3");
attrs.setAudioAttributes(audio);
//Encode
Encoder encoder = new Encoder();
encoder.encode(new MultimediaObject(source), target, attrs);
} catch (Exception ex) {
ex.printStackTrace();
succeeded = false;
}
Github: https://github.com/a-schild/jave2
Jaffree
Jafree (stands for JAvan FFMPEG and FFprobe FREE 😏) is inspired on ffmpeg-cli-wrapper.
Worth noting that this is the most recently updated Java wrapper in this list, so make sense to have a look at it looking at the future.
Supports JDK 8, 11 and 17, and Ubuntu, Windows and MacOS platforms.
Sample code:
FFmpeg.atPath()
.addInput(
UrlInput.fromUrl(pathToSrc)
.setPosition(10, TimeUnit.SECONDS)
.setDuration(42, TimeUnit.SECONDS)
)
.setFilter(StreamType.VIDEO, "scale=160:-2")
.setOverwriteOutput(true)
.addArguments("-movflags", "faststart")
.addOutput(
UrlOutput.toUrl(pathToDst)
.setPosition(10, TimeUnit.SECONDS)
)
.execute();
Github: https://github.com/kokorin/Jaffree
Best mobile FFMPEG wrappers
Mobile App development is not an exception with the FFMPEG wrappers, and even the usual solutions are focused on a single platform, there's a significant exception with ffmpeg-kit.
ffmpeg-kit
ffmpeg-kit is a collection of tools to use FFmpeg in Android, iOS, macOS, tvOS, Flutter and React Native applications.
It includes scripts to build FFmpeg native libraries, a wrapper library to run FFmpeg/FFprobe commands in applications and 8 prebuilt binary packages available at Github, Maven Central, CocoaPods, pub and npm.
As far as I know, ffmpeg-kit
is unique in its kind, and a perfect solution to build apps for different
platforms and reuse part of the logic.
Additionally, ffmpeg-kit
pace of new releases is pretty amazing, having several releases during the last year.
Best Android FFMPEG wrappers
Drilling down the mobile platforms, we found a few dedicated to Android that worth mention but, aside of ffmpeg-kit, all are pretty old and discontinued.
ffmpeg-kit for Android
Just to not miss it in this section, even it's been commented above.
The direct link to the Android home page is here: https://github.com/tanersener/ffmpeg-kit/tree/main/android
android-ffmpeg-java
android-ffmpeg-java is a Java wrapper around an ffmpeg command line binary for use in Android applications.
The project is now discontinued.
ffmpeg-android-java
FFmpeg Android java is a java library that simplifies your task of using ffmpeg in Android.
The project is now discontinued.
Best iOS FFMPEG wrappers
Aside of the already mentioned ffmpeg-kit
there are 2 other iOS FFMPEG wrappers. Again, both are discontinued, so double-check if it makes sense
to start a project using an outdated library.
ffmpeg-kit for Apple iOS
Just to not miss it in this section, even it's been commented above.
The direct link to the Android home page is here: https://github.com/tanersener/ffmpeg-kit/tree/main/apple
FFmpeg Wrapper
FFmpeg Wrapper is a really old and discontinued library (not updated since 2014).
SwiftFFmpeg
SwiftFFmpeg is a discontinued wrapper (not updated since 2019) that didn't get into an stable version, so very careful when using it for production environments.
Best .NET FFMPEG wrappers
There is more active community around .NET than around iOS or Android in terms of FFMPEG wrappers. Three projects that are worth to mention that are alive and with frequent updates.
FFMpegCore
FFMpegCore is one of the .NET FFMPEG wrappers available. It's aimed to easily integrate media analysis and conversion into your .NET applications and supports both synchronous and asynchronous calls.
A sample code:
FFMpegArguments
.FromFileInput(inputPath)
.OutputToFile(outputPath, false, options => options
.WithVideoCodec(VideoCodec.LibX264)
.WithConstantRateFactor(21)
.WithAudioCodec(AudioCodec.Aac)
.WithVariableBitrate(4)
.WithVideoFilters(filterOptions => filterOptions
.Scale(VideoSize.Hd))
.WithFastStart())
.ProcessSynchronously();
Github: https://github.com/rosenbjerg/FFMpegCore
FFmpeg.NET
FFmpeg.NET is another option to use in your .NET developments. FFmpeg.NET provides a straightforward interface for handling media data, making tasks such as converting, slicing and editing both audio and video completely effortless.
Under the hood, FFmpeg.NET is a .NET wrapper for FFmpeg supporting muxing, demuxing and transcoding tasks on many media formats. Some major parts are taken from MediaToolkit. Many features have been refactored and the library has been ported to Netstandard and made threadsafe.
An example of code:
var inputFile = new MediaFile (@"C:\Path\To_Video.flv");
var outputFile = new MediaFile (@"C:\Path\To_Save_Image.jpg");
var ffmpeg = new Engine("C:\ffmpeg\ffmpeg.exe");
// Saves the frame located on the 15th second of the video.
var options = new ConversionOptions { Seek = TimeSpan.FromSeconds(15) };
await ffmpeg.GetThumbnailAsync(inputFile, outputFile, options);
Github: https://github.com/cmxl/FFmpeg.NET
Xabe.FFmpeg
Xabe.FFmpeg is a slightly outdated wrapper (2020) that allows to process media without know how FFmpeg works, and can be used to pass customized arguments to FFmpeg from dotnet core application.
You can check the documentation here, and this is a sample of code:
string outputPath = Path.ChangeExtension(Path.GetTempFileName(), ".mp4");
IMediaInfo mediaInfo = await FFmpeg.GetMediaInfo(Resources.MkvWithAudio);
IStream videoStream = mediaInfo.VideoStreams.FirstOrDefault()
?.SetCodec(VideoCodec.H264);
IStream audioStream = mediaInfo.AudioStreams.FirstOrDefault()
?.SetCodec(AudioCodec.Aac);
FFmpeg.Conversions.New()
.AddStream(audioStream, videoStream)
.SetOutput(outputPath)
.Start();
Github: https://github.com/tomaszzmuda/Xabe.FFmpeg
Other languages
Rust
rust-ffmpeg is a fork of a discontinued wrapper with the same name. It's constantly updated but it supports FFMPEG up to version 4.4
Elixir
ffmpex is an FFMPEG wrapper for Elixir language that has a command builder approach. That is, it generates the final FFMPEG command-line parameters for you. It's quite updated and you can find the documentation here.
A sample code:
import FFmpex
use FFmpex.Options
command =
FFmpex.new_command
|> add_global_option(option_y())
|> add_input_file("/path/to/input.avi")
|> add_output_file("/path/to/output.avi")
|> add_stream_specifier(stream_type: :video)
|> add_stream_option(option_b("64k"))
|> add_file_option(option_maxrate("128k"))
|> add_file_option(option_bufsize("64k"))
{:ok, output} = execute(command)
Github: https://github.com/talklittle/ffmpex
GO lang
For GO lang, we have 2 main options:
Vidio
Vidio is a simple Video I/O library written in Go. This library relies on FFmpeg, and FFProbe which must be downloaded before usage and added to the system path. All frames are encoded and decoded in 8-bit RGB format.
goffmpeg
goffmpeg is self-described as an FFMPEG wrapper which allows to obtain the progress.
Self-evaluation
What is a FFMPEG wrapper?
Published on February 7th, 2022