Flutter标签管理插件taggy的使用

Flutter标签管理插件taggy的使用

概述

提供了简单但功能强大的API来读取、写入和转换音频标签(元数据)。

目录:

特性

  • 📖 阅读音频标签元数据。
  • 📝 写入音频标签。
  • ✂ 删除音频标签。
  • 🎶 支持多种文件格式:
    • MP3, MP4, FLAC等。

计划中的功能

  • 批处理:同时写入多个文件。
  • 编辑文件名:根据轨道标题添加重命名文件的选项。
  • TaggyFileResult:所有公共API应该返回一个通用结果;
    • TaggyFile 类型的值或 TaggyError 类型的错误。
  • 转换标签

开始使用

  • 安装包。
  • 阅读使用部分以探索Taggy的功能。
  • 更多详情:查看示例应用

安装

运行以下命令:

dart pub add taggy

使用

初始化

可以通过两种方式完成初始化:

  1. 第一种方法:

    import 'package:taggy/taggy.dart';
    
    void main(){
      Taggy.initializeFrom(DynamicLibrary.open('path/to/library.dll'));
    }
    
  2. 第二种方法:

    import 'package:taggy/taggy.dart';
    
    // 调用这个帮助函数,它会帮你加载库。
    Taggy.initializeFrom(getTaggyDylibFromDirectory('path/of/binaries/directory'));
    

关于TaggyFile

  • 它给我们提供了更多关于正在读取或写入文件的信息,除了标签列表之外,我们还可以得到:

    • 文件大小(字节)。
    • 文件类型:是否为FLAC、WAV、MPEG等。
    • AudioInfo,这是一个包含音频轨道属性的类型。
  • 可以通过调用 formatAsAString() 来格式化一个 TaggyFile 实例:

    TaggyFile: {
        size: 12494053 bytes ~ 12.2 MB,
        fileType: FileType.Mpeg
        primaryTagType: TagType.Id3v2,
        tags: {
        count: 1,
        items: 
          [ Tag(
                tagType: Id3v2,
                trackTitle: Fine Line,
                trackArtist: Eminem,
                trackNumber: 9,
                trackTotal: 1,
                discTotal: null,
                discNumber: null,
                album: SHADYXV,
                albumArtist: Various Artists,
                genre: null,
                language: null,
                year: null,
                recordingDate: null,
                originalReleaseDate: null,
                has lyrics: true,
                pictures: {
                  count: 1,
                  items: [ Picture(
                    picType: PictureType.CoverFront,
                    picData(Bytes): 168312,
                    mimeType: MimeType.Jpeg,
                    width: 1000,
                    height: 1000,
                    colorDepth: 24,
                    numColors: 0,
                    )],
                },
              ),
          ],
        },
        audio: AudioInfo(
        channelMask: 3,
        channels: 2,
        sampleRate: 44100,
        audioBitrate: 321,
        overallBitrate: 326,
        bitDepth: null,
        durationSec: 306,
        ),
    }
    

读取标签

  • 读取所有标签

    const path = 'path/to/audio/file.mp3';
    
    final TaggyFile taggyFile = await Taggy.readAll(path);
    // 使用getter,底层是[taggyFile.tags.firstOrNull]
    print(taggyFile.firstTagIfAny);
    
    // 或者轻松访问所有返回的标签
    for (var tag in taggyFile.tags) {
      print(tag.tagType);
    }
    
  • 读取主标签

    final path = 'path/to/audio/file.mp3';
    final TaggyFile taggyFile = await Taggy.readPrimary(path);
    
  • 读取任意标签

    readPrimary 类似,但返回的 TaggyFile.tags 可能为空。

    const path = 'path/to/audio/file.mp3';
    final TaggyFile taggyFile = await Taggy.readAny(path);
    
    // 你也可以使用 [formatAsString],我们仍然得到一个 [TaggyFile]。
    print(taggyFile.formatAsString());
    
    // 你可能想检查是否有任何标签
    final hasTags = taggyFile.tags.isNotEmpty;
    // 或使用getter
    final Tag? tag = taggyFile.firstTagIfAny;
    

写入标签

  • 关于指定 TagType

    创建新的 Tag 实例时需要指定 TagType。你可以:

    • 检查基于文件类型(扩展名)支持的 TagType。查看此表格
    • 使用函数 Taggy.writePrimary() 并传递一个 Tag,其类型为 TagType.FilePrimaryType,如下面的示例所示。

    示例创建新标签:

    Tag getTagInstance(TagType tagType){
      return Tag(
        tagType: tagType,
        album: 'Some Album',
        trackTitle: 'some Track',
        trackArtist: 'Some Artist',
        trackTotal: 10,
        trackNumber: 1,
        discNumber: 1,
        discTotal: 2,
        year: 2023,
        recordingDate: '1/3/2019',
        language: 'EN',
        pictures: [
          Picture(
            // 用零表示如何提供图片的数据。
            picData: Uint8List.fromList([0, 0, 0, 0]),
            mimeType: MimeType.Jpeg,
            picType: PictureType.CoverFront,
            width: 1000,
            height: 800,
          ),
        ],
      );
    }
    
  • 写入主标签

    final path = 'path/to/audio/file.mp3';
    
    final tagToWrite = getTagInstance(TagType.FilePrimaryType);
    
    final TaggyFile taggyFile = await Taggy.writePrimary(
      path: path, tag: tagToWrite, keepOthers: false);
    
    // 成功后,[taggyFile.tags] 将包含新添加的标签。
    // 注意:这个标签可能不包含 [tagToWrite] 的相同属性。
    final pTag = taggyFile.primaryTag;
    
  • 写入多个标签

    在大多数情况下,你会使用 Taggy.writePrimary() 添加/编辑音频标签元数据,但你也可以提供多个标签写入同一文件。

    final path = 'path/to/audio/file.mp3';
    
    final tags = [
      getTagInstance(TagType.FilePrimaryType),
      getTagInstance(TagType.Id3v1),
    ];
          
    final TaggyFile taggyFile = await Taggy.writeAll(
      path: path, tags: tags, overrideExistent: true);
    

删除标签

  • 删除特定标签

    你可以通过指定标签类型从文件中删除标签。

    final path = 'path/to/audio/file.mp3';
    
    // 要删除的标签类型
    final tagType = TagType.Ape;
      
    final TaggyFile taggyFile = await Taggy.removeTag(path: path, tagType: tagType);
    
  • 删除所有标签

    final path = 'path/to/audio/file.mp3';
    final TaggyFile taggyFile = await Taggy.removeAll(path: path);
      
    print(taggyFile.tags);
    // 输出是 []
    

反馈与贡献

  • 🐛 发现问题或遇到错误?请检查现有的问题或创建一个新的问题。
  • 💪 想要贡献?感谢您的参与!你可以先阅读贡献指南
  • 🙏 你也可以通过在仓库上 ⭐ 和在 Pub.dev 上 👍 表达你的喜爱。

致谢

示例代码

import 'dart:io';

import 'package:taggy/taggy.dart';
import 'package:path/path.dart' as p;

Future<void> main(List<String> args) async {
  // 初始化Taggy
  // 注意:如果你本地运行,你需要运行 `cargo build` 命令以便生成二进制文件
  Taggy.initializeFrom(getTaggyDylibFromDirectory('../../target/debug'));

  await readAllTags();

  await writeTag();
}

Future<void> writeTag() async {
  final tag = Tag(
    tagType: TagType.FilePrimaryType,
    trackTitle: 'Track Title',
    trackArtist: 'Track Artist',
    trackTotal: 10,
    trackNumber: 1,
    discNumber: 1,
    discTotal: 2,
    year: 2023,
    recordingDate: '1/3/2019',
    language: 'EN',
    pictures: [
      Picture(
        picData: File(_getImagePath()).readAsBytesSync(),
        mimeType: MimeType.Jpeg,
        picType: PictureType.CoverFront,
        width: 1000,
        height: 800,
      ),
    ],
  );
  final taggyFile = await Taggy.writePrimary(
    path: _getAudioSamplePath(),
    tag: tag,
    keepOthers: false,
  );
  assert(taggyFile.primaryTag?.trackTitle == tag.trackTitle);
  print('Tag was written successfully');
}

Future<void> readAllTags() async {
  final taggyFile = await Taggy.readAll(_getAudioSamplePath());
  // 使用 `taggyFile` 作为你所希望的
  final audioInfo = taggyFile.audio;
  final tags = taggyFile.tags;
  final trackDuration = taggyFile.duration;
  final fileType = taggyFile.fileType;
  final size = taggyFile.sizeInMB;
  print('audioInfo: $audioInfo');
  print('tags: $tags');
  print('fileType: $fileType');
  print('trackDuration: $trackDuration');
  print('size: $size');
}

/**
 * 辅助函数
 */

/// 返回音频文件路径
String _getAudioSamplePath() => p.join(_getAssetsDirPath(), 'sample.mp3');

String _getImagePath() => p.join(_getAssetsDirPath(), 'image.jpg');

String _getAssetsDirPath() {
  final dir = File(p.current).parent.absolute;
  final sep = p.separator;
  return p.join(dir.path, 'taggy${sep}example${sep}assets');
}

更多关于Flutter标签管理插件taggy的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter标签管理插件taggy的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


taggy 是一个用于 Flutter 的标签管理插件,它可以帮助你在应用中轻松管理和显示标签。通过 taggy,你可以创建、编辑、删除标签,并将它们与不同的实体(如文章、图片等)关联起来。以下是 taggy 插件的基本使用指南。

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 taggy 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  taggy: ^1.0.0  # 请使用最新版本

然后运行 flutter pub get 来安装依赖。

2. 初始化 Taggy

在你的应用中初始化 Taggy。通常可以在 main.dart 中进行初始化:

import 'package:flutter/material.dart';
import 'package:taggy/taggy.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Taggy.initialize();
  runApp(MyApp());
}

3. 创建标签

你可以使用 Taggy 创建新的标签。例如:

import 'package:taggy/taggy.dart';

Future<void> createTag() async {
  Tag tag = Tag(name: 'Flutter', color: Colors.blue);
  await Taggy.instance.createTag(tag);
}

4. 获取标签

你可以获取所有标签或根据条件获取特定标签:

Future<void> getTags() async {
  List<Tag> tags = await Taggy.instance.getAllTags();
  tags.forEach((tag) {
    print(tag.name);
  });
}

5. 更新标签

你可以更新已存在的标签:

Future<void> updateTag() async {
  Tag tag = Tag(id: 1, name: 'Dart', color: Colors.red);
  await Taggy.instance.updateTag(tag);
}

6. 删除标签

你可以删除标签:

Future<void> deleteTag() async {
  await Taggy.instance.deleteTag(1); // 通过 ID 删除标签
}

7. 关联标签

你可以将标签与实体关联起来。例如,将标签与文章关联:

Future<void> associateTagWithPost() async {
  int tagId = 1;
  int postId = 1;
  await Taggy.instance.associateTagWithEntity(tagId, postId, 'Post');
}

8. 获取关联的标签

你可以获取与特定实体关联的标签:

Future<void> getTagsForPost() async {
  int postId = 1;
  List<Tag> tags = await Taggy.instance.getTagsForEntity(postId, 'Post');
  tags.forEach((tag) {
    print(tag.name);
  });
}

9. 显示标签

在 UI 中显示标签,你可以使用 ChipWrap 来展示标签列表:

import 'package:flutter/material.dart';
import 'package:taggy/taggy.dart';

class TagList extends StatelessWidget {
  final List<Tag> tags;

  TagList({required this.tags});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Wrap(
      children: tags.map((tag) {
        return Chip(
          label: Text(tag.name),
          backgroundColor: tag.color,
        );
      }).toList(),
    );
  }
}

10. 完整示例

以下是一个简单的完整示例,展示如何使用 taggy 插件:

import 'package:flutter/material.dart';
import 'package:taggy/taggy.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Taggy.initialize();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Taggy Example')),
        body: TagExample(),
      ),
    );
  }
}

class TagExample extends StatefulWidget {
  [@override](/user/override)
  _TagExampleState createState() => _TagExampleState();
}

class _TagExampleState extends State<TagExample> {
  List<Tag> tags = [];

  [@override](/user/override)
  void initState() {
    super.initState();
    _loadTags();
  }

  Future<void> _loadTags() async {
    List<Tag> loadedTags = await Taggy.instance.getAllTags();
    setState(() {
      tags = loadedTags;
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Column(
      children: [
        ElevatedButton(
          onPressed: () async {
            Tag newTag = Tag(name: 'New Tag', color: Colors.green);
            await Taggy.instance.createTag(newTag);
            _loadTags();
          },
          child: Text('Add Tag'),
        ),
        TagList(tags: tags),
      ],
    );
  }
}

class TagList extends StatelessWidget {
  final List<Tag> tags;

  TagList({required this.tags});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Wrap(
      children: tags.map((tag) {
        return Chip(
          label: Text(tag.name),
          backgroundColor: tag.color,
        );
      }).toList(),
    );
  }
}
回到顶部