Flutter媒体信息获取插件media_info的使用
Flutter媒体信息获取插件media_info的使用
插件概述
media_info
是一个用于确定音频、视频和照片属性的Flutter插件。根据底层平台的不同版本,会应用各种方法来获取字段。目前支持的属性包括:
- 宽度
- 高度
- 帧速率
- 持续时间(以毫秒为单位)
- MIME类型
- 轨道数量
此外,还可以生成缩略图。
示例代码
以下是一个完整的示例应用程序,展示了如何使用 media_info
插件来获取媒体文件的信息,并生成不同分辨率的缩略图。
import 'dart:async';
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
import 'package:media_info/media_info.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class Resolution {
const Resolution(this.w, this.h);
final int w;
final int h;
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is Resolution && other.w == w && other.h == h;
}
@override
int get hashCode => w.hashCode ^ h.hashCode;
}
const List<Resolution> _resolutions = [
Resolution(384, 216),
Resolution(512, 288),
Resolution(640, 360),
Resolution(768, 432),
Resolution(896, 504),
Resolution(1024, 576),
Resolution(1152, 648),
Resolution(1280, 720),
Resolution(1408, 792),
Resolution(1536, 864),
Resolution(1664, 936),
Resolution(1792, 1008),
Resolution(1920, 1080),
];
class _MyAppState extends State<MyApp> {
String? _file;
Map<String, dynamic>? _mediaInfoCache;
final Map<String, Future<String>> _thumbnails = <String, Future<String>>{};
final MediaInfo _mediaInfo = MediaInfo();
@override
Widget build(BuildContext context) {
return MaterialApp(
showPerformanceOverlay: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Media Info App'),
),
body: SafeArea(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Text(_file ?? 'Please select a file'),
Text(
(_mediaInfoCache?.keys ?? <String>[])
.map((String k) => '$k: ${_mediaInfoCache![k]}')
.join(',\n\n'),
style: Theme.of(context).textTheme.bodyText2,
),
Builder(
builder: (BuildContext context) {
if (_thumbnails.isEmpty) {
return const SizedBox();
}
final List<String> listW = _thumbnails.keys.toList();
listW.sort((a, b) {
final wA = int.parse(a.split('x').first);
final wB = int.parse(b.split('x').first);
return wA.compareTo(wB);
});
final List<Widget> widgets = <Widget>[];
for (final String res in listW) {
widgets.addAll([
Text(res),
FutureBuilder<String>(
future: _thumbnails[res],
builder: (BuildContext context, snapshot) {
if (snapshot.hasData) {
return Image.file(File(snapshot.data!));
}
if (snapshot.hasError) {
return Text(
'E: ${snapshot.error}',
style: TextStyle(color: Colors.red),
);
}
return const SizedBox();
},
),
Divider(),
]);
}
return Column(
mainAxisSize: MainAxisSize.min,
children: widgets,
);
},
),
],
),
),
),
),
floatingActionButton: _buildSelectButton(),
),
);
}
Widget _buildSelectButton() {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
FloatingActionButton(
key: Key("asset file"),
child: Icon(Icons.file_copy),
tooltip: 'Load Asset',
onPressed: _loadFromAsset,
),
SizedBox(width: 24),
FloatingActionButton(
key: Key("local file"),
child: Icon(Icons.attach_file),
onPressed: _selectFile,
),
SizedBox(width: 24),
FloatingActionButton(
key: Key("remote file"),
child: Icon(Icons.wifi),
onPressed: _loadRemoteFile,
),
],
);
}
void _loadFromAsset() async {
var dir = Directory.systemTemp.createTempSync();
var temp = File("${dir.path}/video.mp4")..createSync();
final bytes =
await rootBundle.load('assets/videos/pexels_videos_2268807.mp4');
temp.writeAsBytesSync(
bytes.buffer.asUint8List(bytes.offsetInBytes, bytes.lengthInBytes));
setState(() {
_file = temp.path;
_mediaInfoCache = null;
_thumbnails.clear();
});
_fetchFileDetails();
}
void _selectFile() async {
final FilePickerResult? mediaFile = await FilePicker.platform.pickFiles();
if (!mounted || mediaFile == null) {
return;
}
setState(() {
_file = mediaFile.files.single.path;
_mediaInfoCache = null;
_thumbnails.clear();
});
_fetchFileDetails();
}
void _fetchFileDetails() async {
final Map<String, dynamic> mediaInfo = await _mediaInfo.getMediaInfo(_file!);
if (!mounted || mediaInfo.isEmpty) {
return;
}
setState(() {
_mediaInfoCache = mediaInfo;
});
final Directory cacheDir = await getTemporaryDirectory();
final int cacheName = _file.hashCode;
final int w = mediaInfo['width'];
final int h = mediaInfo['height'];
final String mime = mediaInfo['mimeType'];
if (mime.startsWith("video/")) {
Set<Resolution> resolutions = Set();
resolutions.addAll(_resolutions);
resolutions.add(Resolution(w, h));
for (final Resolution res in resolutions) {
final String target = File('${cacheDir.path}/$cacheName.${res.w}.${res.h}').path;
if (File(target).existsSync()) {
File(target).deleteSync();
}
_thumbnails['${res.w}x${res.h}'] = _mediaInfo.generateThumbnail(
_file!,
target,
res.w,
res.h,
positionMs: 100,
);
}
}
setState(() {});
}
void _loadRemoteFile() async {
setState(() {
_file = "remote file";
_mediaInfoCache = null;
_thumbnails.clear();
});
Set<Resolution> resolutions = Set();
resolutions.add(Resolution(1280, 720));
final Directory cacheDir = await getTemporaryDirectory();
final int cacheName = _file.hashCode;
for (final Resolution res in resolutions) {
final String target = File('${cacheDir.path}/$cacheName.${res.w}').path;
if (File(target).existsSync()) {
File(target).deleteSync();
}
_thumbnails['${res.w}x${res.h}'] = _mediaInfo.generateThumbnail(
"https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4",
target,
res.w,
res.h,
positionMs: 5000,
);
}
setState(() {});
}
}
关键点解释
-
选择文件:通过
FloatingActionButton
提供了三种方式加载文件:- 从本地资源加载 (
_loadFromAsset
) - 从本地文件系统选择文件 (
_selectFile
) - 加载远程文件 (
_loadRemoteFile
)
- 从本地资源加载 (
-
获取媒体信息:
_fetchFileDetails
方法使用MediaInfo.getMediaInfo
获取媒体文件的详细信息,并将其存储在_mediaInfoCache
中。 -
生成缩略图:如果媒体文件是视频,则会根据预定义的分辨率列表生成缩略图,并将这些缩略图的生成任务存储在
_thumbnails
中。 -
显示信息:在界面上显示媒体文件的路径、详细信息以及生成的缩略图。
注意事项
- 确保在
pubspec.yaml
文件中添加了media_info
和其他依赖项。 - 如果需要处理远程文件,请确保网络权限已正确配置。
- 对于本地资源文件,确保在
pubspec.yaml
中正确配置了资源路径。
通过以上步骤,您可以轻松地使用 media_info
插件来获取媒体文件的详细信息并生成缩略图。希望这个示例能帮助您更好地理解和使用该插件。
更多关于Flutter媒体信息获取插件media_info的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter媒体信息获取插件media_info的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用media_info
插件来获取媒体信息的一个基本示例。这个插件允许你获取关于视频和音频文件的详细信息,比如时长、分辨率、比特率等。
首先,确保你的Flutter项目已经配置好,并且已经添加了media_info
插件。你可以在你的pubspec.yaml
文件中添加以下依赖:
dependencies:
flutter:
sdk: flutter
media_info: ^x.y.z # 请使用最新版本号替换x.y.z
然后运行flutter pub get
来安装依赖。
接下来是一个简单的示例代码,展示如何使用media_info
插件获取媒体信息:
import 'package:flutter/material.dart';
import 'package:media_info/media_info.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Media Info Example'),
),
body: Center(
child: MediaInfoExample(),
),
),
);
}
}
class MediaInfoExample extends StatefulWidget {
@override
_MediaInfoExampleState createState() => _MediaInfoExampleState();
}
class _MediaInfoExampleState extends State<MediaInfoExample> {
MediaInfo? mediaInfo;
String? errorMessage;
@override
void initState() {
super.initState();
_getMediaInfo('path/to/your/media/file.mp4');
}
Future<void> _getMediaInfo(String mediaPath) async {
try {
mediaInfo = await MediaInfo.fromFile(mediaPath);
setState(() {});
} catch (e) {
errorMessage = e.toString();
setState(() {});
}
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
if (errorMessage != null)
Text(
'Error: $errorMessage',
style: TextStyle(color: Colors.red),
),
if (mediaInfo != null)
Column(
children: <Widget>[
Text('Duration: ${mediaInfo!.duration} ms'),
Text('Width: ${mediaInfo!.width} px'),
Text('Height: ${mediaInfo!.height} px'),
Text('Bitrate: ${mediaInfo!.bitrate} bps'),
Text('Format: ${mediaInfo!.format}'),
// 根据需要添加更多信息
],
),
ElevatedButton(
onPressed: () {
// 重新获取媒体信息(例如,用于测试不同的文件路径)
// _getMediaInfo('path/to/another/media/file.mp3');
},
child: Text('Get Media Info'),
),
],
);
}
}
注意事项
- 文件路径:确保你提供的文件路径是正确的,并且该文件存在于你的设备或模拟器上。对于Android设备,你可能需要将文件放在应用的
files
目录中或使用适当的文件访问权限。 - 权限:对于访问设备上的文件,你可能需要在
AndroidManifest.xml
和Info.plist
中添加相应的权限声明。 - 错误处理:在实际应用中,添加更详细的错误处理逻辑,以应对各种可能的异常情况。
这个示例展示了如何使用media_info
插件来获取媒体文件的基本信息,并将其显示在Flutter应用的界面上。你可以根据具体需求进一步扩展这个示例。