gpt4 book ai didi

javascript - 添加 id3 标签 html5 文件系统 api

转载 作者:行者123 更新时间:2023-12-03 09:54:00 25 4
gpt4 key购买 nike

我有一个场景,我正在构建一个播客 Web 应用程序,允许收听和存储 .mp3 播客文件。

我正在尝试实现一个基本的网络界面,有人可以从客户端添加整个 id3 标签(该文件将存储在客户端本地:此客户端与每个人不同)客户端,但只是获取原始播客文件的人,最好没有任何 id3 标签)。然后,他在本地托管这一页面并添加正确的 id3 标记,然后将这些 .mp3 复制到 WebDav 文件夹中。

我确实知道编辑需要在服务器上完成,但如果这一切都可以在浏览器本地完成,那将非常有帮助。

当然,没有现成的库可以编辑文件,所以我决定使用 HTML5 文件系统 api,即将文件放入虚拟文件系统中,在那里进行编辑,然后将其复制回本地系统。 (用于复制有一个现成的库 FileSaver.js)。

我已经能够执行以下操作:1) 使用 webkitGetAsEntry 将拖放到拖放区的 mp3 文件与文件系统 api 相关联

2) 将此文件复制到文件系统 api。

部分代码如下:

function onDrop(e) 
{
e.preventDefault();
e.stopPropagation();

var items = e.dataTransfer.items;
var files = e.dataTransfer.files;

for (var i = 0, item; item = items[i]; ++i)
{
// Skip this one if we didn't get a file.
if (item.kind != 'file') {
continue;
}

var entry = item.webkitGetAsEntry();

if (entry.isFile)
{
// Copy the dropped entry into local filesystem.
entry.copyTo(cwd, null, function(copiedEntry) {
//setLoadingTxt({txt: DONE_MSG});
renderMp3Writer(entry);

我的困惑是如何添加整个 id3 标签? 。我现在迷失了,因为我不确定:

1) 我们可以通过 fileWriter 方法将整个 id3 标签添加到文件中吗?2)如果是的话,这将是二进制编辑还是如何? .

任何帮助都会很有用。尝试了下面的方法,但我猜我错了。

var blob1 = new Blob(['ID3hTIT2ga'], {type: 'audio/mp3'});
fileWriter.write(blob1);

最佳答案

您需要构建一个 ID3 缓冲区,然后创建一个足够大的缓冲区来容纳 ID3 和 MP3 文件,插入 ID3 并附加 MP3 数据。

为此,您需要 ID3 specification 并使用类型化数组和 DataView 来构建数组。

ID3整体结构定义如下(见上面的链接):

 +-----------------------------+
| Header (10 bytes) |
+-----------------------------+
| Extended Header |
| (variable length, OPTIONAL) |
+-----------------------------+
| Frames (variable length) |
+-----------------------------+
| Padding |
| (variable length, OPTIONAL) |
+-----------------------------+
| Footer (10 bytes, OPTIONAL) |
+-----------------------------+

此时缓冲区长度未知,因此您需要分步骤执行此操作。有多种方法可以做到这一点,您可以为每个字段构建小的缓冲区段,然后将它们汇总到一个缓冲区中。或者,您可以创建一个更大的缓冲区,您知道它可以容纳您想要包含的所有字段,并将字段的总和从该缓冲区复制到最后一个缓冲区。

后者往往更简单,并且当我们处理非常小的尺寸时,这可能是最好的方法(考虑到第一种方法中的每个片段都有其开销)。

所以您需要做的第一件事就是定义 header 。 header 的定义方式如下:

ID3v2/file identifier      "ID3"
ID3v2 version $04 00
ID3v2 flags %abcd0000 (note: bit-representation)
ID3v2 size 4 * %0xxxxxxx (note: bit-representation/mask)

ID3和版本是固定值(当然也存在其他版本,但我们以当前版本为准)。

您可以通过将它们设置为 0 来忽略大多数标志(如果不是全部)。但是请检查您的用例的文档,例如,如果您想使用扩展 header 。

尺寸定义:

The ID3v2 tag size is stored as a 32 bit synchsafe integer (section 6.2), making a total of 28 effective bits (representing up to 256MB).

The ID3v2 tag size is the sum of the byte length of the extended
header, the padding and the frames after unsynchronisation. If a
footer is present this equals to ('total size' - 20) bytes, otherwise ('total size' - 10) bytes.

如何构建缓冲区的示例。首先定义一个足够大的缓冲区来容纳所有数据以及 DataView:

var id3buffer = new ArrayBuffer(1024),    // 1kb "space"
view = new DataView(id3buffer);

DataView 默认为 big-endian,这是完美的,所以我们现在要做的就是将数据填充到它应该在的位置。我们可以创建一些辅助方法来帮助我们在编写的同时移动位置。 DataView 的位置是字节绑定(bind)的:

 var pos = 0;    // global start position

function setU8(value) {
view.setUint8(pos++, value)
}

function setU16(value) {
view.setUint16(pos, value);
pos += 2;
}

function setU32(value) {
view.setUint32(pos, value);
pos += 4;
}

等等。您可以让助手编写文本 unicode 字符串(例如,请参阅 TextEncoder)等等。

为了定义标题,我们可以写入“神奇”的单词ID3。您可以转换一个字符串,或者因为它只有 3 个字节,所以也可以直接写入。 ID3 = 0x494433(十六进制):

setU8(0x49);     // at pos 0
setU8(0x44); // at pos 1
setU8(0x33); // at pos 2

由于我们制作了包装器,因此我们无需担心缓冲区位置。

然后写入版本(根据规范v.2.4.0使用0x0400而不使用主要版本(2)):

setU16(0x0400);  // default is big-endian so this works

现在您可以继续使用标志和大小(请参阅规范)。

当 ID3 header 填满时,pos 现在将保存总长度。因此,为 ID3 标签和 MP3 缓冲区创建一个新缓冲区:

var mp3 = new ArrayBuffer(pos + mp3Buffer.byteLength),
view8 = new Uint8Array(mp3);

view8 View 将允许我们简单地复制到目的地:

// create a segment from the tag buffer that will fit target:
var segment = new Uint8Array(view.buffer, 0, n); // replace n with actual length
view8.set(segment, 0);
view8.set(mp3buffer, pos);

如果一切顺利,您现在就有了带有 ID3 标签的 MP3(请记住检查现有的 ID3 - 您需要扫描到结束)。

您现在可以将 ArrayBuffer 发送到服务器,或者转换为 IndexedDB 的 Blob,或者如果您想提供下载链接,则转换为对象 URL(此处未显示任何内容,因为答案超出了范围)。

这应该足以让您开始 - 正如所说,您需要研究规范。如果您不熟悉typed array ,也检查一下。

另请参阅网站 other resources (框架等)。

同步安全值

“MP3”文件使用以 11 位开头的帧,全部设置为 1。如果 header 的大小字段碰巧包含设置为 1 的 11 位,则解码器可能会错误地将其解释为声音数据。为了避免这种情况,使用同步安全整数的概念,确保每个字节的 MSB(最高有效位,位 7)始终设置为 0。对于 ID3,该位向左移动,下一个字节移动一位标记 4 次(因此是 4x %01111111)。

以下是如何使用 JavaScript 编码和解码同步安全整数(来自 Wikipedia C/C++ source):

// test values
var value = 0xfffffff,
sync = intToSyncsafe(value);
document.write("<pre>Original size: 0x" + value.toString(16) + "<br>");
document.write("Synch-safe : 0x" + sync.toString(16) + "<br>");
document.write("Decoded value: 0x" + syncsafeToInt(sync).toString(16) + "</pre>");


function intToSyncsafe(value) {
var out, mask = 0x7f;
while(mask ^ 0x7fffffff) {
out = value & ~mask;
out <<= 1;
out |= value & mask;
mask = ((mask + 1) << 8) - 1;
value = out;
}
return out
}

function syncsafeToInt(value) {
var out = 0, mask = 0x7F000000;
while (mask) {
out >>= 1;
out |= value & mask;
mask >>= 8;
}
return out;
}

对于上面演示中使用的示例值,同步安全值将显示如下位:&b01111111011111110111111101111111

关于javascript - 添加 id3 标签 html5 文件系统 api,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30794645/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com