Node.js/Electron中读写MP3的ID3-v2.4元数据(解决GEOB丢失问题)
解决Electron中读写ID3-v2.4元数据并保留GEOB的方案
一、使用支持GEOB保留的NPM库
1. music-metadata
这是一个成熟的元数据处理库,原生支持ID3-v2.4,并且默认提供保留未修改帧的选项,能完美保留GEOB数据,API设计友好,适配Electron环境:
const mm = require('music-metadata'); const fs = require('fs').promises; // 读取包含GEOB的元数据 async function readMp3Metadata(filePath) { const metadata = await mm.parseFile(filePath); // 提取ID3v2.4中的GEOB帧 const geobFrames = metadata.native['ID3v2.4']?.filter(frame => frame.id === 'GEOB'); if (geobFrames) { console.log('已读取GEOB帧:', geobFrames.length); } return metadata.common; } // 修改标签并保留GEOB async function updateMp3Metadata(filePath, newTags) { // 先读取现有元数据,确保保留原始帧 const { common } = await mm.parseFile(filePath); // 合并新标签 const updatedCommon = { ...common, ...newTags }; // 写入时指定保留原始帧,同时指定ID3v2.4版本 const outputBuffer = await mm.writeToBuffer(filePath, updatedCommon, { id3v2Version: 4, preserve: true // 关键配置:保留未修改的所有帧(包括GEOB) }); await fs.writeFile(filePath, outputBuffer); }
2. node-id3-fixed
这是node-id3的社区修复分支,专门解决了原库写入时丢失GEOB的问题,API和原库完全兼容,直接替换即可使用:
const NodeID3 = require('node-id3-fixed'); // 读取元数据(包含GEOB) const originalTags = NodeID3.read('path/to/your.mp3'); console.log('原始GEOB数据:', originalTags.GEOB); // 修改标签并写入,不会清除GEOB NodeID3.write({ title: '更新后的标题', artist: '更新后的艺术家' }, 'path/to/your.mp3');
二、手动处理ID3帧(进阶方案)
如果现有库无法满足定制化需求,可以手动解析ID3-v2.4结构:
- 读取MP3文件的前10字节,解析ID3头部信息(版本、大小、标志)。
- 根据头部中的大小值,定位到ID3帧区域,遍历所有帧,提取GEOB帧并存储。
- 修改需要更新的标签帧后,将原始GEOB帧与修改后的帧重新拼接,写入回文件。
注意:需要处理ID3的同步安全整数编码/解码,以及帧头的标志位解析,适合对ID3格式有一定了解的开发者。
三、原node-id3库的临时修复
如果不想更换依赖,可以通过手动保留GEOB的方式临时解决:
const NodeID3 = require('node-id3'); function writeTagsWithGeobPreserve(filePath, newTags) { // 先读取原始标签,获取GEOB const originalTags = NodeID3.read(filePath); if (originalTags.GEOB) { // 将原始GEOB合并到新标签中 newTags.GEOB = originalTags.GEOB; } // 写入合并后的标签 NodeID3.write(newTags, filePath); }
这个方法的前提是原库能正确读取GEOB数据,若原库读取GEOB也存在问题,建议直接更换为node-id3-fixed。
内容的提问来源于stack exchange,提问作者Chamindu Vidyarathne
相关产品推荐
相关产品推荐

