Video Trim Editor

pub package License: MIT

A beautiful and customizable video trimmer widget for Flutter with timeline preview, drag-to-trim handles, and playback controls.

Features

✨ Beautiful UI - Modern, intuitive interface with smooth animations
🎬 Video Preview - Real-time video playback with play/pause controls
πŸ“Έ Thumbnail Timeline - Automatically generated video thumbnails
βœ‚οΈ Drag-to-Trim - Intuitive handles for selecting trim range
⏱️ Duration Control - Set maximum allowed duration
🎨 Fully Customizable - Theming system for colors, styles, and more
⚑ Performance Optimized - Smooth dragging with debounced seeking
πŸ“± Cross-platform - Works on iOS, Android, Web, and Desktop

Screenshots

Installation

Add this to your package's pubspec.yaml file:

dependencies:
  video_trim_editor: ^0.1.0

Then run:

flutter pub get

Usage

Basic Example

import 'package:flutter/material.dart';
import 'package:video_trim_editor/video_trim_editor.dart';
import 'dart:io';

class TrimVideoScreen extends StatelessWidget {
  final File videoFile;

  const TrimVideoScreen({Key? key, required this.videoFile}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return VideoTrimmerWidget(
      videoFile: videoFile,
      maxDuration: const Duration(seconds: 30),
      onVideoTrimmed: (trimmedVideo) {
        // Handle the trimmed video file
        print('Video trimmed: ${trimmedVideo.path}');
      },
    );
  }
}

With Custom Theme

VideoTrimmerWidget(
  videoFile: videoFile,
  maxDuration: const Duration(seconds: 60),
  theme: VideoTrimmerTheme.light().copyWith(
    accentColor: Colors.blue,
    primaryTextColor: Colors.black,
  ),
  onVideoTrimmed: (trimmedVideo) {
    // Handle the trimmed video
  },
  onError: (error, stackTrace) {
    // Handle errors
    print('Error: $error');
  },
  onInfo: (message) {
    // Handle info messages
    print('Info: $message');
  },
)

Custom Configuration

VideoTrimmerWidget(
  videoFile: videoFile,
  maxDuration: const Duration(minutes: 2),
  showAppBar: true,
  appBarTitle: 'Edit Video',
  continueButtonText: 'DONE',
  theme: VideoTrimmerTheme(
    backgroundColor: Color(0xFF1A1A1A),
    accentColor: Color(0xFF00FF00),
    primaryTextColor: Colors.white,
    secondaryTextColor: Colors.grey,
    // ... more theme options
  ),
  onVideoTrimmed: (trimmedVideo) async {
    // Save to gallery or upload to server
    await saveToGallery(trimmedVideo);
    Navigator.pop(context);
  },
)

Theme Customization

The package provides a comprehensive theming system:

VideoTrimmerTheme(
  // Background colors
  backgroundColor: Color(0xFF000000),
  appBarBackgroundColor: Color(0xFF1A1A1A),
  
  // Text colors
  primaryTextColor: Color(0xFFFFFFFF),
  secondaryTextColor: Color(0xFFB8B8B8),
  
  // Accent color (handles, borders, buttons)
  accentColor: Color(0xFF8B5CF6),
  
  // Thumbnail colors
  thumbnailBackgroundColor: Color(0xFF0D0D0D),
  thumbnailBorderColor: Color(0xFF292929),
  
  // Processing overlay
  processingOverlayColor: Color(0xFF000000),
  progressIndicatorColor: Color(0xFF8B5CF6),
  
  // Timeline colors
  dimmedAreaColor: Color(0x8A000000),
  playbackIndicatorColor: Color(0xCCFFFFFF),
  
  // Play button
  playButtonBackgroundColor: Color(0x8A000000),
  playButtonIconColor: Color(0xFFFFFFFF),
  
  // Text styles
  titleTextStyle: TextStyle(...),
  bodyTextStyle: TextStyle(...),
  captionTextStyle: TextStyle(...),
  buttonTextStyle: TextStyle(...),
  
  // Border radius
  trimmerBorderRadius: BorderRadius.only(
    topLeft: Radius.circular(48),
    topRight: Radius.circular(48),
  ),
  thumbnailBorderRadius: BorderRadius.circular(4),
)

Pre-built Themes

// Dark theme (default)
VideoTrimmerWidget(
  theme: VideoTrimmerTheme.dark(),
  // ...
)

// Light theme
VideoTrimmerWidget(
  theme: VideoTrimmerTheme.light(),
  // ...
)

API Reference

VideoTrimmerWidget

Parameter Type Default Description
videoFile File required The video file to trim
maxDuration Duration 30 seconds Maximum allowed duration for trimmed video
onVideoTrimmed Function(File)? null Callback when video is successfully trimmed
theme VideoTrimmerTheme? dark theme Custom theme configuration
onError Function(String, StackTrace)? null Error callback
onInfo Function(String)? null Info/progress callback
showAppBar bool true Whether to show the app bar
appBarTitle String 'Trim Video' App bar title text
continueButtonText String 'CONTINUE' Continue button text

Advanced Usage

Using as a Route

// Navigate to trimmer screen
final trimmedVideo = await Navigator.push<File>(
  context,
  MaterialPageRoute(
    builder: (context) => VideoTrimmerWidget(
      videoFile: videoFile,
      maxDuration: const Duration(seconds: 30),
    ),
  ),
);

if (trimmedVideo != null) {
  print('Video was trimmed: ${trimmedVideo.path}');
}

Without App Bar

Scaffold(
  appBar: AppBar(title: Text('Custom App Bar')),
  body: VideoTrimmerWidget(
    videoFile: videoFile,
    showAppBar: false, // Hide built-in app bar
    maxDuration: const Duration(seconds: 45),
  ),
)

Error Handling

VideoTrimmerWidget(
  videoFile: videoFile,
  onError: (error, stackTrace) {
    // Log to analytics
    FirebaseCrashlytics.instance.recordError(error, stackTrace);
    
    // Show user-friendly message
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text('Failed to trim video')),
    );
  },
  onInfo: (message) {
    // Show progress updates
    print('Trimmer info: $message');
  },
)

How It Works

  1. Video Selection: Pass a video file to the widget
  2. Thumbnail Generation: Thumbnails are automatically generated for the timeline
  3. Trim Selection: User drags handles to select the desired portion
  4. Preview: Video plays in a loop within the selected range
  5. Processing: When user confirms, video is trimmed using native platform APIs
  6. Callback: Trimmed video file is returned via onVideoTrimmed callback

Performance Tips

  • File Size: Videos larger than 500MB will be rejected by default
  • Thumbnails: 8 thumbnails are generated by default (configurable)
  • Seek Performance: Seeking is debounced during dragging for smooth performance
  • Memory: Old controllers are properly disposed to prevent memory leaks

Platform Support

Platform Supported Notes
Android βœ… Android 5.0+
iOS βœ… iOS 12.0+
Web βœ… Modern browsers
macOS βœ… macOS 10.14+
Windows βœ… Windows 10+
Linux βœ… GTK 3.0+

Requirements

  • Flutter: >=3.0.0
  • Dart: >=3.0.0

Dependencies

This package uses:

  • video_player - For video playback
  • flutter_native_video_trimmer - For native video trimming
  • video_thumbnail - For thumbnail generation
  • flutter_riverpod - For state management
  • file_picker - For file selection
  • freezed - For immutable state models

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Issues

If you encounter any problems or have suggestions, please open an issue.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Author

Priyanshu Mallick
Email: priyanshumallick123456@gmail.com GitHub: @Priyanshu-Mallick

Acknowledgments

  • Inspired by video editing apps and the Flutter community
  • Built with Flutter's amazing ecosystem of packages

Changelog

See CHANGELOG.md for a list of changes.


Made with ❀️ by Priyanshu

Libraries

video_trim_editor