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
The first release focuses on a unified native processing pipeline that can apply multiple edits in one export.
Features
| Feature | Android | iOS |
|---|---|---|
| Trim start/end time | Yes | Yes |
| Normalized crop | Yes | Yes |
| Resize / scale output | Yes | Yes |
| Rotate 0, 90, 180, or 270 degrees | Yes | Yes |
| Speed adjustment | Yes | Yes |
| Mute audio | Yes | Yes |
| Thumbnail extraction | Yes | Yes |
Installation
Add the package to your pubspec.yaml:
dependencies:
native_video_editor: ^0.1.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
- Minimum deployment target: iOS 13.0
- Native backend: AVFoundation
- The app must provide sandbox-accessible local file 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.
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 example project:
cd example
flutter pub get
flutter run
The example applies trimming, cropping, resizing, rotation, and audio muting in one request. It also demonstrates thumbnail extraction with a real file picker and app-cache output paths.
Limitations
- Only Android and iOS are supported.
- 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, progress callbacks, cancellation, and transcoding controls 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.