2

是否可以在不实际下载整个文件的情况下读取在线存储的 MP3 的 ID3 标签?

我使用过 TagLib Sharp,但据我所知,您实际上必须打开文件才能读取 ID3 标签。

4

1 回答 1

0

正如 Florian 上面所说,您可以使用 HTTP 范围读取文件的一小部分并查看是否存在 ID3,然后读取标签的其余部分(如果存在/必要)。例如:

Range: bytes=0-65535

ID3 标签可能包含一个图像,所以它可能非常大(我见过一些是 500Kb)。但是,大多数有用的信息,例如标题、描述等,很可能会在前几个 Kb 中提供。根据您的连接(或预期的客户端连接),我会选择要下载的第一个 Kb 数。对于大多数连接来说,现在每天 64Kb 的速度都会非常快(也许 2014 年的速度会不那么快)。

请注意,整个文件的总大小也可能小于 64Kb。Range 请求应该仍然有效,只是它会返回文件大小。在这种情况下,您将永远不会发送第二个请求以获取更多数据。

带有 ID3 标签的 MP3 文件开头如下:

0x49 0x44 0x33                 ID3
0x03 0x00                      major.revision (2.0 or 3.0)
0x00                           flags
0xSS 0xSS 0xSS 0xSS            size

关于版本的说明:

  1. 标签是 ID3,3不是版本的一部分
  2. 第一个版本是2因为 MP3 已经具有一种TAG功能,并且被认为是版本1(并且1.1在某些条件下)。
  3. 目前,我没有看到除0. 这就是为什么我们将标签称为 ID3v1 ( TAG)、ID3v2 ( ID3+ 0x02) 和 ID3v3 ( ID3+ 0x03)。

0xSS代表大小。这是一个有趣的问题,因为在每个字节中只使用 7 位以避免0xFF哪个是​​ MP3 (MPEG) 文件的同步代码。只有他们忘记做一些关于0xFF在 PNG 和 JPEG 图像中发现的事情......无论如何......

计算大小的方法是这样的:

size = (buffer[pos + 6] << 21) +
       (buffer[pos + 7] << 14) +
       (buffer[pos + 8] <<  7) +
       (buffer[pos + 9] <<  0)

重要提示:您应该验证没有在这些字节中设置第 7 位。如果设置,则它不是有效的 ID3 标签。这就是我不做 ( buffer[pos + n] & 0x7F) 的原因,& 0x7F如果您及早正确验证了尺寸,则不需要该零件。

请注意,这size不包括标题的大小。所以请记住,标头有 10 个字节。

缓冲区的其余部分按组织。这些是 3 个字母、一个大小和该帧的数据,或者是 4 个字母、一个大小、标志和数据。每个帧的标头由版本(2 或 3)确定。

无论如何,一旦你有了它size,如果你想读取整个 ID3,你可以对 HTTP 服务器执行另一个 GET 并检索剩余的数据,如果前 64Kb(或你首先使用的任何大小)尚未大于或等于必要的大小。

Range: bytes=65536-<size + 10 - 1>

大小是 ID3 内的数据。+10 用于标题。-1 是因为 HTTP 范围是包容性的(不是大小,而是位置)。

重要说明:所有服务器都不接受Range标头。如果您可以控制并且您的服务器不支持范围请求,您可能需要考虑在服务器前面添加一个代理。nginx 在这方面真的很擅长。它可以缓存整个文件并仅返回 HTTP 标头中请求的范围。

于 2020-05-19T00:20:30.523 回答