每个YouTube视频都有一个唯一的ID,可用于获取该ID。例如,位于http://www.youtube.com/watch?v=aN46pEO_jX8的视频的ID为aN46pEO_jX8

经过观察,看起来这些ID遵循以下两个规则:


11个字符
允许使用的符号:az,AZ,0-9,-和_

我想知道:


这两个规则是否都是正确的。
如果还有其他重要的规则要遵循。


#1 楼

根据Youtube 2.0 API文档和3.0 API文档,videoId是字符串,未对当前使用的字符集进行任何指定...

关于11个字符的长度,来自Youtube的帖子API小组说:


我没有在文档中看到我们正式将YouTube视频ID的标准长度
承诺为11个字符的地方。这是我们当前有实现的那些事情之一,并且可能会无限期地保持这种状态。但是我们没有为此提供任何官方的
承诺,因此请您自担风险。


最后但同样重要的是,另一篇文章阐明了(或不提供)格式:


我们不对视频ID的格式做任何公开保证。
当前它们是11个包含字母,
数字和某些标点符号,我不建议将其
硬编码到您的应用程序中(除非您将来有一种简便的方法来对其进行更改)。


Youtube团队似乎更喜欢直接询问Youtube服务器Video_ID是否正确(请参阅现有视频):


如果您需要验证随机用户输入是否与有效的
视频ID,建议您进行实证测试。尝试访问

http://gdata.youtube.com/feeds/api/videos/VIDEO_ID

如果收到200响应,则VIDEO_ID有效。如果收到
非200响应,则您的ID无效。对于新上传的视频或私人视频,有些边缘情况
,但出于大多数目的,我
认为这是可以的。


评论


这是一个很好的答案,并给了我所有我需要的信息!谢谢!

–吞噬
14年1月14日在18:01

这将返回一个HTTP 410。关于现在应对此进行验证的新URL有什么想法?

–威尔·斯特罗尔
2015年9月1日,下午2:57

要验证视频ID,请执行以下操作:只需从youtube获取html页面,并验证元规范链接具有您指定的ID。

– Puchu
16-3-10的23:00

#2 楼

摘要

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    -    _

下面的分析还可以进一步确定对videoId和channelId标识符的表示形式的非明显限制。下面的两个正则表达式总结了这个(可能是新颖的)结果,我在这里为那些对阅读下面的形式分析不感兴趣的人提供了以下两个正则表达式。

RegEx

videoId:    [0-9A-Za-z_-]{10}[048AEIMQUYcgkosw]channelId:  [0-9A-Za-z_-]{21}[AQgw]


讨论

相信使用Base64的原因是,当我们假设编码器输入的标准整数大小分别为64位和128位时,Base64会准确预测YouTube channelId和videoId标识符的异常字符长度(11和22个字符)。此外,根据Base64计算得出的余数可以完美地解释在每种类型的标识符字符串的l founda̲s̲t̲ c̲h̲a̲r̲a̲c̲t̲e̲r̲中发现的观察到的分布变化。以下是对这些要点的讨论。在两种情况下,经过Base64编码的二进制“数据”都是(分别)videoId和channelId的64位或128位的sig_n̲gl̲e̲i̲n̲t̲e̲ge̲r̲。相应地,通过使用Base64解码器,可以从相应的s_trri̲n̲gi̲d̲e̲n̲t̲i̲f̲i̲e̲r̲中恢复单个整数。这样做非常有用,因为尽管每个整数id都包含与Base64字符串完全相同的信息,并且与以Unicode存储的Base64字符串相比,二进制表示是:

缩小了63%,
(最大密度)为100%,
在内存中的对齐更好,
排序和散列更快,并且最重要的是,
消除了仅在拼写形式上不同的标识符之间的虚假冲突。

尽管将Base64 ID视为不区分大小写,但最后一个问题尽管在数值上极不可能,但仍不能排除,就像某些文件系统一样(例如Windows,可以追溯到DOS)。这很重要:如果将videoId / channelId字符串用作Windows / ‌NTFS文件名的一部分,则由于文件系统部署了不区分大小写的路径和文件命名,文件名冲突的可能性很小,但非零。
如果您担心文件名冲突的可能性极低,则数学上消除文件名冲突的一种方法是将解码后的整数(仍按本文所述获得)重新编码为10进制(十进制)或10进制。 (均等大小写)十六进制表示形式,用于此类文件系统上的路径或文件名。[注2]。在这种方法中,64位videoId将需要20个十进制数字[0-9]或8个十六进制数字[0-9,A-F](相对于11个Base64数字) )。 128位channelId最多需要39个十进制数字或16个十六进制数字(相对于22个Base64数字)。

分析

您可能已经注意到我在上面写过您可以从公开的字符串值中恢复“一个”整数。这不就是原始编码的值吗?答案几乎肯定是“是的”(本节将详细讨论支持分析)。不过请注意,虽然我们几乎可以肯定我们获得的是“内部”记录在YouTube主保管库中的完全相同的二进制值,但这一事实也肯定是没有根据的。
换句话说,尽管证据显示以下各节中的内容令人信服,也许也很有趣或令人满意,如果错误,也无关紧要。只要YouTube永远不会在任何地方/任何地方公开公开二进制形式的所谓“正确”值,则解码后的64位或128位值除了用作不透明的识别令牌外没有任何用处,并且任何私下使用的二进制重新编码都可以没关系。
转换的唯一真正要求是不同的编码(没有两个唯一令牌冲突)和完美的可逆性(解码可恢复原始令牌标识)。我们真正关心的是原始Base64字符串的无损往返。由于Base64是无损且可逆的(只要您在编码和解码时始终坚持相同的字母映射和字节序假设),它就可以满足我们的目的。
有一些线索可以告诉我们有关“真实的” Base64映射的信息。难题的症结在于,只有某些正确的映射才能预测我们观察到的最终位置字符,这意味着仅那些字符的二进制值必须具有一定数量的LSB零。嘿。数学细节是每个位宽度所特有的,因此我将在接下来的两节中分别讨论64位和128位标识符。
可以这么说,再加上绝大多数可能的假设,即字母和数字字符按升序映射,我们基本上可以确认该映射是上表中所示的映射。下面的分析在数学上没有定论的唯一唯一不确定性涉及用于编码Base64数字-_(即分别是?)的6263字符的映射。

videoId

videoId标识符字符串编码一个8字节(64位)的整数。将Base64编码应用于8个字节的数据需要11个字符。但是,由于每个Base64字符正好传达6位(即2 2等于64),因此此分配实际上最多可以容纳11 × 6 = 66位-比有效负载所需的64位多2位。多余的位设置为零,这具有排除某些字符永远不会出现在编码字符串的最后位置的作用。特别是,保证videoId始终以以下字符之一结尾:

{ A, E, I, M, Q, U, Y, c, g, k, o, s, w, 0, 4, 8 }

因此,videoId的最大约束正则表达式(RegEx)如下: br />
[0-9A-Za-z_-]{10}[048AEIMQUYcgkosw]


channelId

channelId(和某些类型的playlistId)字符串是通过Base64编码的128位(16字节)二进制整数产生的。这给出了一个22个字符的字符串,可以在前面加上UC来标识频道本身,或者在前面加上UU来标识其包含的视频的完整播放列表。这些24个字符的前缀字符串在URL中使用。例如,以下两个URL属于同一频道,因为它们具有相同的22位Base64后缀(K8sQmJBp8GCxrOtXWBpyEA,以粗体显示):
Channel URL:         https://www.youtube.com/channel/UCK8sQmJBp8GCxrOtXWBpyEA

Playlist URL:  https://www.youtube.com/playlist?list=UUK8sQmJBp8GCxrOtXWBpyEA

这两个URL格式都可以使用。例如,播放列表页面包含有关该频道中视频总数的信息,[请参见注释3]。这是其他频道页面似乎未公开的有用信息。
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]

请记住,此正则表达式仅描述了仅由22个字符组成的channelID值,没有任何可能出现在URL,HTML页面以及其他各种用法中的前缀,斜杠,分隔符等。实际上,更普遍地说,尽管我在此处(及以上)提供的RegEx模式在数学上对于隔离的标识符字符串而言是最小的,但如果按原样使用,它们仍然可能会产生许多错误的肯定结果(即,错误地匹配了伪造的文本)。没有其他周围环境。为避免在实际使用中出现此问题,请确保使用尽可能多的预期相邻上下文详细说明这些正则表达式。

实现

对于64位(videoId )的情况下,解码为二进制很简单,因为您可以使用UInt64(在C#中为ulong)保存生成的“本机”二进制值。

// Recover the unique 64-bit value from an 11-character videoID (native-endian)
//
// 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 "=".

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中起作用(未显示)。实际上,您可能想要为二进制解释故意选择big-endian,尽管它现在不像little-endian那样普遍。原因是这是在相同值上出现双重视图的情况,因此在Base64格式中可见实际的字节顺序。在二进制值和(更多)人类可读的Base64字符串之间保持排序顺序一致是很有帮助的,并且不会造成混淆,但是little-endian二进制值的排序是所需ASCII /词法排序的不平凡的争夺。
由于6位模式和8位字节之间存在不规则的重叠,因此,一旦您编码为小端ID值,就无法简单地解决人类可读的排序问题(即简单地反转排序将不起作用)。相反,您必须在解码之前预先计划并反转每个二进制值的字节,换句话说,应用字节序转换。因此,如果您关心与二进制值的排序匹配的字母显示,则可能需要更改上面显示的函数,以便将其解码为big-endian ulong值。这是该代码:

// Recover the unique 64-bit value from an 11-character videoID (big-endian)

static ulong YtEnc_to_videoId(String ytId)
{
    ytId = ytId.Replace('-', '+').Replace('_', '/') + "=";
    var a = Convert.FromBase64String(ytId);
    if (BitConverter.IsLittleEndian)   // true for most computers nowadays
        Array.Reverse(a); 
    return BitConverter.ToUInt64(a, 0);
}


注意事项[1.]如上所述,这是Base64规范的摘录,其中讨论了选择字母符号的注意事项。试图了解工作组最终如何推荐具有基本URL语义的字符'/'的人(实际上是他们在此识别为“特别有问题的”的少数几个人之一),可能会发现讨论有些无意义,即使不是完全奇怪:

3.4。选择字母不同的应用程序对字母中的字符有不同的要求。以下是确定应使用哪个字母的一些要求:


由人类处理。字符“ 0”和“ O”很容易混淆,“ 1”,“ l”和“ I”也很容易混淆。在下面的base32字母表中,其中不存在0(零)和1(一),根据情况,解码器可以将0解释为O,将1解释为I或L。 (但是,默认情况下它不应该;请参见上一节。)


编码为强制执行其他要求的结构。对于
基数16和基数32,这确定使用大写或小写字母。对于base 64,非字母数字字符(特别是“ /”)可能在文件名和URL中有问题。


用作标识符。某些字符,特别是基数为64的字母中的“ +”和“ /”,已被旧版文本搜索/索引工具视为断字。


没有公认的字母满足所有要求。有关高度专业化变体的示例,请参见[IMAP-RFC 3501 5.1.3。]。在本文档中,我们记录和命名一些当前使用的字母。

[2.]或者,解决使用Base64编码的ID字符串作为文件或路径名的“原样”组件的问题。在默认情况下不区分大小写的NTFS文件系统上(因此在技术上存在混淆一个或多个不相关ID值的风险),碰巧会为NTFS配置基于卷的区分大小写的路径/文件命名。启用非默认行为可能会解决此处描述的问题,但是极少建议使用此方法,因为它会更改对检查或访问该卷的所有/所有不同应用程序的期望。如果您甚至正在考虑使用此选项,请先阅读并理解它,然后您可能会改变主意。
[3.]我相信频道播放列表页面上显示的视频总数已考虑了以下因素:受HTTP客户端地理区域限制的视频。这说明了播放列表中列出的视频数量与频道之间的差异。

评论


那是一些令人印象深刻的侦探工作。

–ale
16 Dec 16'在12:53

鳄梨调味酱,这个答案值得一千个投票

– pilau
17年8月19日在6:36

YouTube频道ID现在为24个字符,而不是22个字符;例如UCjXfkj5iapKHJrhYfAF9ZGg;来源:stackoverflow.com/questions/14366648/…

–evandrix
17年8月26日在17:35

@evandrix感谢您的来信。我帖子的最后一段旨在解决这个问题;我只讨论ID字符串的可变部分。有通道ID的前缀(例如UC或UU),本文中不再讨论。如果您有带前缀的值(例如您的示例),则我提供的信息适用于最后22个字符。

– Glenn Slayden
17年8月28日在19:36



@evandrix如果您仍然感兴趣,我刚刚更新了文章本身,以包括有关UC和UU channelId前缀的信息。

– Glenn Slayden
18年1月17日在21:00