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 не используют =
символ заполнения; в этом нет необходимости, поскольку ожидаемые кодированные длины для соответствующего декодированного целочисленного размера являются фиксированными и известными (11 и 22 кодированные «цифры» для 64 и 128 битов соответственно).
За одним незначительным исключением (обсуждается ниже), полные детали отображения Base64 могут быть получены из общедоступных данных. С минимумом догадок, то, скорее всего , что Base64 схема , используемая в VideoID и channelId строк выглядит следующим образом :
——₀————₁————₂————₃————₄————₅————₆————₇————₈————₉———₁₀———₁₁———₁₂———₁₃———₁₄———₁₅—
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 предсказывает необычные длины символов (11 и 22 символов) на YouTube channelId и VideoID идентификаторы точно. Кроме того, остатки, рассчитанные в соответствии с Base64, прекрасно объясняют наблюдаемое изменение распределения, найденное в l̲a̲s̲t̲ c̲h̲a̲r̲a̲c̲t̲e̲r̲ каждого типа строки идентификатора. Обсуждение этих моментов следует.
В обоих случаях, двоичный «данные» , который получает кодировкой Base64 это одно целое число, либо 64 или 128 бит, для (соответственно) VideoID против channelId . Соответственно, используя декодер Base64, одно целое число может быть восстановлено из строкового идентификатора, и это может быть весьма полезно сделать, потому что, хотя каждый целочисленный идентификатор содержит точно такую же информацию, что и строка Base64, а также позволяет строке быть воссозданным в любое время - по сравнению со строками Base64, хранящимися как Unicode, двоичное представление на 63% меньше, имеет максимальную битовую плотность 100%, лучше выравнивается в памяти, быстрее сортирует и хеширует и, что, возможно, самое главное, устраняет ложные столкновения между идентификаторами, которые отличаются только в орфографическом случае, Эта последняя проблема, хотя и чрезвычайно маловероятная в численном отношении, тем не менее не может быть исключена, когда идентификаторы Base64 обрабатываются как регистрозависимые, как это делают некоторые файловые системы (например, Windows , восходящая к DOS ).
Это любопытное важно: если вы используете VideoID / channelId строку как часть файла Windows / NTFS, есть исчезающе miniscule- , но тем не менее ненулевой -chance столкновений имен файлов из - за эти файловые системы , внедряющих регистронезависимым путем и присвоение имен файлов ,
Если вы беспокоитесь об этой удаленно возможной проблеме, один из способов ее математического устранения состоит в перекодировании декодированных целых чисел - все еще получаемых, как описано в этой статье, - либо в основание-10 (десятичное), либо (равномерное- cased) шестнадцатеричное представление, для использования в путях или именах файлов в таких файловых системах. [примечание 2.] В этом подходе для 64-битного videoId потребуется 20 десятичных цифр [0-9]
или 8 шестнадцатеричных цифр [0-9,A-F]
( против 11 цифр Base64). 128-битный идентификатор канала потребует максимум 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 (не показан).
[ править: ]
После дальнейших размышлений часть моего исходного поста не была максимально завершена. Справедливости ради, оригинальный отрывок сохраняется (вы можете пропустить его при желании); ниже я объясню недостающее понимание:
[ Оригинал: ]
Вы , возможно, заметили выше , что я написал , что вы можете восстановить « в » целом. Разве это не было бы значением, которое было изначально закодировано? Не обязательно. И я не имею в виду различие со знаком / без знака, которое, правда, не может быть установлено здесь (потому что это не меняет никаких фактов о бинарном изображении). Это сами числовые значения: без какого-то " Розеттского камня"«Это позволит нам перепроверить абсолютные значения, которые известны как« правильные », отображение числового алфавита, а также порядковый номер не может быть точно известно, что означает, что нет никакой гарантии, что вы восстанавливаете то же значение, что и компьютеры на YouTube закодированы. К счастью, пока YouTube никогда публично не выставляет так называемые правильные значения в менее непрозрачном формате где-либо еще, это не может иметь значения.
Это связано с тем, что декодированные 64- или 128-битные значения не используются в любом случае, кроме как в качестве идентифицирующего токена, поэтому наши единственные требования к преобразованию - это различное кодирование (не сталкиваются два уникальных токена ) и обратимость (декодирование восстанавливает исходную идентификацию токена).
Другими словами, все, что нас действительно волнует, - это обход без потерь исходной строки Base64. Поскольку Base64 без потерь и обратим (если вы всегда придерживаетесь одного и того же алфавитного отображения и предположения о порядке байтов для кодирования и декодирования), это удовлетворяет нашим целям. Ваши числовые значения могут не совпадать с теми, которые записаны в главном хранилище YouTube, но вы не сможете различить их.
[ Новый анализ: ]
Оказывается, что есть несколько подсказок , которые могут рассказать нам о «истинном» Base64 отображении. Только определенные сопоставления предсказывают символы конечной позиции, которые мы наблюдаем, то есть двоичное значение только для этих символов должно иметь определенное количество нулей LSB. Хех.
Взятый вместе с чрезвычайно вероятным предположением, что алфавитные и цифровые символы отображаются в порядке возрастания, мы можем в основном подтвердить соответствие тому, что показано в таблицах выше. Только сохраняющаяся неопределенность относительно которой LSB анализ неубедительны является возможность замены из -
и _
символов ( 62
/ 63
).
Оригинальный текст сделал обсудить этот вопрос LSB (см ниже), но то , что я не в полной мере реализовать в то время было как LSB информация действует , чтобы ограничить возможное Base64 отображение.
Последний комментарий по этому поводу заключается в том, что на самом деле вы можете намеренно выбрать порядок с прямым порядком байтов для двоичной интерпретации, с которой ваше приложение работает внутренне (даже несмотря на то, что это менее распространено, чем метод с прямым порядком байтов в наше время, и, таким образом, это может быть не так, как YouTube официально) Это). Причина в том, что это случай двойных представлений с одним и тем же значением, так что фактический порядок байтов отображается в представлении Base64. Полезно и менее запутанно поддерживать порядок сортировки между двоичным значением и (несколько более) понятной для человека строкой Base64, но сортировка двоичных значений с прямым порядком байтов является нетривиальной схваткой желаемой ASCII / лексической сортировки ,
Простого решения этой проблемы не существует, если вы начинаете с значений порядка байтов с прямым порядком байтов (т. Е. Просто изменение их сортировки не будет работать). Вместо этого вы должны планировать заранее и инвертировать байты каждого двоичного значения во время декодирования . Так что, если вы заботитесь о алфавитном отображении, совпадающем с сортировкой двоичных значений, вы можете изменить показанную выше функцию, чтобы она вместо этого декодировалась в значения с прямым порядком байтов 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);
}
Идентификаторы YouTube
Идентификатор видео
Для videoId это 8-байтовое (64-битное) целое число. Применение кодировки Base64 к 8 байтам данных требует 11 символов . Однако, поскольку каждый символ Base64 передает ровно 6 битов (то есть, 2⁶ равен 64), это распределение может фактически содержать до 11 × 6 = 66
битов - избыток в 2 бита по сравнению с 64 битами, необходимыми для нашей полезной нагрузки. Лишние биты устанавливаются в ноль, что исключает появление определенных символов в последней позиции кодированной строки. В частности, videoId всегда заканчивается одним из следующих символов:
{ A, E, I, M, Q, U, Y, c, g, k, o, s, w, 0, 4, 8 }
Таким образом, максимально ограниченное регулярное выражение (RegEx) для videoId будет выглядеть следующим образом:
[0-9A-Za-z_-]{10}[048AEIMQUYcgkosw]
Идентификатор канала или плейлиста
В channelId и playlistId строки производятся в Base64-кодирующий 128 бит (16 байт) двоичное число. Это дает 22-символьную строку, к которой можно добавить префикс либо UC
для идентификации самого канала, либо UU
для идентификации полного списка воспроизведения видео, которое он содержит. Эти 24-символьные строки с префиксом используются в URL . Например, ниже показаны два способа обращения к одному и тому же каналу. Обратите внимание, что версия списка воспроизведения показывает общее количество видео в канале, [см. Примечание 3.] полезную информацию, которую не раскрывают страницы канала.
URL каналаhttps://www.youtube.com/channel/UC K8sQmJBp8GCxrOtXWBpyEA
URL плейлистаhttps://www.youtube.com/playlist?list=UU K8sQmJBp8GCxrOtXWBpyEA
Как и в случае с 11-символьным videoId , расчет на Base64 правильно предсказывает наблюдаемую длину строки в 22 символа . В этом случае выход способен кодировать 22 × 6 = 132
биты, избыток 4 бита; эти нули в конечном итоге ограничивают m̲o̲s̲t̲ из 64 символов алфавита от появления в последней позиции, и только 4 из них остаются приемлемыми. Поэтому мы знаем, что последний символ в строке channelId YouTube должен быть одним из следующих:
{ A, Q, g, w }
Это дает нам максимально ограниченное регулярное выражение для channelId :
[0-9A-Za-z_-]{21}[AQgw]
В качестве последнего примечания, регулярные выражения, показанные выше, описывают только голые значения идентификаторов, без префиксов, косых черт, разделителей и т. Д., Которые должны присутствовать в 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 в качестве «как есть» компонентов имен файлов или путей в файловой системе NTFS, которая по умолчанию не чувствительна к регистру (и, таким образом, технически рискует объединить одно или несколько не связанные значения идентификаторов), так получается, что NTFS может быть настроен с учетом пути / имен файлов с учетом регистра для каждого тома. Включение поведения не по умолчанию может решить проблему, описанную здесь, но редко рекомендуется, так как это изменяет ожидания для любых / всех разрозненных приложений, которые проверяют или получают доступ к тому. Если вы даже рассматриваете этот вариант, сначала прочитайте и поймите это , и вы, вероятно, передумали.
[3.]
Я полагаю, что общее количество видео, отображаемых на странице списка воспроизведения канала, учитывает исключение для видео, которое ограничено в соответствии с географическим регионом клиента HTTP. Это объясняет любое несоответствие между количеством видео, перечисленных для плейлиста, и каналом.