【问题标题】:Reading ID3 Tags of MP3 Stored Online读取在线存储的 MP3 的 ID3 标签
【发布时间】:2014-07-01 16:38:42
【问题描述】:

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

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

【问题讨论】:

  • 嗯...您总是必须打开文件。对于在线存储的 MP3 文件...您必须创建一个 webrequest,获取响应流并从响应流中读取数据。
  • @thefiloe 它需要是整个文件吗?我正在使用 WebRequest 下载文件,但理想情况下,我想在实际保存文件之前获取文件的名称。我有 atm 的唯一解决方案是将文件另存为:`random_string.tmp',等到它被下载然后读取 ID3 标签。这将允许我在完成后将文件名更改为正确的标题。
  • 没有。由于 ID3v2 存储在开头,您应该可以只下载必要的部分。如果你幸运的话,标签库会为你处理。如果没有,您必须自己解析 ID3 标头,获取 ID3-Tag 的长度,下载必要的数据,从下载的数据创建内存流并将流传递到您的库。解析头部,你可以看看这个:cscore.codeplex.com/SourceControl/latest#CSCore/Tags/ID3/…

标签: c# .net mp3 id3 id3-tag


【解决方案1】:

正如 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) 文件的同步代码。只是他们忘记对 PNG 和 JPEG 图像中的0xFF 做点什么……反正……

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

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

重要提示:您应该确认没有在这些字节中设置第 7 位。如果设置,则它不是有效的 ID3 标签。这就是我不做 (buffer[pos + n] &amp; 0x7F) 的原因,如果您尽早正确验证大小,则不需要 &amp; 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 标头中请求的范围。

【讨论】:

    猜你喜欢
    • 2011-09-12
    • 1970-01-01
    • 1970-01-01
    • 2011-01-06
    • 2011-09-14
    • 1970-01-01
    • 1970-01-01
    • 2011-12-01
    • 1970-01-01
    相关资源
    最近更新 更多