ID3元数据
MP3文件(可选)带有名为“ID3标记”的元数据:
ID3是MP3文件中元数据的事实标准
ID3v1增强型标签
-
id3v1标记占据128个字节,从文件末尾开始的字符串标记128个字节。
-
增强标记的长度为227字节,并放在ID3v1标记之前。
增强标记包含
start-time
和
end-time
字段作为标记的最后6+6字节,格式如下
MSM:SS
. 所以它给出了这首歌的持续时间。
解决方案是下载文件的最后355个字节,并检查增强标记(
TAG+
)存在,然后查找增强标记的最后12个字节。
ID3V2电缆
现在,我们主要使用
ID3V2
它允许我们嵌入高达256MB的信息:
ID3V2
标签由框架组成。每个帧代表一个信息。最大帧大小为16MB。最大标签大小为256MB。
你感兴趣的框架是
TLEN
帧,代表歌曲的长度。
但不能保证任何MP3文件都有id3v2标签,或者
泰伦
帧将存储在其ID3v2标记中。
!\!\!\
如果MP3文件不包含元数据,则唯一的解决方案是您已经提出的解决方案:使用
MP3持续时间
模块。
如何在不下载整个文件的情况下获取这些元数据?
范围请求
如果服务器接受
Range Request
,那么我们只需要告诉他我们想要的字节!
ID3V1
const request = require('request-promise');
const NodeID3 = require('node-id3');
const mp3FileURL = "http://musicSite/yourmp3File.mp3";
const mp3FileHEAD = await request.head(mp3FileURL);
const serverAcceptRangeReq = mp3FileHEAD.headers['Accept-Ranges'] && mp3FileHEAD.headers['Accept-Ranges'].toLowerCase() != "none";
// here we assume that the server accepts range requests
const mp3FileSize = mp3FileHEAD.headers['Content-Length'];
const tagBytesHeader = {'Range': `${mp3FileSize - 355}-${mp3FileSize}`};
const tagBytes = await request.get(mp3FileURL, {headers: tagBytesHeader});
!\
我没有测试代码,它只是作为一个演示
!\
然后分析响应并检查
tagBytes.includes('TAG+')
如果有,你就有你的持续时间。
ID3V2
您可以使用相同的方法检查id3v2标记是否在文件的开头,然后使用类似的模块
node-id3
分析标签。
获取检查ID3v2的请求
根据文件,
id3v2标记头[…]应该是文件中的第一个信息,为10个字节。
因此,即使服务器不接受范围请求,您也可以使用简单的GET请求提出解决方案,并在收到超过10个字节时“停止”它:
const request = require('request');
let buff = new Buffer(0);
const r = request
.get(mp3FileURL)
.on('data', chunk => {
buff = Buffer.concat([buff, chunk]);
if (buff.length > 10) {
r.abort();
// deal with your buff
}
});
});
!\
我没有测试代码,它只是作为一个演示
!\
将它包装在一个返回承诺的函数中会更干净。