zeba_academy_media_tools 1.0.0
zeba_academy_media_tools: ^1.0.0 copied to clipboard
A powerful Flutter media utility package for image compression, video compression, audio recording, video trimming, thumbnail generation, and image cropping.
example/lib/main.dart
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:zeba_academy_media_tools/zeba_academy_media_tools.dart';
void main() {
runApp(const MediaToolsApp());
}
class MediaToolsApp extends StatelessWidget {
const MediaToolsApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "Zeba Media Tools",
debugShowCheckedModeBanner: false,
theme: ThemeData(
useMaterial3: true,
colorSchemeSeed: Colors.indigo,
),
home: const MediaToolsHome(),
);
}
}
class MediaToolsHome extends StatefulWidget {
const MediaToolsHome({super.key});
@override
State<MediaToolsHome> createState() => _MediaToolsHomeState();
}
class _MediaToolsHomeState extends State<MediaToolsHome> {
File? _image;
File? _videoThumb;
File? _videoFile;
bool _isRecording = false;
@override
void initState() {
super.initState();
MediaTools.initRecorder();
}
@override
void dispose() {
MediaTools.disposeRecorder();
super.dispose();
}
Future<void> pickImage() async {
final image = await MediaTools.pickImage();
if (image == null) return;
final compressed = await MediaTools.cropAndCompressImage(image);
if (!mounted) return;
setState(() {
_image = compressed;
});
}
Future<void> pickVideo() async {
final picker = ImagePicker();
final picked = await picker.pickVideo(source: ImageSource.gallery);
if (picked == null) return;
final video = File(picked.path);
final thumb = await MediaTools.generateVideoThumbnail(picked.path);
if (!mounted) return;
setState(() {
_videoFile = video;
_videoThumb = thumb;
});
}
Future<void> compressVideo() async {
if (_videoFile == null) return;
final compressed = await MediaTools.compressVideo(_videoFile!);
if (!mounted) return;
if (compressed == null) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("Compression failed")),
);
return;
}
setState(() => _videoFile = compressed);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("Video Compressed")),
);
}
Future<void> recordAudio() async {
if (_isRecording) {
final path = await MediaTools.stopRecording();
if (!mounted) return;
setState(() => _isRecording = false);
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text("Saved at: $path")));
} else {
await MediaTools.startRecording("test_audio");
if (!mounted) return;
setState(() => _isRecording = true);
}
}
Widget featureCard({
required IconData icon,
required String title,
required String subtitle,
required VoidCallback onTap,
Color? color,
}) {
return InkWell(
borderRadius: BorderRadius.circular(18),
onTap: onTap,
child: Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(18),
color: Colors.white,
boxShadow: [
BoxShadow(
blurRadius: 10,
color: Colors.black.withValues(alpha: 0.08),
offset: const Offset(0, 4),
)
],
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircleAvatar(
radius: 26,
backgroundColor: color ?? Colors.indigo,
child: Icon(icon, color: Colors.white),
),
const SizedBox(height: 12),
Text(title,
textAlign: TextAlign.center,
style: const TextStyle(
fontWeight: FontWeight.bold, fontSize: 15)),
const SizedBox(height: 4),
Text(
subtitle,
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 12, color: Colors.grey),
)
],
),
),
);
}
Widget previewBox(String title, File file) {
return Container(
margin: const EdgeInsets.only(top: 20),
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
color: Colors.grey.shade100,
),
child: Column(
children: [
Text(title, style: const TextStyle(fontWeight: FontWeight.bold)),
const SizedBox(height: 10),
ClipRRect(
borderRadius: BorderRadius.circular(12),
child: Image.file(file, height: 150),
),
],
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey.shade50,
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
Container(
width: double.infinity,
padding: const EdgeInsets.all(22),
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [Colors.indigo, Colors.blue],
),
borderRadius: BorderRadius.circular(20),
),
child: const Column(
children: [
Icon(Icons.perm_media,
color: Colors.white, size: 50),
SizedBox(height: 10),
Text(
"Zeba Media Tools",
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold),
),
Text(
"Image • Video • Audio Utilities",
style: TextStyle(color: Colors.white70),
)
],
),
),
const SizedBox(height: 25),
Expanded(
child: GridView.count(
crossAxisCount: 2,
crossAxisSpacing: 16,
mainAxisSpacing: 16,
children: [
featureCard(
icon: Icons.image,
title: "Image Compress",
subtitle: "Pick & compress image",
onTap: pickImage,
),
featureCard(
icon: Icons.video_library,
title: "Video Thumbnail",
subtitle: "Generate preview",
onTap: pickVideo,
),
featureCard(
icon: Icons.compress,
title: "Video Compress",
subtitle: "Reduce video size",
onTap: compressVideo,
),
featureCard(
icon: _isRecording ? Icons.stop : Icons.mic,
title: _isRecording
? "Stop Recording"
: "Start Recording",
subtitle: "Record audio",
color: _isRecording ? Colors.red : Colors.green,
onTap: recordAudio,
),
],
),
),
if (_image != null)
previewBox("Compressed Image", _image!),
if (_videoThumb != null)
previewBox("Video Thumbnail", _videoThumb!),
],
),
),
),
);
}
}