
Cross-platform library for writing ID3 v2.3 tags to MP3 files, supporting byte array operations without reading or removing tags. Java compatibility with a builder interface.
A Kotlin Multiplatform library for write ID3 (v2.3) tag to MP3 files. Java Compatible. Currently, reading ID3 tags is not supported.
Online documentation: https://kingg22.github.io/vibrion-id3/
Disclaimer: This library was inspired on browser-id3-writer for JavaScript/Typescript.
A JavaScript library for writing ID3 tags in the browser. While this implementation was built from scratch in Kotlin Multiplatform and does not reuse code from that project, some implementation and core writer were adapted from it. Some tests use a tag built using it. Full credit to @egoroof for the original concept.
[!NOTE]
This library doesn't read, remove or scan byteArray, only generate the tag. You can use
Id3AudioWriter.removeTag(bytearray).This library works on byteArray, doesn't use files, stream, sink, or other formats. You can open an issue or PR to add a module.
implementation("io.github.kingg22:vibrion-id3:<current-version>")implementation 'io.github.kingg22:vibrion-id3:<current-version>'[versions]
vibrion-id3 = "<current-version>"
[libraries]
vibrion-id3 = { group = "io.github.kingg22", name = "vibrion-id3", version.ref = "vibrion-id3" }<dependency>
<groupId>io.github.kingg22</groupId>
<artifactId>vibrion-id3</artifactId>
<version>current-version</version>
</dependency>You required targets are not available? Please make a PR to add it or create an issue.
You need an Export annotation for specific target? Please make a PR to add it or create an issue.
Java inaccessible? Please create an issue with demonstration of the code. I try to make java-friendly.
Using verbose builder:
Kotlin:
val tag: ByteArray = Id3WriterBuilder.id3Writer {
title = "Song Title Example"
artist("Example Artist")
album = "Example Album"
length = 240_000 // 4 minutos en milisegundos
year = 2021
year = null // null is not considered to add frame but is permitted in builder
picture {
type = AttachedPictureType.CoverFront
data = byteArrayOf(0xFF.toByte(), 0xD8.toByte(), 0xFF.toByte()) // Data of image with mimeType JPEG
}
syncLyrics {
line("Just a simple line", timestamp = 1000)
line("Another line of lyrics", timestamp = 5000)
}
}.toByteArray()Java builder style:
final byte[] tag = Id3WriterBuilder.id3Writer()
.title("Título")
.artist("Artista")
.picture(new AttachedPictureBuilder().type(AttachedPictureType.CoverFront).data(new byte[]{
(byte) 0xFF, (byte) 0xD8, (byte) 0xFF
}))
.syncLyrics(new SynchronizedLyricsBuilder().line("a line", 1000).line("other line", 12343))
.toByteArray();Using direct frames and data:
Kotlin:
val writer = Id3AudioWriter()
writer[Id3v2v3TagFrame.TIT2] = "Title"
writer[Id3v2v3TagFrame.TPE1] = listOf("Eminem", "50 Cent")
// ⚠️ Advanced use only. May lead to invalid tag structure if not used carefully.
writer["IPLS"] = PairedTextFrame("key" to "value")
val tag: ByteArray = writer.build()Java:
class Id3BuilderJavaTest {
void testBuilderStyle() {
final var writer = new Id3AudioWriter();
// Need to call `.INSTANCE` because is a kotlin object.
writer.set(Id3v2v3TagFrame.TIT2.INSTANCE, "Title");
writer.set(Id3v2v3TagFrame.TPE1.INSTANCE, List.of("Eminem", "50 Cent"));
// ⚠️ Advanced use only. May lead to invalid tag structure if not used carefully.
// Java consumers don't need to use kotlin Pair, can use Map thinking is only for pair key-value
writer.set("IPLS", new PairedTextFrame(Map.of("key", value)));
final byte[] tag = writer.build();
}
}A specific frame is not supported and you require it? Please open a PR or create an issue to try to deliver it.
Grouped by type, where (name) is the type in code
Array of strings (StringListFrame):
Pairs of string (PairedTextFrame):
String (TextFrame):
URL (TextFrame):
Integer (IntegerFrame):
Object:
CommentFrame) (comments)UnsynchronisedLyrics) (unsychronised lyrics)SynchronizedLyrics) (synchronised lyrics)AttachedPicture) (attached picture)UserDefinedText) (user defined text)PrivateFrame) (private frame)UserDefinedText) (user defined url link)| Type | Name |
|---|---|
| 0 | Other |
| 1 | 32x32 pixels 'file icon' (PNG only) |
| 2 | Other file icon |
| 3 | Cover (front) |
| 4 | Cover (back) |
| 5 | Leaflet page |
| 6 | Media (e.g. label side of CD) |
| 7 | Lead artist/lead performer/soloist |
| 8 | Artist/performer |
| 9 | Conductor |
| 10 | Band/Orchestra |
| 11 | Composer |
| 12 | Lyricist/text writer |
| 13 | Recording location |
| 14 | During recording |
| 15 | During performance |
| 16 | Movie/video screen capture |
| 17 | A bright coloured fish |
| 18 | Illustration |
| 19 | Band/artist logotype |
| 20 | Publisher/Studio logotype |
| Type | Name |
|---|---|
| 0 | Other |
| 1 | Lyrics |
| 2 | Text transcription |
| 3 | Movement/part name (e.g. "Adagio") |
| 4 | Events (e.g. "Don Quijote enters the stage") |
| 5 | Chord (e.g. "Bb F Fsus") |
| 6 | Trivia/'pop up' information |
| Type | Name |
|---|---|
| 1 | Absolute time, 32 bit sized, using MPEG frames as unit |
| 2 | Absolute time, 32 bit sized, using milliseconds as unit |
This library is licensed under the MIT License. See LICENSE for details.
Found a bug or missing frame? Contributions are welcome!
For larger changes (breaking changes, adding features), please open an issue first to discuss ideas.
The library includes unit tests for core frames and encoding logic. See the tests folder for examples. Contributions with additional test coverage are welcome! Contribution for specific Java interop are really welcome!
A Kotlin Multiplatform library for write ID3 (v2.3) tag to MP3 files. Java Compatible. Currently, reading ID3 tags is not supported.
Online documentation: https://kingg22.github.io/vibrion-id3/
Disclaimer: This library was inspired on browser-id3-writer for JavaScript/Typescript.
A JavaScript library for writing ID3 tags in the browser. While this implementation was built from scratch in Kotlin Multiplatform and does not reuse code from that project, some implementation and core writer were adapted from it. Some tests use a tag built using it. Full credit to @egoroof for the original concept.
[!NOTE]
This library doesn't read, remove or scan byteArray, only generate the tag. You can use
Id3AudioWriter.removeTag(bytearray).This library works on byteArray, doesn't use files, stream, sink, or other formats. You can open an issue or PR to add a module.
implementation("io.github.kingg22:vibrion-id3:<current-version>")implementation 'io.github.kingg22:vibrion-id3:<current-version>'[versions]
vibrion-id3 = "<current-version>"
[libraries]
vibrion-id3 = { group = "io.github.kingg22", name = "vibrion-id3", version.ref = "vibrion-id3" }<dependency>
<groupId>io.github.kingg22</groupId>
<artifactId>vibrion-id3</artifactId>
<version>current-version</version>
</dependency>You required targets are not available? Please make a PR to add it or create an issue.
You need an Export annotation for specific target? Please make a PR to add it or create an issue.
Java inaccessible? Please create an issue with demonstration of the code. I try to make java-friendly.
Using verbose builder:
Kotlin:
val tag: ByteArray = Id3WriterBuilder.id3Writer {
title = "Song Title Example"
artist("Example Artist")
album = "Example Album"
length = 240_000 // 4 minutos en milisegundos
year = 2021
year = null // null is not considered to add frame but is permitted in builder
picture {
type = AttachedPictureType.CoverFront
data = byteArrayOf(0xFF.toByte(), 0xD8.toByte(), 0xFF.toByte()) // Data of image with mimeType JPEG
}
syncLyrics {
line("Just a simple line", timestamp = 1000)
line("Another line of lyrics", timestamp = 5000)
}
}.toByteArray()Java builder style:
final byte[] tag = Id3WriterBuilder.id3Writer()
.title("Título")
.artist("Artista")
.picture(new AttachedPictureBuilder().type(AttachedPictureType.CoverFront).data(new byte[]{
(byte) 0xFF, (byte) 0xD8, (byte) 0xFF
}))
.syncLyrics(new SynchronizedLyricsBuilder().line("a line", 1000).line("other line", 12343))
.toByteArray();Using direct frames and data:
Kotlin:
val writer = Id3AudioWriter()
writer[Id3v2v3TagFrame.TIT2] = "Title"
writer[Id3v2v3TagFrame.TPE1] = listOf("Eminem", "50 Cent")
// ⚠️ Advanced use only. May lead to invalid tag structure if not used carefully.
writer["IPLS"] = PairedTextFrame("key" to "value")
val tag: ByteArray = writer.build()Java:
class Id3BuilderJavaTest {
void testBuilderStyle() {
final var writer = new Id3AudioWriter();
// Need to call `.INSTANCE` because is a kotlin object.
writer.set(Id3v2v3TagFrame.TIT2.INSTANCE, "Title");
writer.set(Id3v2v3TagFrame.TPE1.INSTANCE, List.of("Eminem", "50 Cent"));
// ⚠️ Advanced use only. May lead to invalid tag structure if not used carefully.
// Java consumers don't need to use kotlin Pair, can use Map thinking is only for pair key-value
writer.set("IPLS", new PairedTextFrame(Map.of("key", value)));
final byte[] tag = writer.build();
}
}A specific frame is not supported and you require it? Please open a PR or create an issue to try to deliver it.
Grouped by type, where (name) is the type in code
Array of strings (StringListFrame):
Pairs of string (PairedTextFrame):
String (TextFrame):
URL (TextFrame):
Integer (IntegerFrame):
Object:
CommentFrame) (comments)UnsynchronisedLyrics) (unsychronised lyrics)SynchronizedLyrics) (synchronised lyrics)AttachedPicture) (attached picture)UserDefinedText) (user defined text)PrivateFrame) (private frame)UserDefinedText) (user defined url link)| Type | Name |
|---|---|
| 0 | Other |
| 1 | 32x32 pixels 'file icon' (PNG only) |
| 2 | Other file icon |
| 3 | Cover (front) |
| 4 | Cover (back) |
| 5 | Leaflet page |
| 6 | Media (e.g. label side of CD) |
| 7 | Lead artist/lead performer/soloist |
| 8 | Artist/performer |
| 9 | Conductor |
| 10 | Band/Orchestra |
| 11 | Composer |
| 12 | Lyricist/text writer |
| 13 | Recording location |
| 14 | During recording |
| 15 | During performance |
| 16 | Movie/video screen capture |
| 17 | A bright coloured fish |
| 18 | Illustration |
| 19 | Band/artist logotype |
| 20 | Publisher/Studio logotype |
| Type | Name |
|---|---|
| 0 | Other |
| 1 | Lyrics |
| 2 | Text transcription |
| 3 | Movement/part name (e.g. "Adagio") |
| 4 | Events (e.g. "Don Quijote enters the stage") |
| 5 | Chord (e.g. "Bb F Fsus") |
| 6 | Trivia/'pop up' information |
| Type | Name |
|---|---|
| 1 | Absolute time, 32 bit sized, using MPEG frames as unit |
| 2 | Absolute time, 32 bit sized, using milliseconds as unit |
This library is licensed under the MIT License. See LICENSE for details.
Found a bug or missing frame? Contributions are welcome!
For larger changes (breaking changes, adding features), please open an issue first to discuss ideas.
The library includes unit tests for core frames and encoding logic. See the tests folder for examples. Contributions with additional test coverage are welcome! Contribution for specific Java interop are really welcome!