-
Notifications
You must be signed in to change notification settings - Fork 1
Chapters
Hirdaya Shrestha edited this page Sep 14, 2026
·
1 revision
hAudiotagger supports reading and writing chapter markers (ID3v2 CHAP frames) for MP3 files. Chapters are commonly used for podcasts, audiobooks, and multi-part songs.
Chapters mark positions within an audio file with start and end times. They're used for:
- Podcasts — Mark segments, topics, or ads
- Audiobooks — Mark chapters or sections
- Multi-part songs — Mark movements or parts
- DJ mixes — Mark track transitions
final chapters = await Haudiotagger.getChapters('/path/to/song.mp3');
for (final ch in chapters) {
print('${ch.title}: ${ch.startMs}ms - ${ch.endMs}ms');
}await Haudiotagger.setChapters('/path/to/song.mp3', [
Chapter(title: 'Introduction', startMs: 0, endMs: 42000),
Chapter(title: 'Main Content', startMs: 42000, endMs: 180000),
Chapter(title: 'Outro', startMs: 180000, endMs: 240000),
]);await Haudiotagger.setChapters('/path/to/song.mp3', []);| Field | Type | Description |
|---|---|---|
title |
String |
Chapter name |
startMs |
int |
Start time in milliseconds |
endMs |
int |
End time in milliseconds |
// Read from bytes
final chapters = await Haudiotagger.getChaptersFromBytes(fileBytes);
// Write to bytes
final modified = await Haudiotagger.setChaptersFromBytes(fileBytes, chapters);import 'package:haudiotagger/haudiotagger.dart';
class PodcastPlayer {
final String audioPath;
List<Chapter> chapters = [];
PodcastPlayer(this.audioPath);
Future<void> loadChapters() async {
chapters = await Haudiotagger.getChapters(audioPath);
}
Chapter? getCurrentChapter(int positionMs) {
for (final ch in chapters) {
if (positionMs >= ch.startMs && positionMs < ch.endMs) {
return ch;
}
}
return null;
}
List<Chapter> getChapterList() {
return chapters.asMap().entries.map((entry) {
final i = entry.key;
final ch = entry.value;
final duration = Duration(milliseconds: ch.endMs - ch.startMs);
return Chapter(
title: '${i + 1}. ${ch.title} (${duration.inMinutes}m)',
startMs: ch.startMs,
endMs: ch.endMs,
);
}).toList();
}
}import 'package:haudiotagger/haudiotagger.dart';
List<Chapter> generateChapters(List<int> timecodes, List<String> titles) {
final chapters = <Chapter>[];
for (var i = 0; i < timecodes.length; i++) {
final startMs = timecodes[i];
final endMs = i < timecodes.length - 1
? timecodes[i + 1]
: startMs + 300000; // Default 5 minutes
chapters.add(Chapter(
title: titles[i],
startMs: startMs,
endMs: endMs,
));
}
return chapters;
}
// Usage
final chapters = generateChapters(
[0, 180000, 360000, 540000],
['Intro', 'Topic 1', 'Topic 2', 'Conclusion'],
);
await Haudiotagger.setChapters('/path/to/podcast.mp3', chapters);| Format | Support |
|---|---|
| MP3 (ID3v2) | Full read/write |
| FLAC | Not supported |
| MP4/M4A | Not supported |
| Ogg Vorbis | Not supported |
Note
Chapters are currently only supported for MP3 files using ID3v2 CHAP frames.
Made with ❤️ and 🦀 by Hirdaya Shrestha