Flutter标签解析插件taglib_ffi_dart的使用
Flutter标签解析插件taglib_ffi_dart的使用
概述
taglib_ffi_dart 是一个基于 TagLib 的 Dart/Flutter 插件,用于管理和解析音频文件的元数据标签。它支持多种音频格式,并允许读取和写入标签信息。
当前状态
- 工作状态:插件目前处于开发阶段(WIP),API 可能会随版本更新而发生变化。
- 测试平台:已在 Android 和 Linux 平台上进行了测试。
使用方法
1. 添加依赖
在 pubspec.yaml 文件中添加以下依赖:
dependencies:
taglib_ffi_dart: current_version
taglib_ffi_dart_libs: current_version
然后运行 dart pub get 来安装依赖。
示例代码
以下是一个完整的 Flutter 示例,展示如何使用 taglib_ffi_dart 插件来读取音频文件的元数据。
代码实现
import 'dart:async';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:taglib_ffi_dart/taglib_ffi_dart.dart' as taglib;
Future<void> main() async {
await taglib.initialize(); // 初始化插件
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final formKey = GlobalKey<FormState>();
final titleC = TextEditingController();
final artistC = TextEditingController();
final albumC = TextEditingController();
final trackC = TextEditingController();
final yearC = TextEditingController();
final genreC = TextEditingController();
final commentC = TextEditingController();
final sampleRateC = TextEditingController();
final bitrateC = TextEditingController();
final channelsC = TextEditingController();
final lengthC = TextEditingController();
final lyricsC = TextEditingController();
Uint8List? albumCoverData;
@override
void initState() {
super.initState();
}
// 读取音频文件的元数据
Future<void> readMetadataFromFile() async {
FilePickerResult? result = await FilePicker.platform.pickFiles();
if (result == null) {
return;
}
final filePath = result.files.single.path;
if (filePath == null) {
return;
}
// 获取元数据
taglib.Metadata? metaData;
try {
metaData = await taglib.readMetadata(filePath);
} on PlatformException {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Failed to read metadata: $PlatformException'),
),
);
return;
}
setState(() {
if (metaData == null) {
return;
}
titleC.text = metaData.title ?? '';
artistC.text = metaData.artist ?? '';
albumC.text = metaData.album ?? '';
trackC.text = metaData.track == 0 ? '' : metaData.track.toString();
yearC.text = metaData.year == 0 ? '' : metaData.year.toString();
genreC.text = metaData.genre ?? '';
commentC.text = metaData.comment ?? '';
sampleRateC.text =
metaData.sampleRate == 0 ? '' : metaData.sampleRate.toString();
bitrateC.text = metaData.bitrate == 0 ? '' : metaData.bitrate.toString();
channelsC.text =
metaData.channels == 0 ? '' : metaData.channels.toString();
lengthC.text = metaData.length == 0 ? '' : metaData.length.toString();
lyricsC.text = metaData.lyrics ?? '';
albumCoverData = metaData.albumCover;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('taglib_ffi_dart 示例应用'),
),
body: Scrollbar(
child: SingleChildScrollView(
primary: true,
child: Padding(
padding: const EdgeInsets.all(15),
child: Form(
key: formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
// 显示专辑封面
if (albumCoverData != null) Image.memory(albumCoverData!),
TextFormField(
autofocus: false,
controller: titleC,
decoration: const InputDecoration(
labelText: '标题',
),
),
TextFormField(
autofocus: false,
controller: artistC,
decoration: const InputDecoration(
labelText: '艺术家',
),
),
TextFormField(
autofocus: false,
controller: albumC,
decoration: const InputDecoration(
labelText: '专辑',
),
),
TextFormField(
autofocus: false,
controller: trackC,
decoration: const InputDecoration(
labelText: '轨道号',
),
),
TextFormField(
autofocus: false,
controller: yearC,
decoration: const InputDecoration(
labelText: '年份',
),
),
TextFormField(
autofocus: false,
controller: genreC,
decoration: const InputDecoration(
labelText: '流派',
),
),
TextFormField(
autofocus: false,
controller: commentC,
decoration: const InputDecoration(
labelText: '评论',
),
minLines: 1,
maxLines: 10,
),
TextFormField(
autofocus: false,
controller: sampleRateC,
decoration: const InputDecoration(
labelText: '采样率 (kHz)',
),
),
TextFormField(
autofocus: false,
controller: bitrateC,
decoration: const InputDecoration(
labelText: '比特率 (kbps)',
),
),
TextFormField(
autofocus: false,
controller: channelsC,
decoration: const InputDecoration(
labelText: '声道数',
),
),
TextFormField(
autofocus: false,
controller: lengthC,
decoration: const InputDecoration(
labelText: '时长 (秒)',
),
),
TextFormField(
autofocus: false,
controller: lyricsC,
decoration: const InputDecoration(
labelText: '歌词',
),
minLines: 1,
maxLines: 20,
)
],
),
),
),
),
),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () async {
await readMetadataFromFile(); // 点击按钮时读取文件元数据
},
),
),
);
}
}
功能说明
-
初始化插件: 在
main()函数中调用taglib.initialize()初始化插件。 -
读取文件: 使用
FilePicker提供的pickFiles()方法让用户选择音频文件。 -
解析元数据: 调用
taglib.readMetadata(filePath)获取音频文件的元数据。 -
显示结果: 将解析出的元数据显示在表单中,包括标题、艺术家、专辑、轨道号等信息。
-
专辑封面: 如果音频文件包含专辑封面图像,则通过
Uint8List显示。
平台支持
| 平台 | 支持情况 |
|---|---|
| Android | ✅ |
| iOS | ❌ |
| Linux | ✅ |
| macOS | ❌ |
| Windows | ❌ (即将支持) |
格式支持
| 格式 | 标签类型 | 读取支持 | 写入支持 |
|---|---|---|---|
| mp3 | Id3v2 | ✔️ | ❌ |
| flac | Vorbis | ❌ | ❌ |
| ape | APEv2 | ❌ | ❌ |
| wma | ASF | ❌ | ❌ |
| dsd/dsf | Id3v2 | ❌ | ❌ |
| wav | RIFF | ❌ | ❌ |
标签支持
| 标签 | 支持情况 |
|---|---|
| 标题 | ✅ |
| 艺术家 | ✅ |
| 专辑 | ✅ |
| 专辑艺术家 | ✅ |
| 轨道号 | ✅ |
| 专辑总轨道数 | ✅ |
| 年份 | ✅ |
| 流派 | ✅ |
| 评论 | ✅ |
| 采样率 | ✅ |
| 比特率 | ✅ |
| 声道数 | ✅ |
| 时长 | ✅ |
| 歌词 | ✅ |
| 专辑封面图像 | ✅ |
| 多张封面图像 | ❌ |
| 自定义标签 | ❌ |
构建方式
1. 所有平台
首先生成绑定代码:
dart pub get
dart run ffigen --config ffigen.yaml
2. Android
export ANDROID_HOME=/path/to/Android/SDK
cd packages
./taglib_ffi_dart/scripts/build_android.sh ./taglib_ffi_dart_libs/android/src/main/jniLibs
3. Linux
./taglib_ffi_dart/scripts/build_linux.sh ./taglib_ffi_dart_libs/linux
更多关于Flutter标签解析插件taglib_ffi_dart的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter标签解析插件taglib_ffi_dart的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
taglib_ffi_dart 是一个 Flutter 插件,用于解析和编辑音频文件的元数据(如 ID3 标签、MP3 标签等)。它基于 TagLib 库,并通过 Dart 的 FFI(Foreign Function Interface)与原生代码进行交互。
以下是使用 taglib_ffi_dart 插件的基本步骤:
1. 添加依赖
首先,在 pubspec.yaml 文件中添加 taglib_ffi_dart 插件的依赖:
dependencies:
flutter:
sdk: flutter
taglib_ffi_dart: ^0.1.0 # 请使用最新版本
然后运行 flutter pub get 来安装依赖。
2. 导入包
在你的 Dart 文件中导入 taglib_ffi_dart 包:
import 'package:taglib_ffi_dart/taglib_ffi_dart.dart';
3. 使用插件
你可以使用 TagLib 类来读取和编辑音频文件的元数据。
读取标签
void readTags() async {
final tagLib = TagLib();
// 打开音频文件
final file = await tagLib.openFile('path/to/your/audiofile.mp3');
// 读取标签
final title = file.title;
final artist = file.artist;
final album = file.album;
final year = file.year;
final comment = file.comment;
final genre = file.genre;
final track = file.track;
print('Title: $title');
print('Artist: $artist');
print('Album: $album');
print('Year: $year');
print('Comment: $comment');
print('Genre: $genre');
print('Track: $track');
// 关闭文件
file.close();
}
编辑标签
void editTags() async {
final tagLib = TagLib();
// 打开音频文件
final file = await tagLib.openFile('path/to/your/audiofile.mp3');
// 编辑标签
file.title = 'New Title';
file.artist = 'New Artist';
file.album = 'New Album';
file.year = 2023;
file.comment = 'New Comment';
file.genre = 'New Genre';
file.track = 1;
// 保存更改
file.save();
// 关闭文件
file.close();
}
4. 处理异常
在使用 taglib_ffi_dart 时,可能会遇到文件无法打开或标签无法读取的情况。因此,建议在处理这些操作时添加异常处理:
void readTagsSafely() async {
final tagLib = TagLib();
try {
final file = await tagLib.openFile('path/to/your/audiofile.mp3');
print('Title: ${file.title}');
file.close();
} catch (e) {
print('Error reading tags: $e');
}
}

