Как найти одну модель на разных сайтах: pHash, GD и история трансляций

Одна модель может одновременно вести эфиры на двух или трёх платформах, используя совершенно разные ники. Поиск по имени в таком случае бесполезен, а сравнение фотографий вручную не подходит для большого каталога. Есть более простой и дешёвый способ: искать похожие кадры с помощью perceptual hash (pHash), а затем проверять, совпадают ли начало и конец эфиров на разных сайтах. Для этого не нужны нейросети, распознавание лиц или GPU.
Разберём подход на реальных примерах: с 16-значными хешами, расстоянием между ними, историей трансляций и оценкой затрат. Это не описание внутренней инфраструктуры конкретного сайта, а метод, который можно повторить на собственном агрегаторе.
Почему ников недостаточно
anna_live и anna-live легко привести к одному написанию. Можно также учитывать опечатку или цифры в конце имени. Но как связать hottdoll611 на Chaturbate и Carrie1337 на BongaCams? По буквам у этих названий ничего общего.
Сходство имён к тому же не доказывает, что перед нами один человек: популярные ники повторяются. Поэтому разумно разделить поиск на два этапа. Картинка предлагает кандидатов, а история эфиров помогает подтвердить связь. Отдельный кадр — ещё не доказательство, особенно если на нём тёмный экран или стандартная заставка.
Что делает GD, а что — pHash

В PHP расширение GD позволяет открыть JPEG, WebP или PNG, изменить размер изображения и прочитать цвета пикселей. Это удобный первый шаг. Но GD сам по себе не выдаёт pHash: цифровой отпечаток нужно посчитать отдельно либо воспользоваться библиотекой, реализующей тот же алгоритм.
Типовая схема pHash выглядит так:
- Загрузить кадр с помощью GD, привести ориентацию к единому виду и уменьшить до 32 × 32 пикселей.
- Перевести изображение в оттенки серого, используя один и тот же способ расчёта яркости для всех кадров.
- Выполнить дискретное косинусное преобразование (DCT) — оно описывает не отдельные пиксели, а крупные светлые и тёмные области изображения.
- Взять низкочастотный участок 8 × 8 коэффициентов. Сравнить их с медианой и записать 64 результата в биты в строго определённом порядке. При реализации заранее зафиксировать правило обработки нулевого (DC) коэффициента: разные библиотеки делают это по-разному.
- Сохранить 64-битный результат как 16 шестнадцатеричных символов, например
f8949667272fc82a.
Получается отпечаток композиции кадра, а не файла. Разный формат, размер, сжатие или небольшая плашка платформы часто не мешают увидеть близость. Сильное изменение позы или кадрирования, напротив, может заметно изменить хеш. Поэтому pHash не заменяет распознавание человека и не обязан совпадать на каждом снимке.
Вычислять отпечаток выгодно один раз, при сохранении очередного кадра. Позже поиск работает с короткими строками, а не повторно читает тысячи изображений.
Реальная пара: два ника, одна комната

Посмотрим на профили hottdoll611 на Chaturbate и Carrie1337 на BongaCams. В кадрах видны одни и те же детали: чёрное кресло, полка с цветными папками, золотой шар в форме сердца, красная звезда, белая рубашка и розовая юбка. Кадрирование отличается, а фотографии сделаны не одновременно.
В архиве сохранились две пары кадров:
| Снимки, UTC | Chaturbate: pHash | BongaCams: pHash | Различающихся битов |
|---|---|---|---|
| Снимки, UTC20:52 и 20:57 | Chaturbate: pHashf29a95ea642eca26 | BongaCams: pHashf09097e7662ece22 | Различающихся битов10 из 64 |
| Снимки, UTC21:20 и 21:26 | Chaturbate: pHashf8949667272fc82a | BongaCams: pHashf094d6e7662ec82a | Различающихся битов6 из 64 |
Вторая пара снята с интервалом примерно 5 минут 23 секунды. Близкое значение pHash позволяет выдвинуть гипотезу: перед нами два профиля одной модели. Но почему в первой строке расстояние 10, а во второй — 6? Потому что pHash отражает общий рисунок картинки, и даже небольшой сдвиг камеры или позы меняет часть битов. Искать следует близкие хеши, а не только полностью одинаковые.

f8949667272fc82a
f094d6e7662ec82a- 6 из 64 бит
- 38 соответствующих сессий
MATCH
Два кадра не совпадают пиксель в пиксель. Камера и поза чуть сдвинулись. pHash всё равно видит похожую структуру кадра, а история эфиров даёт дополнительное подтверждение.
Как получить число 6 из двух хешей
Расстояние Хэмминга — это количество битов, в которых два отпечатка различаются. Чтобы его найти, выполняют побитовое исключающее ИЛИ (XOR) и считают единичные биты результата. Для приведённой пары получится 6.
Если хеши хранятся как 16-значные hex-строки, в PHP не нужно даже переводить всё число в знаковый 64-битный int. Можно сравнить его по шестнадцатеричным цифрам:
function hammingHex(string $a, string $b): int
{
if (!preg_match('/^[0-9a-f]{16}$/i', $a) ||
!preg_match('/^[0-9a-f]{16}$/i', $b)) {
throw new InvalidArgumentException('Expected two 64-bit hex hashes');
}
$ones = [0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4];
$distance = 0;
for ($i = 0; $i < 16; $i++) {
$distance += $ones[hexdec($a[$i]) ^ hexdec($b[$i])];
}
return $distance;
}
// 6
hammingHex('f8949667272fc82a', 'f094d6e7662ec82a');
Чем меньше расстояние, тем ближе композиции. Универсального безопасного порога нет: его выбирают по собственным кадрам, отдельно проверяя ложные совпадения. И ещё одно важное условие: сравнивать можно только хеши, рассчитанные одинаковым алгоритмом, с одинаковой обработкой цветов, DCT и порядком битов.
Почему похожий кадр — только половина проверки

У чёрного кадра pHash может оказаться 0000000000000000. Точно такой же отпечаток получат совершенно посторонние пустые трансляции. Расстояние 0 в таком случае говорит лишь о совпадении изображений, но не людей. Похожие заставки, одинаковые интерьеры и элементы интерфейса создают ту же проблему.
Поэтому после поиска похожих снимков полезно сравнивать расписание эфиров. Если одна модель транслирует на двух сайтах одновременно, её комнаты обычно открываются и закрываются приблизительно в одно время. Не обязательно до секунды: одна платформа может дольше подключаться, позже заметить завершение эфира или временно оборвать соединение.
Практический вариант: хранить для каждой платформы интервалы started_at / ended_at и считать пару эфиров совпавшей, если и начало, и конец находятся в пределах разумного временного окна — например, 30 минут. Это пример настройки для старта, а не универсальное правило. Не следует считать единственным доказательством два похожих начала без совпадающих окончаний. И одна сессия на первом сайте не должна подтверждать сразу несколько сессий на втором.
Дальше проверяют не один вечер, а несколько недель истории: сколько раз совпадения повторялись, в скольких разных днях и какую долю эфиров каждого аккаунта они составляют. Для новых профилей полезно отдельно отмечать недостаток данных, а не объявлять их несовпадающими.
Что показала история этой пары
У hottdoll611 и Carrie1337 оказалось 38 соответствующих трансляционных сессий. В рассматриваемой истории это составляло 57,6% эфиров одного профиля и 27% другого. Разные проценты объясняются просто: аккаунты могли вести эфиры с разной частотой и не всегда одновременно на обеих площадках.
Сочетание факторов существенно сильнее одного скриншота: почти одинаковая обстановка, расстояние pHash 6 из 64, снимки с разницей чуть больше пяти минут и десятки эфиров с похожим временем начала и завершения. Ники при этом никак не помогают поиску.
Другой пример — your_wild_lexi на Chaturbate и AlexisGrays на BongaCams. Их хеши d64ff814856fc286 и c64ff814876dc28e различаются всего на 4 бита, а история содержит 13 соответствующих сессий.
Когда похожие кадры не означают совпадение моделей
pHash помогает быстро найти изображения, которые стоит сравнить. Но даже небольшое расстояние между отпечатками не доказывает, что два профиля принадлежат одному человеку. Похожими могут оказаться тёмные кадры, стандартные заставки или трансляции с одинаковым освещением и фоном.
Показательный случай — EthanLowell на Xlove и Laena_Castillo на Amateur.tv. Расстояние между pHash их кадров составило 10 из 64 бит. На этапе поиска кандидатов такая пара заслуживала проверки, однако история эфиров не подтвердила предполагаемую связь.
За доступный период у профилей нашлось лишь два совпадения по времени трансляций — 4,8% истории одного профиля и 2% другого. Большинство эфиров начинались и заканчивались независимо. В ранней версии правил этого оказалось недостаточно для защиты от ошибки: пару связали, поскольку проверка расписания была слишком мягкой. После пересмотра правил такой набор признаков не должен приводить к автоматическому объединению.

e6c619c91cec2772
ec8619c51cec67b8- 10 из 64 бит
- 2 совпавших эфира
- 4,8% и 2%
NO MATCH
NO MATCH: недостаточно оснований связывать профили. Это решение алгоритма, а не доказательство того, что за аккаунтами обязательно стоят разные люди. Для агрегатора лучше оставить сомнительную пару раздельно, чем ошибочно смешать историю, расписания и другие данные двух профилей.
Для сравнения, у hottdoll611 на Chaturbate и Carrie1337 на BongaCams визуальное расстояние на выбранных кадрах составило 6 из 64 бит, а в истории обнаружились 38 соответствующих трансляционных сессий. Здесь совпадение подтверждают два разных признака: похожий кадр и регулярно совпадающее время эфиров.
Вывод: pHash находит кандидатов с минимальными вычислительными затратами. История начала и окончания трансляций помогает решить, какие из этих кандидатов действительно стоит связывать. Расстояние Хэмминга нельзя превращать в «процент вероятности совпадения», а долю отклонённых кандидатов — называть измеренным false-positive rate.
Как искать быстро, а не сравнивать всё со всем
Наивное сравнение каждой картинки с каждой быстро становится дорогим. При 7 000 кадрах получается почти 24,5 миллиона неупорядоченных пар, ещё до проверки расписания. Для небольшого проекта это терпимо, но для каталога с постоянным обновлением бессмысленно выполнять такую работу снова и снова.
Несколько простых оптимизаций дают гораздо больший эффект, чем перенос задачи на GPU:
- Сравнивать только свежие кадры моделей из разных платформ, а не все изображения в архиве.
- Сохранять pHash вместе с кадром, чтобы не пересчитывать его при каждом поиске.
- Разбивать 64-битный хеш на небольшие блоки и сначала искать совпадение хотя бы одного блока. Полное расстояние Хэмминга считать лишь для кандидатов. Число блоков и допустимое расстояние нужно выбирать совместно, иначе можно потерять реальные совпадения.
- Запрашивать историю эфиров только для прошедших фильтр пар, а не для всех профилей.
- Кешировать результаты проверки и не создавать повторные связи для уже сопоставленных профилей.
В одном наблюдавшемся проходе обрабатывались примерно 6–7,5 тысячи свежих отпечатков, а до проверки расписания доходили лишь 9–22 пары. Полный проход занимал 3–5 секунд и примерно 39–45 МБ памяти. Это показатели конкретной нагрузки, а не обещание производительности для любого проекта.
Почему это дешевле распознавания через AI
Здесь нет необходимости отправлять каждую фотографию в модель машинного зрения, оплачивать API за изображения или содержать GPU для постоянного поиска. GD обрабатывает обычную картинку на CPU, pHash сводит её к 64 битам, а близость считается несколькими простыми операциями. История эфиров — это уже имеющиеся у агрегатора временные записи.
Алгоритм не «ничего не стоит»: нужно сохранять снимки, рассчитывать хеши, хранить события эфиров, отсекать пустые кадры и проверять спорные совпадения. Однако основная вычислительная работа здесь небольшая и предсказуемая. AI может пригодиться для отдельных сложных случаев, но для первого массового отбора кандидатов необязателен.
Что получилось в одном проходе

10 ноября 2026 года одна проверка нашла 17 уверенных пар аккаунтов на разных платформах. Из них 9 можно было бы обнаружить по похожим никам, ещё 2 имели узнаваемые имена, но находились в разных категориях каталога, а 6 пар не находились по именам вообще.
Это не показатель точности в процентах и не оценка количества дубликатов во всём интернете. Это конкретный результат одного прохода. Он показывает ценность дополнительного сигнала: сравнение снимков вместе с историей эфиров позволяет обнаруживать связи, которые обычный поиск по нику пропускает.
Для вебмастера практический вывод простой. Начать можно с регулярного сохранения кадров, 64-битного pHash и истории start/end. Затем добавить быстрый отбор кандидатов и консервативное подтверждение по повторяющимся сессиям. Не соединяйте профили только потому, что нашлась одна похожая картинка: ошибочно объединить двух разных людей хуже, чем оставить один дубль ненайденным.
На Cloud9Cams такие связи помогают посетителям находить знакомую модель на другой платформе, даже если там используется иной ник. Но сам подход подходит любому каталогу, где объект появляется в нескольких источниках, а его изображения и время активности можно сравнить.