mp3tag.js is an open-sourced JavaScript library used to edit the metadata of audio files. It supports ID3v1, ID3v2.2, ID3v2.3, and ID3v2.4 tags for MP3 files, as well as ID3v2 tags in MP4/M4A/M4V/MOV containers (ID32 box), AIFF/AIFC files (ID3 chunk), and AAC/ADTS streams (prepended ID3v2).
Visit https://mp3tag.js.org to learn more about the library and view it in action through an editor. You can also explore the examples directory.
The website is also open-sourced and can be viewed at the gh-pages branch.
Features
- Read, write, and remove ID3 tags (Supports ID3v1, ID3v2.2, ID3v2.3, and ID3v2.4)
- Read and write ID3v2 tags in MP4/M4A/M4V/MOV containers (via ID32 box)
- Read and write ID3v2 tags in AIFF/AIFC files (via ID3 chunk)
- Read and write ID3v2 tags in AAC/ADTS streams (prepended ID3v2)
- Partial reading from Blob/File without loading entire file into memory
- Supports unsynchronisation
- Standards compliant. See ~~id3.org~~
Installation
You can download the ready-to-use script at GitHub releases or you can build your own by cloning this repository usinggit then build it.
git clone https://github.com/eidoriantan/mp3tag.js
cd ./mp3tag.js
npm install
npm run build
You can also install this package by using npm:
npm install --save mp3tag.js@latest
If you are using a browser, you can just install the library through a CDN:
<script src="https://cdn.jsdelivr.net/npm/mp3tag.js@latest/dist/mp3tag.min.js">
Usage
For browsers:
<input type="file" id="input-file" accept="audio/mpeg,audio/mp4,audio/x-m4a,audio/aiff,audio/aac">
<script>
const inputFile = document.getElementById('input-file')
inputFile.addEventListener('change', function () {
[...this.files].forEach(async (file) => {
const buffer = await file.arrayBuffer()
// MP3Tag Usage
const mp3tag = new MP3Tag(buffer)
mp3tag.read()
// Handle error if there's any
if (mp3tag.error !== '') throw new Error(mp3tag.error)
else console.log(mp3tag.tags)
})
})
</script>
<input type="file" id="input-file" accept="audio/mpeg,audio/mp4,audio/x-m4a,audio/aiff,audio/aac">
<script>
inputFile.addEventListener('change', function () {
const reader = new FileReader()
reader.onload = function () {
const buffer = this.result
// MP3Tag Usage
const mp3tag = new MP3Tag(buffer)
mp3tag.read()
// Handle error if there's any
if (mp3tag.error !== '') throw new Error(mp3tag.error)
else console.log(mp3tag.tags)
}
if (this.files.length > 0) {
reader.readAsArrayBuffer(this.files[0])
}
})
</script>
For Node.js:
const MP3Tag = require('mp3tag.js')
const fs = require('fs')
const buffer = fs.readFileSync('/path/to/audio.mp3')
const mp3tag = new MP3Tag(buffer)
mp3tag.read()
// Handle error if there's any
if (mp3tag.error !== '') throw new Error(mp3tag.error)
else console.log(mp3tag.tags)
import { openAsBlob } from 'node:fs'
import MP3Tag from 'mp3tag.js'
async function main () {
const blob = await openAsBlob('/path/to/audio.mp3')
const arrayBuffer = await blob.arrayBuffer()
const mp3tag = new MP3Tag(arrayBuffer)
mp3tag.read()
if (mp3tag.error !== '') throw new Error(mp3tag.error)
else console.log(mp3tag.tags)
}
main()
Partial reading with readBlob
For read-only scenarios, you can read the metadata without loading the entire
file into memory. MP3Tag.readBlob() accepts a
Blob (or File) and
uses blob.slice() to read only the bytes it needs.
In the browser:
<input type="file" id="input-file" accept="audio/mpeg,audio/mp4,audio/x-m4a,audio/aiff,audio/aac">
<script>
const inputFile = document.getElementById('input-file')
inputFile.addEventListener('change', async function () {
for (const file of this.files) {
// Only reads headers + tag data, not the entire file
const tags = await MP3Tag.readBlob(file)
console.log(tags.title, tags.artist)
}
})
</script>
In Node.js (requires Node 19.8+):
import { openAsBlob } from 'node:fs'
import MP3Tag from 'mp3tag.js'
const blob = await openAsBlob('/path/to/large-file.mp3')
const tags = await MP3Tag.readBlob(blob)
console.log(tags.title, tags.artist)
readBlob accepts the same options as read:
const tags = await MP3Tag.readBlob(blob, {
id3v1: true,
id3v2: true,
mp4: true,
aiff: true,
aac: true,
unsupported: false
})
MP4/M4A Support
mp3tag.js supports reading and writing ID3v2 tags embedded in MP4/M4A containers using the ID32 box format. The library automatically detects MP4 files and handles the container structure transparently.
const MP3Tag = require('mp3tag.js')
const fs = require('fs')
// Reading from MP4/M4A
const buffer = fs.readFileSync('/path/to/audio.m4a')
const mp3tag = new MP3Tag(buffer)
mp3tag.read()
if (mp3tag.error !== '') throw new Error(mp3tag.error)
console.log(mp3tag.tags.title) // Works the same as MP3
// Writing to MP4/M4A
mp3tag.tags.v2.TIT2 = 'New Title'
mp3tag.tags.v2.TPE1 = 'New Artist'
mp3tag.save({
id3v2: { padding: 0 },
mp4: { language: 'eng' } // Optional: ISO-639-2/T language code (default: 'und')
})
if (mp3tag.error !== '') throw new Error(mp3tag.error)
fs.writeFileSync('/path/to/audio.m4a', Buffer.from(mp3tag.buffer))
Note: MP4 support focuses on ID32 boxes containing ID3v2 data. Native iTunes metadata (ilst atoms) is not supported.
AIFF/AIFC Support
mp3tag.js supports reading and writing ID3v2 tags in AIFF and AIFC audio files. Tags are stored in an "ID3 " chunk within the AIFF container structure.
const MP3Tag = require('mp3tag.js')
const fs = require('fs')
// Reading from AIFF
const buffer = fs.readFileSync('/path/to/audio.aiff')
const mp3tag = new MP3Tag(buffer)
mp3tag.read()
if (mp3tag.error !== '') throw new Error(mp3tag.error)
console.log(mp3tag.tags.title) // Works the same as MP3
// Writing to AIFF
mp3tag.tags.v2.TIT2 = 'New Title'
mp3tag.tags.v2.TPE1 = 'New Artist'
mp3tag.save({ id3v2: { padding: 0 } }) // No padding recommended for AIFF
if (mp3tag.error !== '') throw new Error(mp3tag.error)
fs.writeFileSync('/path/to/audio.aiff', Buffer.from(mp3tag.buffer))
AAC/ADTS Support
mp3tag.js supports reading and writing ID3v2 tags in raw AAC/ADTS audio streams. Tags are prepended to the audio data, similar to MP3 files.
const MP3Tag = require('mp3tag.js')
const fs = require('fs')
// Reading from AAC
const buffer = fs.readFileSync('/path/to/audio.aac')
const mp3tag = new MP3Tag(buffer)
mp3tag.read()
if (mp3tag.error !== '') throw new Error(mp3tag.error)
console.log(mp3tag.tags.title) // Works the same as MP3
// Writing to AAC
mp3tag.tags.v2.TIT2 = 'New Title'
mp3tag.tags.v2.TPE1 = 'New Artist'
mp3tag.save({ id3v2: { padding: 1024, unsynch: true } }) // Unsync recommended for AAC
if (mp3tag.error !== '') throw new Error(mp3tag.error)
fs.writeFileSync('/path/to/audio.aac', Buffer.from(mp3tag.buffer))
Note: AAC support is for raw ADTS streams (.aac files). For AAC audio in MP4 containers (.m4a files), see the MP4/M4A Support section above.
Read Options
mp3tag.read({
id3v1: true, // Read ID3v1 tags (default: true)
id3v2: true, // Read ID3v2 tags (default: true)
mp4: true, // Detect and read from MP4 containers (default: true)
aiff: true, // Detect and read from AIFF containers (default: true)
aac: true, // Detect and read from AAC/ADTS streams (default: true)
unsupported: false // Parse unsupported frames as raw bytes (default: false)
})
Write Options
mp3tag.save({
strict: false, // Enable strict validation (default: false)
id3v1: {
include: false // Write ID3v1 tags (default: false)
},
id3v2: {
include: true, // Write ID3v2 tags (default: true)
version: 3, // ID3v2 version: 2, 3, or 4 (default: from source or 3)
padding: 2048, // Padding bytes after tags (default: 2048, use 0 for MP4)
unsynch: false, // Use unsynchronisation (default: false)
unsupported: false // Write unsupported frames (default: false)
},
mp4: {
language: 'und' // ISO-639-2/T language code for ID32 box (default: 'und')
}
})
If you want detailed documentation, please visit the documentations page at mp3tag.js.org.