easy_video_editor
A lightweight Flutter plugin for video editing without FFmpeg dependency. Trim, merge, adjust speed and more on Android & iOS.
A lightweight Flutter plugin for video editing without FFmpeg dependency. Trim, merge, adjust speed and more on Android & iOS.
{"sdk":"flutter"}^2.0.2{"sdk":"flutter"}^3.0.0English project snapshot. Visit GitHub for the latest content.
A powerful Flutter plugin for video editing operations with a simple, chainable API - without FFmpeg dependency. Perform common video editing tasks like trimming, merging, speed adjustment, and more with ease by leveraging native platform capabilities.
pub package likes License: MIT
Add this to your package's pubspec.yaml file:
dependencies:
easy_video_editor: ^0.1.6
Or install via command line:
flutter pub add easy_video_editor
import 'package:easy_video_editor/easy_video_editor.dart';
// Create a builder instance
final editor = VideoEditorBuilder(videoPath: '/path/to/video.mp4')
.trim(startTimeMs: 0, endTimeMs: 5000) // Trim first 5 seconds
.speed(speed: 1.5) // Speed up by 1.5x
.removeAudio(); // Remove audio
// Export the edited video with progress tracking
final outputPath = await editor.export(
outputPath: '/path/to/output.mp4', // Optional output path
onProgress: (progress) {
// Progress ranges from 0.0 to 1.0 (0% to 100%)
print('Export progress: ${(progress * 100).toStringAsFixed(1)}%');
// Update UI with progress information
// e.g., setState(() => exportProgress = progress);
}
);
final editor = VideoEditorBuilder(videoPath: '/path/to/video.mp4')
// Trim video
.trim(startTimeMs: 1000, endTimeMs: 6000)
// Merge with another video
.merge(otherVideoPaths: ['/path/to/second.mp4'])
// Adjust speed
.speed(speed: 1.5)
// Compress video
.compress(resolution: VideoResolution.p720)
// Crop video
.crop(aspectRatio: VideoAspectRatio.ratio16x9)
// Rotate video
.rotate(degree: RotationDegree.d90)
// Flip video
.flip(flipDirection: FlipDirection.horizontal);
// Export the final video
final outputPath = await editor.export(
outputPath: '/path/to/output.mp4' // Optional output path
);
// Extract audio
final audioPath = await editor.extractAudio(
outputPath: '/path/to/output.m4a' // Optional output path, iOS outputs M4A format
);
// Generate thumbnail
final thumbnailPath = await editor.generateThumbnail(
positionMs: 2000,
quality: 85,
width: 1280, // optional
height: 720, // optional
exactFrame: true, // optional, request exact-frame extraction when supported
outputPath: '/path/to/thumbnail.jpg' // Optional output path
);
// Extract raw RGBA8888 frame pixels
final frame = await editor.getFrame(
positionMs: 2000,
width: 320, // optional
height: 180, // optional
exactFrame: true, // optional, request closest exact frame when supported
);
if (frame != null) {
print('Frame: ${frame.width}x${frame.height}');
print('Pixel bytes: ${frame.bytes.length}');
}
// Get video metadata
final metadata = await editor.getVideoMetadata();
print('Duration: ${metadata.duration} ms');
print('Dimensions: ${metadata.width}x${metadata.height}');
print('Orientation: ${metadata.rotation}°');
print('File size: ${metadata.fileSize} bytes');
print('Creation date: ${metadata.date}');
final editor = VideoEditorBuilder(videoPath: '/path/to/video.mp4')
.trim(startTimeMs: 1000, endTimeMs: 10000)
.compress(resolution: VideoResolution.p720);
// Track export progress
double exportProgress = 0.0;
// Export with progress updates
final outputPath = await editor.export(
outputPath: '/path/to/output.mp4',
onProgress: (progress) {
setState(() {
exportProgress = progress; // Update state variable
});
// Use progress value (0.0 to 1.0) to update UI
// For example, with a LinearProgressIndicator:
// LinearProgressIndicator(value: exportProgress)
}
);
final editor = VideoEditorBuilder(videoPath: '/path/to/video.mp4');
// Start an operation
final outputPath = await editor.trim(startTimeMs: 0, endTimeMs: 5000);
// Cancel the operation
await editor.cancel();
The main class for chaining video operations.
VideoEditorBuilder({required String videoPath}): Creates a new builder instancetrim({required int startTimeMs, required int endTimeMs}): Trim video to specified duration (outputs MP4)merge({required List<String> otherVideoPaths}): Merge with other videos, fitting mixed dimensions and orientations into one output canvas (outputs MP4)speed({required double speed}): Adjust playback speed (e.g., 0.5 for half speed, 2.0 for double speed) (outputs MP4)removeAudio(): Remove audio track (outputs MP4)rotate({required RotationDegree degree}): Rotate video by 90, 180, or 270 degrees (outputs MP4)crop({required VideoAspectRatio aspectRatio}): Crop video to predefined aspect ratio (outputs MP4)compress({VideoResolution resolution = VideoResolution.p720}): Compress video to standard resolution (outputs MP4)
flip({required FlipDirection flipDirection}): Flip video horizontally or vertically (outputs MP4)export({String? outputPath, void Function(double progress)? onProgress}): Process all operations and return output path (outputs MP4)
outputPath: Optional custom path for the output fileonProgress: Optional callback that receives progress updates (0.0 to 1.0) during exportextractAudio({String? outputPath}): Extract audio to separate file (outputs M4A on iOS, AAC on Android)generateThumbnail({required int positionMs, required int quality, int? width, int? height, bool exactFrame = false, String? outputPath}): Generate thumbnail (outputs JPEG)getFrame({required int positionMs, int? width, int? height, bool exactFrame = false}): Extract raw RGBA8888 frame pixels at the requested video positiongetVideoMetadata(): Retrieves detailed metadata about the current video fileget currentPath: Gets the current video pathAdd the following permissions to your AndroidManifest.xml:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Requires iOS 13.0 or later.
The iOS plugin supports both CocoaPods and Swift Package Manager. Flutter will use Swift Package Manager when it is enabled in your Flutter project and will continue to fall back to CocoaPods for existing projects.
On iOS, transformed video exports such as merge, scale, rotate, flip, and crop preserve the source track frame rate when AVFoundation reports one. If the source frame rate is unavailable, the exporter falls back to 30 fps.
Add the following keys to your Info.plist:
<key>NSPhotoLibraryUsageDescription</key>
<string>This app requires access to the photo library for video editing.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>This app requires access to the photo library to save edited videos.</string>
Contributions are always welcome! Here's how you can help:
This project is licensed under the MIT License - see the LICENSE file for details.
If you find this plugin helpful, please give it a star on GitHub! It helps others discover the plugin and motivates me to keep improving it.