Answers:
根据Youtube 2.0 API文档和3.0 API文档,videoId是一个字符串,关于当前使用的字符集未指定任何内容。
大约11个字符的长度,Youtube API小组的一则帖子说:
我没有在文档中看到任何地方正式承诺将11个字符的标准长度用于YouTube视频ID。这是我们当前实施的事情之一,并且可能会无限期地保持下去。但是我们没有为此提供任何官方承诺,因此风险自负。
最后但并非最不重要的一点是,另一篇文章阐明了(或没有)格式:
对于视频ID的格式,我们不做任何公开保证。尽管它们当前是包含字母,数字和标点符号的11个字符串,但我不建议您将其硬编码到您的应用程序中(除非您将来有一种简单的方法来对其进行更改)。
Youtube团队似乎更喜欢直接询问Youtube服务器Video_ID是否正确(请参阅现有视频):
如果您需要验证随机用户输入是否与有效的视频ID相对应,建议您进行经验测试。尝试访问
http://gdata.youtube.com/feeds/api/videos/VIDEO_ID
如果收到200响应,则VIDEO_ID有效。如果收到非200的响应,则您的ID无效。对于新上传的视频或私人视频,有些边缘情况,但是对于大多数目的,我认为这是可以的。
YouTube videoId和channelId标识符是单个整数值,以对Base64编码稍加修改的版本表示。与IETF RFC4648建议的不同之处在于,在编码字母中替换了两个字符:
Payload ASCII/Unicode Base64 YouTube
------- ------------- --------- ---------
0...25 \x41 ... \x5A 'A'...'Z' 'A'...'Z'
26...51 \x61 ... \x7A 'a'...'z' 'a'...'z'
52...61 \x30 ... \x39 '0'...'9' '0'...'9'
62 \x2F vs. \x2D → '/' (2F) '-' (2D)
63 \x2B vs. \x5F → '+' (2B) '_' (5F)
替换可能是由于以下事实:出于某种原因,RFC4648选择了两个字符,这些字符在URL中已经具有突出的和完善的功能。[注1.]显然,对于此处讨论的用法,最好避免这种特殊的并发症。
与官方规范的另一个区别是YouTube标识符不使用=
填充字符;没必要,因为每个解码后的整数大小所期望的编码长度是固定且已知的(分别针对64位和128位为11和22个编码的“数字”)。
除一个较小的例外(如下所述)外,可以从可公开访问的数据推断出Base64映射的完整细节。通过最少的猜测,videoId和channelId字符串中使用的Base64方案可能如下所示:
——₀————₁————₂————₃————₄————₅————₆————₇————₈————₉———₁₀———₁₁———₁₂———₁₃———₁₄———₁₅—
00ᴴ 01ᴴ 02ᴴ 03ᴴ 04ᴴ 05ᴴ 06ᴴ 07ᴴ 08ᴴ 09ᴴ 0Aᴴ 0Bᴴ 0Cᴴ 0Dᴴ 0Eᴴ 0Fᴴ
00→ 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
A B C D E F G H I J K L M N O P
—₁₆———₁₇———₁₈———₁₉———₂₀———₂₁———₂₂———₂₃———₂₄———₂₅———₂₆———₂₇———₂₈———₂₉———₃₀———₃₁—
10ᴴ 11ᴴ 12ᴴ 13ᴴ 14ᴴ 15ᴴ 16ᴴ 17ᴴ 18ᴴ 19ᴴ 1Aᴴ 1Bᴴ 1Cᴴ 1Dᴴ 1Eᴴ 1Fᴴ
01→ 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
Q R S T U V W X Y Z a b c d e f
—₃₂———₃₃———₃₄———₃₅———₃₆———₃₇———₃₈———₃₉———₄₀———₄₁———₄₂———₄₃———₄₄———₄₅———₄₆———₄₇—
20ᴴ 21ᴴ 22ᴴ 23ᴴ 24ᴴ 25ᴴ 26ᴴ 27ᴴ 28ᴴ 29ᴴ 2Aᴴ 2Bᴴ 2Cᴴ 2Dᴴ 2Eᴴ 2Fᴴ
10→ 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
g h i j k l m n o p q r s t u v
—₄₈———₄₉———₅₀———₅₁———₅₂———₅₃———₅₄———₅₅———₅₆———₅₇———₅₈———₅₉———₆₀———₆₁———₆₂———₆₃—
30ᴴ 31ᴴ 32ᴴ 33ᴴ 34ᴴ 35ᴴ 36ᴴ 37ᴴ 38ᴴ 39ᴴ 3Aᴴ 3Bᴴ 3Cᴴ 3Dᴴ 3Eᴴ 3Fᴴ
11→ 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
w x y z 0 1 2 3 4 5 6 7 8 9 - _
相信使用Base64的原因是,当我们假设编码器输入的标准整数大小分别为64位和128位时,Base64会准确预测YouTube channelId和videoId标识符的异常字符长度(11和22个字符)。此外,根据Base64计算得出的余数可以完美地解释在每种类型的标识符字符串的l founda̲s̲t̲ c̲h̲a̲r̲a̲c̲t̲e̲r̲中发现的观察到的分布变化。这些问题的讨论如下。
在这两种情况下,分别针对videoId和channelId进行Base64编码的二进制“数据”是64或128位的单个整数。因此,通过使用Base64解码器,可以从字符串标识符中恢复单个整数,并且这样做非常有用,因为尽管每个整数id都包含与Base64字符串完全相同的信息,并且还允许该字符串可以随时重新创建-与以Unicode形式存储的Base64字符串相比,二进制表示形式小63%,最大位密度为100%,在内存中的对齐方式更好,排序和散列处理更快,并且也许最重要的是,消除了仅在正交情况下不同的标识符之间的错误冲突。这最后一个问题,虽然极不可能的数字,但不能排除当Base64编码ID是不区分大小写处理,因为一些文件系统做(如视窗,可以追溯到DOS)。
这很重要:如果您将videoId / channelId字符串用作Windows / NTFS文件名的一部分,则由于文件系统部署了不区分大小写的路径和文件命名而导致文件名冲突的可能性微乎其微,但非零。
如果您担心这个遥远的问题,可以用数学方法消除它的一种方法是将解码后的整数(仍按本文所述获得)重新编码为10进制(十进制)或(均匀-十六进制表示形式,用于此类文件系统上的路径或文件名。[注2]。在这种方法中,64位videoId将需要20个十进制数字
[0-9]
或8个十六进制数字[0-9,A-F]
(相对于 11个Base64数字)。128位channelId最多需要39个十进制数字或16个十六进制数字(而 22个Base64数字)。
对于64位情况,解码为二进制很简单,因为您可以使用UInt64
(ulong
在C#中)保留返回的本机二进制值。
/// <summary> Recover the unique 64-bit value from an 11-character videoID </summary>
/// <remarks>
/// The method of padding shown here (i.e. 'b64pad') is provided to demonstrate the
/// full and correct padding requirement for Base64 in general. For our cases:
///
/// videoId → 11 chars → b64pad[11 % 3] → b64pad[2] → "="
/// channelId → 22-chars → b64pad[22 % 3] → b64pad[1] → "=="
///
/// Note however that, because it returns 'ulong', this function only works for videoId
/// values, and the padding will always end up being "=". This is assumed in the revised
/// version of this code given further below, by just hard-coding the value "=".
/// </remarks>
static ulong YtEnc_to_videoId(String ytId)
{
String b64 = ytId.Replace('-', '+').Replace('_', '/') + b64pad[ytId.Length % 3];
return BitConverter.ToUInt64(Convert.FromBase64String(b64), 0);
}
static String[] b64pad = { "", "==", "=" };
对于128位值,这有点棘手,因为除非编译器具有__int128
表示形式,否则您必须找出一种存储整个事物并在传递时保持组合状态的方法。一个简单的值类型(或System.Numerics.Vectors.Vector<T>
,如果可用,则显示为128位SIMD硬件寄存器)将在.NET中发挥作用(未显示)。
[ 编辑: ]
进一步的思考后,我原来的职位的一部分是不完整的最大。为了公平起见,保留了原始摘录(如果需要,您可以跳过它);我在下面立即解释缺少的见解:[ 原文: ]
上面您可能已经注意到我写过您可以恢复“ a ”整数。这不是最初编码的值吗?不必要。而且我并不是在暗示有符号/无符号的区别,这是真的,在这里无法确定(因为它不会改变有关二进制映像的任何事实)。它本身就是数值:没有一些“ Rosetta Stone”“,这样我们就可以对绝对值为“正确”的绝对值进行交叉检查,无法肯定地知道数字字母映射以及字节序,这意味着我们无法保证您会恢复与幸运的是,只要YouTube从未在其他地方公开以不太透明的格式公开所谓的正确值,那就没关系了。那是因为解码后的64位或128位值除了用作标识令牌外没有其他用途,因此我们对转换的唯一要求是不同的编码(没有两个唯一的令牌发生冲突)和可逆性(解码可恢复原始令牌标识)。
换句话说,我们真正关心的只是原始Base64字符串的无损往返。由于Base64是无损且可逆的(只要您在编码和解码时始终坚持相同的字母映射和字节序假设),就可以满足我们的目的。您的数值可能与YouTube主保管库中记录的数值不匹配,但是您将无法分辨出任何差异。
[ 新分析: ]
事实证明,有有一些线索,可以告诉我们关于“真实” 的Base64映射。只有某些映射可以预测我们观察到的最终位置字符,这意味着仅那些字符的二进制值必须具有一定数量的LSB零。h结合绝大多数以字母和数字字符按升序映射的假设,我们基本上可以确认该映射为上表所示。关于LSB分析不确定的唯一剩下的不确定因素是可能替换
-
和_
字符(62
/63
)。原始文本确实讨论了这个LSB问题(请参阅下文),但是当时我还没有完全意识到LSB信息如何作用以限制可能的Base64映射。
最后对此的评论是,您实际上可能想要故意选择 big-endian作为您的应用在内部使用的二进制解释(尽管如今它不如little-endian常见,因此可能不是YouTube“正式”使用的方式)它)。原因是这是在相同值上出现双重视图的情况,因此实际字节顺序在Base64格式中明显可见。保持二进制值和(更多)人类可读的Base64字符串之间的排序顺序一致是有用的,而且不会造成混乱,但是little-endian二进制值的排序是所需ASCII /词法排序的不平凡的争夺。
如果从小尾数ID值开始(即简单地反转它们的排序将不起作用),则没有针对此问题的简单解决方案。相反,您必须提前计划并在解码时反转每个二进制值的字节。因此,如果您关心与二进制值的排序匹配的字母显示,则可能需要更改上面显示的函数,以便将其解码为big-endian ulong
值。这是代码:
// Recover the unique 64-bit value (big-endian) from an 11-character videoID
static ulong YtEnc_to_videoId(String ytId)
{
var a = Convert.FromBase64String(ytId.Replace('-', '+').Replace('_', '/') + "=");
if (BitConverter.IsLittleEndian) // true for most computers nowadays
Array.Reverse(a);
return BitConverter.ToUInt64(a, 0);
}
影片编号
对于videoId,它是一个8字节(64位)的整数。将Base64编码应用于8个字节的数据需要11个字符。但是,由于每个Base64字符正好传达6位(即11 × 6 = 66
2 2 等于64),所以这种分配实际上可以容纳位,比有效负载所需的64位多2位。多余的位设置为零,这具有排除某些字符永远不会出现在编码字符串的最后位置的作用。特别是,保证videoId始终以以下字符之一结尾:
{ A, E, I, M, Q, U, Y, c, g, k, o, s, w, 0, 4, 8 }
因此,videoId的最大约束正则表达式(RegEx)将如下所示:
[0-9A-Za-z_-]{10}[048AEIMQUYcgkosw]
频道或播放列表ID
所述的channelID和playlistId串被编码的Base64 128位(16字节)的二进制整数制造。这提供了一个22个字符的字符串,该字符串可以加上前缀UC
以标识频道本身,或带有UU
标识所包含视频的完整播放列表。这些24个字符的前缀字符串用于URL中。例如,下面显示了两种引用同一通道的方法。请注意,播放列表版本显示了频道中的视频总数,[请参阅注3],这是频道页面未公开的有用信息。
频道网址https://www.youtube.com/channel/UC K8sQmJBp8GCxrOtXWBpyEA播放清单网址https://www.youtube.com/playlist?list=UU K8sQmJBp8GCxrOtXWBpyEA
与11个字符的videoId一样,根据Base64计算可以正确预测观察到的22个字符的字符串长度。在这种情况下,输出能够22 × 6 = 132
对4位的剩余位进行编码;这些零最终限制了64个字母符号中的m̲o̲s̲t̲出现在最后一个位置,仅剩下4个符合条件。因此,我们知道YouTube channelId字符串中的最后一个字符必须为以下字符之一:
{ A, Q, g, w }
这为我们提供了channelId的最大约束正则表达式:
[0-9A-Za-z_-]{21}[AQgw]
最后一点,上面显示的正则表达式仅描述了裸ID值,没有URL,其他用途中必须存在的前缀,斜杠,分隔符等。在给定标识符字符串的属性的情况下,我介绍的RegEx模式在数学上尽可能地小,但是如果按原样使用而没有其他上下文,则它们可能会生成很多错误的肯定信息,即:错误地匹配了虚假文本。为避免在实际使用中出现此问题,请将它们尽可能多地包含在预期的相邻上下文中。
注意事项
[1.]
如上所述,这是Base64规范的摘录,其中讨论了选择字母符号时的注意事项。试图了解该过程如何在选择具有URL语义的字符时得出结论的个人可能会发现这些解释有些没有道理。
3.4。选择字母
不同的应用程序对字母中的字符有不同的要求。以下是确定应使用哪个字母的一些要求:
由人类处理。字符“ 0”和“ O”以及“ 1”,“ l”和“ I”很容易混淆。在下面的base32字母表中,其中不存在0(零)和1(一),根据情况,解码器可以将0解释为O,将1解释为I或L。(但是,默认情况下它不应该;请参阅上一节。)
编码为要求其他要求的结构。对于基数16和基数32,这确定使用大写或小写字母。对于基数64,非字母数字字符(特别是“ /”)在文件名和URL中可能会出现问题。
用作标识符。某些字符,特别是基数为64的字母中的“ +”和“ /”,被传统文本搜索/索引工具视为断字。
没有能够满足所有要求的公认字母。有关高度专业化变体的示例,请参见IMAP [8]。在本文档中,我们记录并命名了一些当前使用的字母。
[2.]
或者,要解决使用Base64编码的ID字符串作为NTFS文件系统上文件或路径名的“原样”组成部分的问题,默认情况下,该字符串不区分大小写(因此在技术上可能会混淆一个或多个)不相关的ID值),这样就可以对NTFS 进行按卷区分大小写的路径/文件命名配置。启用非默认行为可以解决此处描述的问题,但是极少推荐使用此方法,因为它会更改对检查或访问该卷的所有/所有不同应用程序的期望。如果您甚至正在考虑使用此选项,请先阅读并理解它,然后您可能会改变主意。
[3.]
我认为,频道播放列表页面上显示的视频总数考虑了根据HTTP客户端的地理区域限制的视频排除范围。这说明了为播放列表和频道列出的视频数量之间的差异。
UC
vs. UU
channelId前缀的信息。