ai_video_editor 1.0.0
ai_video_editor: ^1.0.0 copied to clipboard
CapCut-style video editor for Flutter with free on-device AI: voice AI Edit, AI Shorts, captions, noise cancellation, cut-out, transitions and FFmpeg export.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:ai_video_editor/video_editor.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(const VideoEditorExampleApp());
}
/// CapCut-style entry point: projects home with one-tap editor launch.
class VideoEditorExampleApp extends StatelessWidget {
const VideoEditorExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Video Editor',
theme: VideoEditorTheme.dark(),
home: const VideoEditorExamplePage(),
debugShowCheckedModeBanner: false,
);
}
}
class VideoEditorExamplePage extends StatelessWidget {
const VideoEditorExamplePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: ListView(
padding: const EdgeInsets.all(VideoEditorSpacing.lg),
children: [
const Text('Video Editor', style: VideoEditorTextStyles.screenTitle),
const SizedBox(height: VideoEditorSpacing.sm),
const Text(
'CapCut-style editing with free, on-device AI: auto captions, '
'person cut-out, beat sync, AI music and voiceover.',
style: VideoEditorTextStyles.bodySecondary,
),
const SizedBox(height: VideoEditorSpacing.xl),
GradientButton(
label: 'New project',
icon: Icons.add,
onPressed: () => _open(context, const VideoEditorScreen()),
),
const SizedBox(height: VideoEditorSpacing.md),
_Tile(
icon: Icons.folder_open,
title: 'My projects',
subtitle: 'Reopen saved drafts',
onTap: () => _open(context, const ProjectsScreen()),
),
_Tile(
icon: Icons.tune,
title: 'Editor with external controller',
subtitle: 'Host app owns the controller',
onTap: () => _open(context, const VideoEditorScreenWithController()),
),
],
),
),
);
}
void _open(BuildContext context, Widget screen) {
Navigator.of(context).push(MaterialPageRoute<void>(builder: (_) => screen));
}
}
class _Tile extends StatelessWidget {
const _Tile({
required this.icon,
required this.title,
required this.subtitle,
required this.onTap,
});
final IconData icon;
final String title;
final String subtitle;
final VoidCallback onTap;
@override
Widget build(BuildContext context) {
return Card(
color: VideoEditorColors.surface,
margin: const EdgeInsets.only(bottom: VideoEditorSpacing.sm),
child: ListTile(
leading: Icon(icon, color: VideoEditorColors.primary),
title: Text(title),
subtitle: Text(subtitle, style: VideoEditorTextStyles.caption),
trailing: const Icon(Icons.chevron_right),
onTap: onTap,
),
);
}
}
/// Demonstrates injecting an externally owned controller.
class VideoEditorScreenWithController extends StatefulWidget {
const VideoEditorScreenWithController({super.key});
@override
State<VideoEditorScreenWithController> createState() =>
_VideoEditorScreenWithControllerState();
}
class _VideoEditorScreenWithControllerState
extends State<VideoEditorScreenWithController> {
late final VideoEditorController _controller = VideoEditorController();
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return VideoEditorScreen(existingController: _controller);
}
}