-
Notifications
You must be signed in to change notification settings - Fork 1
Examples
Hirdaya Shrestha edited this page Sep 14, 2026
·
1 revision
Real-world examples showing how to use hAudiotagger for common tasks.
Read metadata from all audio files in a directory:
import 'dart:io';
import 'package:haudiotagger/haudiotagger.dart';
Future<List<Tag>> scanDirectory(String dirPath) async {
final tags = <Tag>[];
final dir = Directory(dirPath);
await for (final entity in dir.list(recursive: true)) {
if (entity is File && _isAudioFile(entity.path)) {
final tag = await Haudiotagger.read(entity.path);
if (tag != null) {
tags.add(tag);
}
}
}
return tags;
}
bool _isAudioFile(String path) {
final ext = path.split('.').last.toLowerCase();
return ['mp3', 'flac', 'm4a', 'ogg', 'opus', 'aac', 'wav'].contains(ext);
}Build a simple tag editor UI:
class TagEditor extends StatefulWidget {
final String filePath;
const TagEditor({required this.filePath});
@override
State<TagEditor> createState() => _TagEditorState();
}
class _TagEditorState extends State<TagEditor> {
Tag? _tag;
final _titleController = TextEditingController();
final _artistController = TextEditingController();
final _albumController = TextEditingController();
@override
void initState() {
super.initState();
_loadTag();
}
Future<void> _loadTag() async {
final tag = await Haudiotagger.read(widget.filePath);
setState(() {
_tag = tag;
_titleController.text = tag?.title ?? '';
_artistController.text = tag?.trackArtist ?? '';
_albumController.text = tag?.album ?? '';
});
}
Future<void> _saveTag() async {
if (_tag == null) return;
await Haudiotagger.update(widget.filePath, TagChanges(
title: _titleController.text,
trackArtist: _artistController.text,
album: _albumController.text,
));
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Tags saved')),
);
}
@override
Widget build(BuildContext context) {
return Column(
children: [
TextField(controller: _titleController, decoration: InputDecoration(labelText: 'Title')),
TextField(controller: _artistController, decoration: InputDecoration(labelText: 'Artist')),
TextField(controller: _albumController, decoration: InputDecoration(labelText: 'Album')),
ElevatedButton(onPressed: _saveTag, child: Text('Save')),
],
);
}
}Rename audio files based on their metadata:
import 'package:haudiotagger/haudiotagger.dart';
Future<void> renameFiles(List<String> paths) async {
for (final path in paths) {
final newPath = await Haudiotagger.rename(
path,
pattern: '{track} - {title}',
);
print('Renamed: $path → $newPath');
}
}Save embedded artwork to separate files:
import 'dart:io';
import 'package:haudiotagger/haudiotagger.dart';
Future<void> extractArtwork(String audioPath, String outputPath) async {
final pictures = await Haudiotagger.readPictures(audioPath);
if (pictures.isNotEmpty) {
final cover = pictures.firstWhere(
(p) => p.pictureType == PictureType.coverFront,
orElse: () => pictures.first,
);
final ext = cover.mimeType?.toString().split('/').last ?? 'jpg';
final file = File('$outputPath/cover.$ext');
await file.writeAsBytes(cover.bytes);
print('Artwork saved to ${file.path}');
}
}Read metadata from user-selected files on web:
import 'dart:typed_data';
import 'package:file_picker/file_picker.dart';
import 'package:haudiotagger/haudiotagger.dart';
Future<void> pickAndReadAudio() async {
final result = await FilePicker.platform.pickFiles(
type: FileType.audio,
);
if (result != null && result.files.first.bytes != null) {
final bytes = result.files.first.bytes!;
final tag = await Haudiotagger.readFromBytes(bytes);
if (tag != null) {
print('Title: ${tag.title}');
print('Artist: ${tag.trackArtist}');
}
}
}Check metadata quality before uploading:
import 'package:haudiotagger/haudiotagger.dart';
Future<void> validateForUpload(String filePath) async {
final result = await Haudiotagger.validate(filePath);
if (!result.isValid) {
print('Issues found:');
for (final issue in result.issues) {
final icon = issue.severity == ValidationSeverity.error ? '❌' : '⚠️';
print('$icon ${issue.field}: ${issue.message}');
}
} else {
print('✓ Metadata is valid');
}
}Clean up metadata across a music library:
import 'package:haudiotagger/haudiotagger.dart';
Future<void> normalizeLibrary(List<String> paths) async {
final pipeline = TagPipeline()
..trimWhitespace()
..normalizeWhitespace()
..normalizeUnicode()
..removeEmptyFields();
await pipeline.process(paths);
print('Library normalized');
}Access MusicBrainz IDs, ISRC codes, and other professional metadata:
import 'package:haudiotagger/haudiotagger.dart';
Future<void> readExtendedInfo(String filePath) async {
final ext = await Haudiotagger.getExtended(filePath);
print('ISRC: ${ext.isrc}');
print('MusicBrainz Recording ID: ${ext.musicBrainzRecordingId}');
print('AcoustID: ${ext.acoustId}');
print('Mood: ${ext.mood}');
print('Catalog Number: ${ext.catalogNumber}');
print('Barcode: ${ext.barcode}');
}Transfer metadata from FLAC to MP3:
import 'package:haudiotagger/haudiotagger.dart';
Future<void> copyBetweenFormats(String flacPath, String mp3Path) async {
await Haudiotagger.copyMetadata(
flacPath,
mp3Path,
includeArtwork: true,
includeLyrics: true,
includeCustomTags: true,
);
print('Metadata copied from FLAC to MP3');
}When you only need one field, use readField for better performance:
import 'package:haudiotagger/haudiotagger.dart';
// Fast: only reads the title field
final title = await Haudiotagger.readField('/path/to/song.mp3', TagField.title);
// Slower: reads all metadata
final tag = await Haudiotagger.read('/path/to/song.mp3');
final title = tag?.title;Read and write chapter markers:
import 'package:haudiotagger/haudiotagger.dart';
Future<void> manageChapters(String filePath) async {
// Read existing chapters
final chapters = await Haudiotagger.getChapters(filePath);
for (final ch in chapters) {
print('${ch.title}: ${ch.startMs}ms - ${ch.endMs}ms');
}
// Write new chapters
await Haudiotagger.setChapters(filePath, [
Chapter(title: 'Intro', startMs: 0, endMs: 30000),
Chapter(title: 'Main Topic', startMs: 30000, endMs: 180000),
Chapter(title: 'Q&A', startMs: 180000, endMs: 240000),
Chapter(title: 'Outro', startMs: 240000, endMs: 250000),
]);
}Made with ❤️ and 🦀 by Hirdaya Shrestha