Mp3tag.js
MP3 tagging library written in pure JavaScript for Node.js and browsers
Install / Use
/learn @eidoriantan/Mp3tag.jsREADME
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~~ mutagen-specs.readthedocs.io
Installation
You can download the ready-to-use script at
GitHub releases or you can
build your own by cloning this repository using git 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.
Support
If you had found a bug or any unexpected behavior, you can submit an issue through GitHub issues. If you want to contribute to this repository, please refer to CONTRIBUTING.md.
Related Skills
qqbot-channel
346.8kQQ 频道管理技能。查询频道列表、子频道、成员、发帖、公告、日程等操作。使用 qqbot_channel_api 工具代理 QQ 开放平台 HTTP 接口,自动处理 Token 鉴权。当用户需要查看频道、管理子频道、查询成员、发布帖子/公告/日程时使用。
docs-writer
100.1k`docs-writer` skill instructions As an expert technical writer and editor for the Gemini CLI project, you produce accurate, clear, and consistent documentation. When asked to write, edit, or revie
model-usage
346.8kUse CodexBar CLI local cost usage to summarize per-model usage for Codex or Claude, including the current (most recent) model or a full model breakdown. Trigger when asked for model-level usage/cost data from codexbar, or when you need a scriptable per-model summary from codexbar cost JSON.
Design
Campus Second-Hand Trading Platform \- General Design Document (v5.0 \- React Architecture \- Complete Final Version)1\. System Overall Design 1.1. Project Overview This project aims t

