ffmpeg-kit-extended is a comprehensive Flutter plugin for executing FFmpeg, FFprobe, and FFplay commands on Windows, and Linux. It leverages Dart FFI to interact directly with native FFmpeg libraries, providing high performance and flexibility.
- Cross-Platform Support: Works on Windows, and Linux.
- Android, iOS, macOS: Not yet supported.
- FFmpeg, FFprobe & FFplay: Full support for media manipulation and information retrieval.
- Dart FFI: Direct native bindings for optimal performance.
- Asynchronous Execution: Run long-running tasks without blocking the UI thread.
- Parallel Execution: Run multiple tasks in parallel.
- Callback Support: detailed hooks for logs, statistics, and session completion.
- Session Management: Full control over execution lifecycle (start, cancel, list).
- Extensible: Designed to allow custom native library loading and configuration.
- Deploy Custom Builds: You can deploy custom builds of ffmpeg-kit-extended. See: https://github.com/akashskypatel/ffmpeg-kit-builders
| Platform | Status | Architecture |
|---|---|---|
| Android | 🚧 Planned | armv7, arm64, x86_64 |
| iOS | Not Supported | |
| macOS | Not Supported | |
| Linux | ✅ Supported | x86_64 |
| Windows | ✅ Supported | x86_64 |
-
Install the package:
flutter pub add ffmpeg_kit_extended_flutter
-
Add the dependency to your
pubspec.yamlthen addffmpeg_kit_extended_configsection to yourpubspec.yaml:dependencies: ffmpeg_kit_extended_flutter: ^0.1.0 ffmpeg_kit_extended_config: version: "0.8.2" # version of the pre-bundled libffmpegkit libraries released at https://github.com/akashskypatel/ffmpeg-kit-builders/releases type: "base" # pre-bundled builds: debug, base, full, audio, video, video_hw gpl: true # enable to include GPL libraries small: true # enable to use smaller builds # == OR == # ------------------------------------------------------------- # You can specify remote or local path to libffmpegkit libraries for each platform # This allows you to deploy custom builds of libffmpegkit. # See: https://github.com/akashskypatel/ffmpeg-kit-builders # Note: This will override all above options. # ------------------------------------------------------------- # windows: "path/to/ffmpeg-kit/libraries" # linux: "https://path/to/ffmpeg-kit/libraries"
-
Run
dart run ffmpeg_kit_extended_flutter:configureto generate the native libraries.dart run ffmpeg_kit_extended_flutter:configure
Configure Options
--help: Show this help message.--platform=<platform1,platform2>: Specify platforms to configure (e.g.,windows,linux).--verbose: Enable verbose output.--app-root=<path>: Specify the path to the app root.
-
Import the package in your Dart code:
import 'package:ffmpeg_kit_extended_flutter/ffmpeg_kit_extended_flutter.dart';
import 'package:ffmpeg_kit_extended_flutter/ffmpeg_kit_extended_flutter.dart';
// Execute a simple FFmpeg command asynchronously and wait for it to complete
final session = await FFmpegKit.executeAsync('-i input.mp4 -c:v libx264 output.mp4');
// Check the result
if (ReturnCode.isSuccess(session.getReturnCode())) {
print('Conversion successful!');
} else {
print('Conversion failed: ${session.getOutput()}');
}// Retrieve media information using FFprobe asynchronously
final session = await FFprobeKit.getMediaInformationAsync('/path/to/video.mp4');
if (session is MediaInformationSession) {
final info = session.getMediaInformation();
print('Duration: ${info?.duration}');
print('Format: ${info?.format}');
print('Bitrate: ${info?.bitrate}');
print('Streams: ${info?.streams.length}');
}// Play a media file
await FFplayKit.execute('-i input.mp4');
// Control playback
FFplayKit.pause();
FFplayKit.resume();
FFplayKit.seek(30.0); // Seek to 30 seconds
// Get playback status
final position = FFplayKit.getPosition();
final duration = FFplayKit.getDuration();
print('Playing at $position / $duration seconds');// Execute asynchronously with callbacks
await FFmpegKit.executeAsync(
'-i input.mp4 -vf scale=1280:720 output.mp4',
onComplete: (session) {
print('Command completed with return code: ${session.getReturnCode()}');
},
onLog: (log) {
print('FFmpeg log: ${log.message}');
},
onStatistics: (statistics) {
print('Progress: ${statistics.time}ms, Speed: ${statistics.speed}x');
},
);Every FFmpeg, FFprobe, or FFplay command creates a Session object that tracks:
- Execution state (created, running, completed, failed)
- Return code and output
- Logs and statistics
- Timing information (start time, end time, duration)
Synchronous: Blocks until the command completes
final session = FFmpegKit.execute('-i input.mp4 output.mp4');Asynchronous: Returns immediately and notifies via callbacks
await FFmpegKit.executeAsync('-i input.mp4 output.mp4',
onComplete: (session) => print('Done!'),
);Three types of callbacks are available for FFmpeg operations:
- Log Callback - Receives log messages from FFmpeg
- Statistics Callback - Receives real-time encoding statistics
- Complete Callback - Called when the session finishes
Callbacks can be set globally or per-session.
Comprehensive guides are available in the flutter/doc/ directory:
- Installation Guide - Detailed setup instructions (Coming soon)
- Quick Start Guide - Get up and running quickly
- Core Concepts - Understanding sessions, callbacks, and execution modes
- FFmpegKit API - Video and audio processing
- FFprobeKit API - Media information extraction
- FFplayKit API - Media playback
- FFmpegKitConfig API - Global configuration (Coming soon)
- Session API - Session management and control (Coming soon)
- Data Models - MediaInformation, Log, Statistics, etc. (Coming soon)
- Video Processing - Common video operations (Coming soon)
- Audio Processing - Audio conversion and manipulation (Coming soon)
- Media Information - Extracting and using media metadata (Coming soon)
- Playback Control - Using FFplay for media playback (Coming soon)
- Callbacks and Monitoring - Real-time progress tracking
- Error Handling - Handling failures and edge cases (Coming soon)
- Advanced Usage - Pipes, fonts, environment variables (Coming soon)
- Common Use Cases - Practical examples
- Complete Applications - Full app examples
await FFmpegKit.executeAsync(
'-i input.mp4 -c:v libx264 -preset medium -crf 23 output.mp4',
onStatistics: (stats) {
final progress = (stats.time / totalDuration) * 100;
print('Progress: ${progress.toStringAsFixed(1)}%');
},
onComplete: (session) {
if (ReturnCode.isSuccess(session.getReturnCode())) {
print('Conversion complete!');
}
},
);final session = await FFmpegKit.executeAsync(
'-i video.mp4 -ss 00:00:05 -vframes 1 thumbnail.jpg'
);
if (ReturnCode.isSuccess(session.getReturnCode())) {
print('Thumbnail extracted successfully');
}await FFmpegKit.executeAsync('-i video.mp4 -vn -acodec copy audio.aac');final session = await FFprobeKit.getMediaInformationAsync('video.mp4');
if (session is MediaInformationSession) {
final info = session.getMediaInformation();
final videoStreams = info?.streams
.where((s) => s.type == 'video')
.toList() ?? [];
for (final stream in videoStreams) {
print('Video stream: ${stream.codec}, ${stream.width}x${stream.height}');
}
}// Play a video file
await FFplayKit.execute('video.mp4');
// Check if currently playing
if (FFplayKit.isPlaying()) {
print('Playback is active');
}| Platform | Status | Architecture |
|---|---|---|
| Android | 🚧 Planned | API 21+ |
| iOS | Not Supported | iOS 12+ |
| macOS | Not Supported | macOS 10.13+ |
| Linux | ✅ Supported | x86_64 |
| Windows | ✅ Supported | x86_64 |
FFmpegKitConfig.setLogLevel(LogLevel.info);FFmpegKitConfig.setFontDirectory('/path/to/fonts');// Limit the number of sessions kept in history
FFmpegKitConfig.setSessionHistorySize(10);// Set global log callback for all sessions
FFmpegKitConfig.enableLogCallback((log) {
print('[${log.logLevel}] ${log.message}');
});
// Set global statistics callback
FFmpegKitConfig.enableStatisticsCallback((stats) {
print('Speed: ${stats.speed}x, Frame: ${stats.videoFrameNumber}');
});Check the session output and logs:
final session = await FFmpegKit.executeAsync('...');
print('Return code: ${session.getReturnCode()}');
print('Output: ${session.getOutput()}');
print('Logs: ${session.getLogs()}');Ensure you're using await and handling the Future properly:
await FFmpegKit.executeAsync('...', onComplete: (session) {
// This will be called when done
});Only one FFplay session can be active at a time. Starting a new session with FFplayKit.execute will automatically handle the previous one.
await FFplayKit.execute('video.mp4');Contributions are welcome! Please read our contributing guidelines and submit pull requests to our repository.
This library is licensed under the GNU Lesser General Public License v2.1 or later.
FFmpegKit Flutter Extended Plugin - A wrapper library for FFmpeg
Copyright (C) 2026 Akash Patel
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
See the LICENSE file for details.
- Issues: GitHub Issues
- Repository: GitHub
This plugin is built on top of FFmpeg, FFprobe, and FFplay. Special thanks to the FFmpeg team for their incredible work on these tools.