是否可以在不实际下载整个文件的情况下读取在线存储的MP3的ID3标签?
我使用过TagLib Sharp,但据我所知,您实际上必须打开文件才能读取ID3标签。
如弗洛里安所说,您可以使用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
关于版本的注释:
- 标签是ID3,
3
不是版本的一部分- 第一个版本为
2
,因为MP3已经具有TAG
功能,并且被认为是版本1
(在某些情况下为1.1
)。- 目前,除
0
以外,我没有看到其他任何修订。这就是为什么我们将标记称为ID3v1(TAG
),ID3v2(ID3
+ 0x02)和ID3v3(ID3
+ 0x03)。
0xSS
代表尺寸。这很有趣,因为每个字节仅使用7位来避免0xFF
,它是MP3(MPEG)文件的同步代码。只有他们忘记对PNG和JPEG图像中的0xFF
进行处理...无论如何...
计算大小的方法是这样的:
您应该验证在那些字节中的任何一个中都没有设置位7。如果设置,则它不是有效的ID3标签。这就是为什么我不做(size = (buffer[pos + 6] << 21) + (buffer[pos + 7] << 14) + (buffer[pos + 8] << 7) + (buffer[pos + 9] << 0)
重要:
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标头中请求的范围。