Skip to content

Examples

Hirdaya Shrestha edited this page Sep 14, 2026 · 1 revision

Real-world examples showing how to use hAudiotagger for common tasks.

Music Library App

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);
}

Tag Editor

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')),
      ],
    );
  }
}

Batch Rename Files

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');
  }
}

Extract Album Art

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}');
  }
}

Web App with File Picker

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}');
    }
  }
}

Validate Before Publishing

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');
  }
}

Normalize Metadata

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');
}

Read Extended Metadata

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}');
}

Copy Metadata Between Formats

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');
}

Read Single Field (Performance)

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;

Chapters for Podcasts

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),
  ]);
}

Clone this wiki locally