Flutter图片压缩插件light_compressor的使用
Flutter图片压缩插件light_compressor的使用
插件概述
light_compressor
是一个强大且易于使用的Flutter视频压缩插件,基于 LightCompressor 库(用于Android)和 LightCompressor_iOS 库(用于iOS和macOS)。该插件可以生成具有修改后的宽度、高度和比特率的压缩MP4视频。其工作原理是减少极高的比特率,同时保持良好的视频质量,从而实现更小的文件大小。
安装与配置
添加依赖
首先,在您的pubspec.yaml
文件中添加light_compressor
作为依赖项:
dependencies:
light_compressor: ^latest_version # 替换为最新版本号
平台特定配置
iOS 和 macOS
在<project root>/ios/Runner/Info.plist
文件中添加以下内容:
<key>NSPhotoLibraryUsageDescription</key>
<string>${PRODUCT_NAME} library Usage</string>
Android
在AndroidManifest.xml
中添加权限声明:
- API < 29
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28"
tools:ignore="ScopedStorage" />
- API >= 29
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32"/>
- API >= 33
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
在项目级别的build.gradle
文件中添加JitPack仓库:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
在模块级别的build.gradle
文件中添加依赖:
implementation 'com.github.AbedElazizShe:LightCompressor:1.3.2'
确保Kotlin版本不低于1.8.21
,可以在项目级别的build.gradle
文件中设置:
ext.kotlin_version = '1.8.21'
使用示例
以下是一个完整的示例应用,展示了如何使用light_compressor
进行视频压缩,并展示压缩进度和结果。
import 'dart:async';
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:light_compressor/light_compressor.dart';
void main() {
runApp(MyApp());
}
/// A widget that uses LightCompressor library to compress videos
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late String _desFile;
String? _displayedFile;
late int _duration;
String? _failureMessage;
String? _filePath;
bool _isVideoCompressed = false;
final LightCompressor _lightCompressor = LightCompressor();
@override
Widget build(BuildContext context) => MaterialApp(
theme: ThemeData(
primaryColor: const Color(0xFF344772),
primaryColorDark: const Color(0xFF002046),
),
home: Scaffold(
appBar: AppBar(
title: const Text('Compressor Sample'),
actions: [
TextButton(
child: const Text(
'Cancel',
style: TextStyle(color: Colors.white, fontSize: 18),
),
onPressed: () => _lightCompressor.cancelCompression(),
)
],
),
body: Container(
margin: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (_filePath != null)
Text(
'Original size: ${_getVideoSize(file: File(_filePath!))}',
style: const TextStyle(fontSize: 16),
),
const SizedBox(height: 8),
if (_isVideoCompressed)
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Size after compression: ${_getVideoSize(file: File(_desFile))}',
style: const TextStyle(fontSize: 16),
),
const SizedBox(height: 8),
Text(
'Duration: $_duration seconds',
style: const TextStyle(fontSize: 16, color: Colors.red),
),
],
),
const SizedBox(height: 16),
Visibility(
visible: !_isVideoCompressed,
child: StreamBuilder<double>(
stream: _lightCompressor.onProgressUpdated,
builder: (BuildContext context,
AsyncSnapshot<dynamic> snapshot) {
if (snapshot.data != null && snapshot.data > 0) {
return Column(
children: [
LinearProgressIndicator(
minHeight: 8,
value: snapshot.data / 100,
),
const SizedBox(height: 8),
Text(
'${snapshot.data.toStringAsFixed(0)}%',
style: const TextStyle(fontSize: 20),
)
],
);
}
return const SizedBox.shrink();
},
),
),
const SizedBox(height: 24),
if (_displayedFile != null)
Builder(
builder: (BuildContext context) => Container(
alignment: Alignment.center,
child: OutlinedButton(
onPressed: () => Navigator.push<dynamic>(
context,
MaterialPageRoute<dynamic>(
builder: (_) => VideoPlayerScreen(_desFile),
),
),
child: const Text('Play Video')),
),
),
Text(
_failureMessage ?? '',
)
],
),
),
floatingActionButton: FloatingActionButton.extended(
onPressed: () => _pickVideo(),
label: const Text('Pick Video'),
icon: const Icon(Icons.video_library),
backgroundColor: const Color(0xFFA52A2A),
),
),
);
// Pick a video form device's storage
Future<void> _pickVideo() async {
_isVideoCompressed = false;
final FilePickerResult? result = await FilePicker.platform.pickFiles(
type: FileType.video,
);
final PlatformFile? file = result?.files.first;
if (file == null) {
return;
}
_filePath = file.path;
setState(() {
_failureMessage = null;
});
final String videoName =
'MyVideo-${DateTime.now().millisecondsSinceEpoch}.mp4';
final Stopwatch stopwatch = Stopwatch()..start();
final Result response = await _lightCompressor.compressVideo(
path: _filePath!,
videoQuality: VideoQuality.medium,
isMinBitrateCheckEnabled: false,
video: Video(videoName: videoName),
android: AndroidConfig(isSharedStorage: true, saveAt: SaveAt.Movies),
ios: IOSConfig(saveInGallery: false),
);
stopwatch.stop();
final Duration duration =
Duration(milliseconds: stopwatch.elapsedMilliseconds);
_duration = duration.inSeconds;
if (response is OnSuccess) {
setState(() {
_desFile = response.destinationPath;
_displayedFile = _desFile;
_isVideoCompressed = true;
});
} else if (response is OnFailure) {
setState(() {
_failureMessage = response.message;
});
} else if (response is OnCancelled) {
print(response.isCancelled);
}
}
String _getVideoSize({required File file}) =>
formatBytes(file.lengthSync(), 2);
}
// Helper function to format bytes into human-readable format
String formatBytes(int bytes, int decimals) {
if (bytes <= 0) return "0 B";
const suffixes = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
var i = (log(bytes) / log(1024)).floor();
return ((bytes / pow(1024, i)).toStringAsFixed(decimals)) + ' ' + suffixes[i];
}
主要功能
- 选择视频:通过
FilePicker
从设备存储中选择视频。 - 压缩视频:调用
compressVideo
方法进行视频压缩,支持多种压缩质量选项。 - 显示进度:使用
StreamBuilder
实时显示压缩进度。 - 取消压缩:提供按钮以取消正在进行的压缩操作。
- 结果显示:压缩完成后显示原始和压缩后的文件大小及压缩时间,并提供播放压缩后视频的功能。
兼容性
- Android SDK:最低API级别为24。
- iOS:最低版本为11。
- macOS:最低版本为10.15。
报告问题
如果您遇到任何问题,请提供以下信息以便更好地帮助您:
- 设备名称
- Android版本
- 是否可以在样本应用程序中重现问题
希望这个指南能帮助您顺利使用light_compressor
插件进行视频压缩!如果有任何疑问或需要进一步的帮助,请随时提问。
更多关于Flutter图片压缩插件light_compressor的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter图片压缩插件light_compressor的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter项目中使用light_compressor
插件进行图片压缩的示例代码。这个插件可以帮助你有效地压缩图片,减少其文件大小,而不显著影响图片质量。
首先,你需要在pubspec.yaml
文件中添加light_compressor
依赖项:
dependencies:
flutter:
sdk: flutter
light_compressor: ^latest_version # 请替换为最新版本号
然后,运行flutter pub get
来安装依赖。
接下来,你可以在你的Flutter项目中使用light_compressor
进行图片压缩。以下是一个完整的示例,包括从设备图库中选择图片、进行压缩并显示压缩后的图片:
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:light_compressor/light_compressor.dart';
import 'dart:typed_data/uint8list.dart';
import 'dart:io';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: ImageCompressionScreen(),
);
}
}
class ImageCompressionScreen extends StatefulWidget {
@override
_ImageCompressionScreenState createState() => _ImageCompressionScreenState();
}
class _ImageCompressionScreenState extends State<ImageCompressionScreen> {
File? _imageFile;
File? _compressedImageFile;
final ImagePicker _picker = ImagePicker();
Future<void> _pickImage() async {
final pickedFile = await _picker.pickImage(source: ImageSource.gallery);
if (pickedFile != null) {
setState(() {
_imageFile = File(pickedFile.path);
});
_compressImage();
}
}
Future<void> _compressImage() async {
if (_imageFile != null) {
Uint8List? imageBytes = await _imageFile!.readAsBytes();
if (imageBytes != null) {
Uint8List compressedImageBytes = await LightCompressor.compressImage(
imageBytes,
quality: 80, // 质量(0-100),值越低,压缩率越高,但质量越低
);
File compressedImageFile = File('${_imageFile!.path}.jpg')
..writeAsBytesSync(compressedImageBytes);
setState(() {
_compressedImageFile = compressedImageFile;
});
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Image Compression with light_compressor'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_imageFile != null
? Image.file(
_compressedImageFile ?? _imageFile!,
width: 300,
height: 300,
)
: Container(),
SizedBox(height: 20),
ElevatedButton(
onPressed: _pickImage,
child: Text('Pick Image'),
),
],
),
),
);
}
}
在这个示例中,我们做了以下几件事:
- 使用
image_picker
插件从设备图库中选择图片。 - 使用
light_compressor
插件压缩选择的图片。 - 显示原始图片(如果压缩后的图片尚未生成)或压缩后的图片。
注意:
- 你需要在
android/app/src/main/AndroidManifest.xml
中添加必要的权限来访问图库。 light_compressor
插件支持多种图片格式(如JPEG、PNG等),但在这个示例中,为了简单起见,我们假设压缩后的图片为JPEG格式,并添加了一个.jpg
扩展名。在实际应用中,你可能需要根据原始图片格式动态调整输出文件的扩展名。
希望这个示例能帮你顺利地在Flutter项目中使用light_compressor
插件进行图片压缩。