native_video_editor 0.4.0
native_video_editor: ^0.4.0 copied to clipboard
A Flutter plugin for native video edits using AVFoundation and AndroidX Media3 Transformer.
native_video_editor #
Native video editing for Flutter without FFmpeg.
native_video_editor exposes a small Dart API that sends edit requests to the
platform video stack:
- Android: AndroidX Media3 Transformer
- iOS: AVFoundation
- macOS: AVFoundation
- Windows: Windows Media Editing (
Windows.Media.Editing.MediaComposition)
The first release focuses on a unified native processing pipeline that can apply multiple edits in one export.
Features #
| Feature | Android | iOS | macOS | Windows |
|---|---|---|---|---|
| Trim start/end time | Yes | Yes | Yes | Yes |
| Normalized crop | Yes | Yes | Yes | Yes |
| Resize / scale output | Yes | Yes | Yes | Yes |
| Rotate 0, 90, 180, or 270 degrees | Yes | Yes | Yes | Yes |
| Speed adjustment | Yes | Yes | Yes | Yes |
| Mute audio | Yes | Yes | Yes | Yes |
| Progress reporting & cancellation | Yes | Yes | Yes | Yes |
| Compose image + audio into video | Yes | Yes | Yes | Yes |
| Merge / replace background audio | Yes | Yes | Yes | Yes |
| Thumbnail extraction | Yes | Yes | Yes | Yes |
Installation #
Add the package to your pubspec.yaml:
dependencies:
native_video_editor: ^0.4.0
Then run:
flutter pub get
Platform Requirements #
Android #
- Minimum SDK: 23
- Native backend: AndroidX Media3 Transformer
- The app must provide local file paths that Android can read and write.
iOS & macOS #
- Minimum iOS deployment target: 13.0
- Minimum macOS deployment target: 10.15
- Native backend: AVFoundation
- The app must provide sandbox-accessible local file paths.
Windows #
- Minimum OS version: Windows 10 (version 1809+ / build 17763+)
- Native backend: C++/WinRT (
Windows.Media.Editing.MediaComposition) - The app must provide valid local file system paths.
Basic Usage #
import 'package:native_video_editor/native_video_editor.dart';
final outputPath = await NativeVideoEditor.processVideo(
VideoEditRequest(
inputPath: inputPath,
outputPath: outputPath,
trimStart: const Duration(seconds: 1),
trimEnd: const Duration(seconds: 8),
cropRect: const VideoCropRect(
left: 0.1,
top: 0.1,
width: 0.8,
height: 0.8,
),
targetWidth: 720,
targetHeight: 720,
rotationDegrees: 90,
speedMultiplier: 1.25,
muteAudio: true,
),
);
Request Options #
Trimming #
Use trimStart and trimEnd to export only part of a video:
VideoEditRequest(
inputPath: inputPath,
outputPath: outputPath,
trimStart: const Duration(seconds: 3),
trimEnd: const Duration(seconds: 12),
);
Cropping #
VideoCropRect uses normalized values from 0.0 to 1.0 relative to the
oriented source frame.
const crop = VideoCropRect(
left: 0.1,
top: 0.1,
width: 0.8,
height: 0.8,
);
This keeps the center 80% of the source frame.
Resizing #
Set both targetWidth and targetHeight to resize the export:
VideoEditRequest(
inputPath: inputPath,
outputPath: outputPath,
targetWidth: 1280,
targetHeight: 720,
);
Both dimensions must be positive even numbers because many platform encoders reject odd output sizes.
Rotation #
rotationDegrees is clockwise and must be one of:
090180270
Muting Audio #
Set muteAudio to true to export the video without an audio track:
VideoEditRequest(
inputPath: inputPath,
outputPath: outputPath,
muteAudio: true,
);
Speed Adjustment #
Use speedMultiplier to slow down or speed up the exported video:
VideoEditRequest(
inputPath: inputPath,
outputPath: outputPath,
speedMultiplier: 1.5,
);
Values greater than 1.0 make the output faster. Values less than 1.0 make
the output slower. Supported values are from 0.25 to 4.0.
Progress Reporting & Cancellation #
Pass an onProgress callback to receive real-time export progress updates (0.0 to 1.0). To cancel an ongoing export, call NativeVideoEditor.cancelProcessVideo:
final resultPath = await NativeVideoEditor.processVideo(
request,
onProgress: (progress) {
print('Export progress: ${(progress * 100).toStringAsFixed(1)}%');
},
);
// Cancel from another UI handler:
await NativeVideoEditor.cancelProcessVideo(outputPath);
Image + Audio Composition #
Compose a still image (PNG or JPEG) and an audio track into a video frame:
final outputPath = await NativeVideoEditor.composeImageWithAudio(
ImageVideoComposeRequest(
imagePath: imagePath,
audioPath: audioPath,
outputPath: outputPath,
targetWidth: 1080,
targetHeight: 1920,
audioDurationMs: 15000, // Optional cap in ms
frameRate: 30,
),
onProgress: (progress) => print('Composing: $progress'),
);
Audio Merging into Video #
Inject or replace background audio in an existing video:
final outputPath = await NativeVideoEditor.mergeAudioIntoVideo(
AudioMergeRequest(
inputVideoPath: videoPath,
audioPath: audioPath,
outputPath: outputPath,
replaceExistingAudio: true, // Set false to mix streams
),
onProgress: (progress) => print('Merging: $progress'),
);
Thumbnail Extraction #
Extract a thumbnail frame to a JPEG or PNG file:
final thumbnailPath = await NativeVideoEditor.extractThumbnail(
VideoThumbnailRequest(
inputPath: inputPath,
outputPath: thumbnailPath,
position: const Duration(seconds: 2),
quality: 92,
),
);
Use .jpg, .jpeg, or .png in outputPath to choose the image format.
File Path Notes #
The plugin expects local file paths. It does not request storage permissions or copy files for you.
In a real app, a common flow is:
- Let the user pick or record a video.
- Copy that video into your app sandbox or cache directory.
- Build an output path in a writable cache/documents directory.
- Call
NativeVideoEditor.processVideo.
inputPath and outputPath must be different files. Existing output files are
replaced.
Example App #
This package includes a runnable, full-featured interactive UI video editor example:
cd example
flutter pub get
flutter run
The example features:
- Interactive timeline trimming slider
- Visual cropping overlay box with aspect ratio control
- Live video player preview
- Real-time export progress tracking and cancellation modal
- Full support for image+audio video composition and audio merging tools
Limitations #
- Unsupported source codecs can fail if the platform encoder/decoder cannot process them.
- Long videos can take time to export because processing is done by the native platform stack.
- Watermarks, text overlays, and advanced filter effects are planned for later phases.
Troubleshooting #
The export fails immediately #
Check that the input file exists, the output directory is writable, and the input and output paths are different.
The output size is rejected #
Use even values for targetWidth and targetHeight, such as 720x1280 or
1280x720.
The source video cannot be decoded #
Try a common MP4/H.264 source first. The plugin relies on Media3 and AVFoundation codec support rather than FFmpeg.