I build an android app to compress video to any resolutions and save as new file on gallery. If you wish to try let's check source code below.
Demo :
Packages Installation :
image_picker: ^0.8.5
video_compress: ^3.1.0
gallery_saver: ^2.3.2
path_provider: ^2.0.9
Source code :
Add following files inside lib directory
1. main.dart
xxxxxxxxxx
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
​
import 'home.dart';
​
void main() {
WidgetsFlutterBinding.ensureInitialized();
MobileAds.instance.initialize();
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
.then((_) {
runApp(const MyApp());
});
}
​
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
​
@override
State<MyApp> createState() => _MyAppState();
}
​
class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Vid Compressor',
home: Home(),
);
}
}
2. home.dart
xxxxxxxxxx
import 'dart:io';
import 'dart:typed_data';
​
import 'package:flutter/material.dart';
import 'package:gallery_saver/gallery_saver.dart';
import 'package:image_picker/image_picker.dart';
import 'package:vid_compressor/show_progress.dart';
import 'package:video_compress/video_compress.dart';
​
class Home extends StatefulWidget {
Home({Key? key}) : super(key: key);
​
@override
State<Home> createState() => _HomeState();
}
​
class _HomeState extends State<Home> {
late File vid;
late Uint8List thumb;
late String vidSize;
late MediaInfo compressedInfo;
bool picked = false;
bool compressed = false;
String fileName = "filename";
VideoQuality vidQuality = VideoQuality.LowQuality;
@override
void dispose() {
super.dispose();
}
​
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
alignment: Alignment.center,
child: Stack(alignment: Alignment.center, children: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: getBody(),
),
]),
),
backgroundColor: const Color.fromRGBO(230, 230, 230, 1),
);
}
​
void clear() {
setState(() {
picked = false;
compressed = false;
});
}
​
getBody() {
if (picked && !compressed) {
return [
Image.memory(
thumb,
height: 250,
),
const SizedBox(
height: 8,
),
Text("Original Size : $vidSize MB"),
const SizedBox(
height: 8,
),
DropdownButton(
value: vidQuality,
items: VideoQuality.values.map((quality) {
return DropdownMenuItem(
child: Text(quality.toString().replaceAll("VideoQuality.", "")),
value: quality,
);
}).toList(),
onChanged: (selected) {
setState(() {
// selectQuality = selected as VideoQuality;
vidQuality = selected as VideoQuality;
});
}),
const SizedBox(
height: 8,
),
ElevatedButton.icon(
style: _buttonStyle(),
onPressed: () => compressVid(vid),
icon: const Icon(Icons.wifi_protected_setup_outlined),
label: const Text("Compress")),
const SizedBox(
height: 8,
),
ElevatedButton.icon(
style: ElevatedButton.styleFrom(primary: Colors.blueAccent),
onPressed: () => clear(),
icon: const Icon(Icons.home),
label: const Text("Home")),
];
} else if (picked && compressed) {
return [
Image.memory(
thumb,
height: 250,
),
conpressWidget(),
const SizedBox(
height: 8,
),
ElevatedButton.icon(
onPressed: () {
clear();
},
icon: const Icon(Icons.home),
label: const Text("Home")),
];
} else {
return [
ElevatedButton.icon(
style: _buttonStyle(),
onPressed: () => pickVid(),
icon: const Icon(Icons.video_library),
label: const Text("Pick a video")),
];
}
}
​
ButtonStyle _buttonStyle() {
return ElevatedButton.styleFrom(
// primary: Colors.green,
// onPrimary: Colors.white,
// shadowColor: Colors.greenAccent,
elevation: 3,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(32.0)),
minimumSize: const Size(200, 60), //////// HERE
);
}
​
Widget conpressWidget() {
if (compressedInfo == null) return Container();
final size = (compressedInfo.filesize! / (1024 * 1024)).toStringAsFixed(2);
return Column(
children: [
const Text(
"Compressed",
style: TextStyle(fontSize: 20),
),
const SizedBox(
height: 8,
),
Text("Size : $size MB"),
const SizedBox(
height: 8,
),
Text(compressedInfo.path.toString()),
],
);
}
​
Future<void> pickVid() async {
final picker = ImagePicker();
final pickedFile = await picker.pickVideo(source: ImageSource.gallery);
if (pickedFile == null) return;
final file = File(pickedFile.path);
​
setState(() {
vid = file;
fileName = pickedFile.name;
});
getThumb(file);
getVidSize(file);
}
​
Future<void> getThumb(File file) async {
final pic = await VideoCompress.getByteThumbnail(file.path);
setState(() {
thumb = pic!;
});
}
​
Future<void> getVidSize(File file) async {
final size = await file.length();
setState(() {
vidSize = (size / (1024 * 1024)).toStringAsFixed(2);
picked = true;
});
}
​
Future<void> compressVid(File file) async {
showDialog(
context: context,
builder: (context) {
return const AlertDialog(
content: ShowProgress(),
);
},
);
​
final info = await VideoCompress.compressVideo(file.path,
quality: vidQuality, includeAudio: true);
final getFile = await VideoCompress.getMediaInfo(info!.path ?? "");
​
if (getFile != null) {
final savedFile = await GallerySaver.saveVideo(getFile.path ?? "",
albumName: "Vid Compressor");
}
​
info.path = "Saved to your gallery album: Vid Compressor";
setState(() {
compressedInfo = info;
compressed = true;
});
await VideoCompress.deleteAllCache();
Navigator.of(context).pop();
}
}
3. show_progress.dart
xxxxxxxxxx
import 'package:flutter/material.dart';
import 'package:video_compress/video_compress.dart';
​
class ShowProgress extends StatefulWidget {
const ShowProgress({Key? key}) : super(key: key);
​
@override
State<ShowProgress> createState() => _ShowProgressState();
}
​
class _ShowProgressState extends State<ShowProgress> {
late Subscription subscription;
double progress = 0;
@override
void initState() {
subscription = VideoCompress.compressProgress$.subscribe((progress) {
setState(() {
this.progress = progress;
});
});
​
// TODO: implement initState
super.initState();
}
​
@override
void dispose() {
VideoCompress.cancelCompression();
subscription.unsubscribe();
// TODO: implement dispose
super.dispose();
}
​
@override
Widget build(BuildContext context) {
final done = progress == 0 ? progress : progress / 100;
return Container(
height: MediaQuery.of(context).size.height * 0.2,
padding: const EdgeInsets.all(20),
child: Column(
children: [
const Text(
"Compressing...",
style: TextStyle(fontSize: 20),
),
const SizedBox(
height: 24,
),
LinearProgressIndicator(
value: done,
minHeight: 12,
),
const SizedBox(
height: 16,
),
ElevatedButton(
onPressed: () {
VideoCompress.cancelCompression();
subscription.unsubscribe();
Navigator.of(context).pop();
},
child: const Text(
"Cancel",
style: TextStyle(color: Colors.red),
))
],
),
);
}
}
can you please send GitHub code, because I have implemented same code you have given but some videos are compressing some dont. but your app compressing all videos. those which are not compressed by my machine with same code that also getting compressed on your app. plz help i am stucked.
ReplyDeleteSorry for late reply. I can't share Github repo but I promise all code shared above is full.
Delete