- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个场景,我正在构建一个播客 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/
今天我在一个 Java 应用程序中看到了几种不同的加载文件的方法。 文件:/ 文件:// 文件:/// 这三个 URL 开头有什么区别?使用它们的首选方式是什么? 非常感谢 斯特凡 最佳答案 file
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我有一个 javascript 文件,并且在该方法中有一个“测试”方法,我喜欢调用 C# 函数。 c# 函数与 javascript 文件不在同一文件中。 它位于 .cs 文件中。那么我该如何管理 j
需要检查我使用的文件/目录的权限 //filePath = path of file/directory access denied by user ( in windows ) File fil
我在一个目录中有很多 java 文件,我想在我的 Intellij 项目中使用它。但是我不想每次开始一个新项目时都将 java 文件复制到我的项目中。 我知道我可以在 Visual Studio 和
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 这个问题似乎不是关于 a specific programming problem, a software
我有 3 个组件的 Twig 文件: 文件 1: {# content-here #} 文件 2: {{ title-here }} {# content-here #}
我得到了 mod_ldap.c 和 mod_authnz_ldap.c 文件。我需要使用 Linux 命令的 mod_ldap.so 和 mod_authnz_ldap.so 文件。 最佳答案 从 c
我想使用PIE在我的项目中使用 IE7。 但是我不明白的是,我只能在网络服务器上使用 .htc 文件吗? 我可以在没有网络服务器的情况下通过浏览器加载的本地页面中使用它吗? 我在 PIE 的文档中看到
我在 CI 管道中考虑这一点,我应该首先构建和测试我的应用程序,结果应该是一个 docker 镜像。 我想知道使用构建环境在构建服务器上构建然后运行测试是否更常见。也许为此使用构建脚本。最后只需将 j
using namespace std; struct WebSites { string siteName; int rank; string getSiteName() {
我是 Linux 新手,目前正在尝试使用 ginkgo USB-CAN 接口(interface) 的 API 编程功能。为了使用 C++ 对 API 进行编程,他们提供了库文件,其中包含三个带有 .
我刚学C语言,在实现一个程序时遇到了问题将 test.txt 文件作为程序的输入。 test.txt 文件的内容是: 1 30 30 40 50 60 2 40 30 50 60 60 3 30 20
如何连接两个tcpdump文件,使一个流量在文件中出现一个接一个?具体来说,我想“乘以”一个 tcpdump 文件,这样所有的 session 将一个接一个地按顺序重复几次。 最佳答案 mergeca
我有一个名为 input.MP4 的文件,它已损坏。它来自闭路电视摄像机。我什么都试过了,ffmpeg , VLC 转换,没有运气。但是,我使用了 mediainfo和 exiftool并提取以下信息
我想做什么? 我想提取 ISO 文件并编辑其中的文件,然后将其重新打包回 ISO 文件。 (正如你已经读过的) 我为什么要这样做? 我想开始修改 PSP ISO,为此我必须使用游戏资源、 Assets
给定一个 gzip 文件 Z,如果我将其解压缩为 Z',有什么办法可以重新压缩它以恢复完全相同的 gzip 文件 Z?在粗略阅读了 DEFLATE 格式后,我猜不会,因为任何给定的文件都可能在 DEF
我必须从数据库向我的邮件 ID 发送一封带有附件的邮件。 EXEC msdb.dbo.sp_send_dbmail @profile_name = 'Adventure Works Admin
我有一个大的 M4B 文件和一个 CUE 文件。我想将其拆分为多个 M4B 文件,或将其拆分为多个 MP3 文件(以前首选)。 我想在命令行中执行此操作(OS X,但如果需要可以使用 Linux),而
快速提问。我有一个没有实现文件的类的项目。 然后在 AppDelegate 我有: #import "AppDelegate.h" #import "SomeClass.h" @interface A
我是一名优秀的程序员,十分优秀!