Как за один вечер разгрести 36 000 фотографий и почту с 2005 года, руками AI-агента и локальных моделей. clip.. clip. czkawka.. clip. czkawka. insightface.. clip. czkawka. insightface. mlx.. clip. czkawka. insightface. mlx. дедупликация.. clip. czkawka. insightface. mlx. дедупликация. диаризация.. clip. czkawka. insightface. mlx. дедупликация. диаризация. локальные модели.. clip. czkawka. insightface. mlx. дедупликация. диаризация. локальные модели. распознавание лиц.

Есть задачи, которые не делаются никогда. Не потому что сложные, а потому что объём убивает любое намерение на втором часу. У меня такой задачей был фотоархив: около 36 000 фото и видео, 222 ГБ, копившиеся 20 лет и размазанные вообще везде:

  • часть в OneDrive, разложенная по годам;

  • часть там же, но в свалках: дампы с телефонов, выгрузки из WhatsApp, папка буквально с названием «разобрать старые фото», которая ждала своего часа лет десять;

  • часть уже в Apple Photos, с iPhone, сама по себе и никак не связанная с остальным архивом;

  • часть вообще застряла в почте: приходила годами порциями, тяжёлыми письмами, и так и осела вложениями;

  • имена файлов: половина по-человечески, половина IMG_4348.JPG и DSCN0217.JPG;

  • EXIF: у части корректный, у части враньё, у части нет вовсе.

Разобрать это руками означало однажды сесть и просмотреть десятки тысяч файлов, то есть никогда.

А началось всё буднично. Пришло уведомление, что в почте кончается место, и сервис предложил очевидное: докупить квоту. Но я подумал, что за 20 лет ящик ни разу толком не чистил, и логичнее один раз разобрать. И сразу решил делать это не руками, а с агентом: выдал ему доступ к Gmail API, попросил проанализировать ящик. Он вернулся с раскладкой (сколько чего по отправителям, размерам, годам), и дальше почту мы разрулили целиком его руками. По дороге выяснилось, что куча фотографий осела в тяжёлых письмах, решил их вытащить и кинуть в Apple Photos. И тут вспомнил про старый неразобранный архив в OneDrive. И понеслось.

Исторически у такой задачи было ровно два исхода: «руками когда-нибудь» (то есть никогда) и «докупить квоту». Я решил попробовать третий: отдать рутину AI-агенту, а самому только принимать решения. Оркестратором был Claude Code / Opus 4.8, он сам писал одноразовые скрипты под каждый шаг и дёргал нужные инструменты.

С чего начали: почта

План, на котором сошлись с агентом, был простой: сначала вычистить спам, а фото-архивы, осевшие в письмах, вытащить и перенести в отдельный сервис, чтобы и место освободить, и снимки не потерять.

Около 9 500 явного мусора (реклама, уведомления) отправили в Корзину. И сразу урок, ради которого стоит держать страховку: в эту пачку уехала рассылка живого интернет-магазина (конструктор сайта, сервис рассылок, платёжные уведомления), формально спам-признаки, фактически рабочая история проекта. Спасло то, что удаляли только в Корзину: восстановили одной командой, отправителя занесли в исключения. Никаких «удалить насовсем», пока человек не подтвердил.

А вот дальше началось интересное. Тяжёлые письма оказались, по сути, непросмотренным фотоальбомом. Причём слали их порциями: одно событие нередко было раскидано по нескольким письмам («часть 1», «часть 2», и так далее). И тут агент сделал больше, чем тупо вытащил вложения: он проанализировал темы и содержание писем, выборочно посмотрел сами фотографии и предложил понятную структуру. Например, файлы, присланные четырьмя разными письмами, он объединил в одно событие. То есть не «папка на письмо», а «папка на реальное событие».

Эти альбомы перенесли в Apple Photos. С массовым импортом скриптом возникли проблемы (Apple Photos с таким дружит плохо), но вместе с агентом мы их порешали. Подробности скучные, важно другое.

Поворот: а давай заодно и OneDrive

Вот ровно в этот момент я задумался плотнее. Раз фотографии из почты уже едут в Apple Photos, логично причесать и старый архив в OneDrive, который лежал нетронутым годами, и тоже завести его в Apple Photos.

Зачем. Во-первых, альтернативная копия. Во-вторых, и это главное, появлялась реальная возможность вообще отказаться от подписки OneDrive и переехать в Apple целиком. Раньше об этом не было смысла даже думать: затащить 36 тысяч неразобранных файлов в Apple Photos означало просто перевезти бардак с места на место.

Так задача из «почистить почту» выросла в «разобрать весь фотоархив». А это уже 36 659 файлов и 222 ГБ.

Честный разговор про объём

Когда я попросил агента «разобрать 36 тысяч фотографий», он не бросился их смотреть. Он сказал прямо: гонять такой объём через меня саму (фронтир-модель) бессмысленно, это и в контекст не влезет, и по токенам разорит. Правильный путь, говорит, поднять локальные модели, которые сделают тяжёлую работу почти даром на твоём железе, а я возьму на себя оркестрацию и контроль качества.

Это и задало всю архитектуру. Сложилось разделение труда:

  • локальные модели перемалывают десятки тысяч файлов почти бесплатно;

  • фронтир-агент пишет под каждый шаг одноразовый скрипт, склеивает инструменты и сам проверяет результат, а не только показывает его мне;

  • человек принимает финальные решения и ловит то, что машина знать не может.

Связка человек, агент, локальные модели

Связка человек, агент, локальные модели

Источники из разных мест сходятся к агенту, тот раздаёт тяжёлую работу локальным моделям, а себе оставляет оркестрацию и контроль.

Дальше каждый узел покажу одинаково: в какую проблему уперлись, что предложил агент, как это выглядело технически, что значило по-человечески, и какое решение это позволило принять.

Шаг 1. Дедуп, до всего остального

Первое правило большого архива: сначала убрать дубли, потом всё остальное.

Проблема. Куча почти-одинаковых файлов: пересохранения, ресайзы, кадры серий. Точные дубли по хэшу их не ловят. Что предложил агент. Сравнивать не байты, а изображения. Технически. Перцептивный хэш, инструмент czkawka. По-человечески. «Вот 5 кадров, где одно и то же, разница только в сжатии: оставляем лучший по разрешению, остальные в карантин.» Какое решение позволило принять. Схлопнуть очевидные повторы, не глядя руками на 36 тысяч файлов. Обратимо, в карантин.

Поверх czkawka агент за 15 минут собрал маленькую браузерную страничку для ревью: группы похожих, миниатюры в ряд, лучший предвыбран. Удобнее любой готовой галереи.

Дедуп по содержимому

Дедуп по содержимому

Из почти одинаковых кадров остаётся лучший по разрешению, остальные в карантин (обратимо).

Шаг 2. «А что вообще на фото?», локальные модели

Свалки без имён и дат нельзя разложить по событиям, пока не поймёшь, что на снимках. Руками те же десятки тысяч. Поэтому модели, локально.

Грубые теги содержимого. CLIP (open_clip, ViT-B-32) для каждого фото выдаёт ближайшие теги из словаря (пляж, дети, еда, документ). По-человечески: «это похоже на праздник», «это скан документа, не память». Заодно отделили документы и скриншоты от снимков.

Имена событий.

Проблема. Тег «праздник» это не название альбома. Нужно «день рождения», «поездка», «корпоратив». Что предложил агент. Показать зрительной модели по паре кадров из каждого кластера и попросить описать. Технически. Qwen2.5-VL-7B через mlx-vlm, нативно на Apple Silicon. По-человечески. Модель выдавала «Дети на катке с маскотом в виде зайца», «Семья катается на коньках в тумане». Из этого уже собирается человеческое имя события.

Вот здесь и видна та самая экономика. Просить фронтир-модель «опиши все 4 000 фото» это и долго (около 17 секунд на кадр, итого часы), и дорого по токенам. Локальная VLM делает это почти даром, а агент только склеивает описания в имена событий.

Шаг 3. Лица, как диаризация в аудио

Самая красивая часть. Задача «найти, кто на фото» это ровно та же задача, что диаризация спикеров в аудио: разбить на «персона 1, персона 2», а человек потом называет их по разу.

Проблема. Хочется находить всех по человеку и подписывать события именами, но 74 тысячи лиц вручную не разметишь. Что предложил агент. Детектировать лица, посчитать эмбеддинги, кластеризовать, а человеку оставить только «назвать кластеры». Технически. InsightFace (ArcFace-эмбеддинги), затем kNN и union-find, получилось 2 153 кластера-персоны. По-человечески. «Вот один человек на 3 818 фото, вот другой на 3 200: назови их по разу, имена сами разойдутся по всем снимкам.»

И тут поучительный провал с порогом. При мягком пороге кластеризация схлопнула пол-архива в один мегакластер на 30 000 лиц, где разные люди вперемешку (эффект цепочки через «мостиковые» лица). Подняли порог строже, получили чистые кластеры.

Показательно, кто проверял качество. Не я глазами, а сам агент: вырезал по несколько лиц из крупнейших кластеров и смотрел (у фронтир-модели есть зрение), один это человек или каша. То есть оптический контроль, который обычно ложится на человека, агент во многом взял на себя.

Какое решение позволило принять. Назвать топ-персон по разу (это покрыло больше 15 тысяч фото), а их имена вписались тегами прямо в файлы (XMP/IPTC), так что ищутся в любом просмотрщике.

Диаризация лиц

Диаризация лиц

Лица бьются на персон автоматически, человек называет каждую один раз, имена расходятся по всем фото и видео.

Называл не всех, да это и не нужно. Персоны отсортированы по частоте: сверху те, кто чаще всего в кадре (по факту семья, друзья, родственники, коллеги), внизу случайные и малознакомые люди, попавшие в объектив на групповых и публичных снимках. Подписывать имеет смысл именно частых, у них и отдача максимальная.

Лейблер персон

Лейблер персон

Реальный экран лейблера: персоны по убыванию частоты, лица заблюрены, а имена я скрыл специально для публикации. Из 2 153 персон подписаны верхние несколько десятков, дальше хвост из случайных людей.

Шаг 4. Видео: тот же стек, в два прохода

Роликов в архиве 1 754, и бросать их не хотелось. Отдельный «видео-стек» не понадобился: ffmpeg достаёт из ролика несколько кадров, а дальше работают те же модели, что и для фото. Что в ролике, описывает та же VLM по кадрам. Кто в ролике, те же лица сверяются с уже названными персонами, и клип получает теги.

Видео кадры из ffmpeg в те же модели

Видео кадры из ffmpeg в те же модели

Видео разбирается тем же стеком: кадры из ffmpeg уходят в VLM (что в ролике) и в распознавание лиц (кто), результат тегами в файл.

С распознаванием людей в видео всплыл нюанс, который мы с агентом обсудили и решили в два прохода. Сначала прогнали все 1 754 ролика по 5 кадров, это дало людей в части роликов. Но 5 кадров легко пропускают человека, который мелькнул лишь в куске видео. Поэтому вторым проходом взяли только те ролики, где в первый раз никого не нашли, и прогнали их плотнее, по 12 кадров. Так добрали ещё заметную долю: итого из 1 754 людей распознали в 608 (470 в первом проходе плюс 138, всплывших во втором).

Логика та же, что и со всем остальным: сначала дёшево закрыть основной объём, потом точечно дожать остаток там, где это реально окупается.

Хозяйке на заметку. Этим же реестром лиц можно довольно точно вытащить все фото и видео с конкретным человеком и собрать на их основе, например, короткий коллаж-ролик к событию: дню рождения, юбилею, выпускному.

Шаг 5. Сортировка, и почему EXIF врёт

Целевая структура хронологическая: год, внутри ГГГГ-ММ-ДД, событие. Делали через манифест с предпросмотром и полным undo-логом (любой шаг обратим), сначала пилот на одном годе. И пилот тут же себя оправдал.

Проблема. Пачка фото с корпоратива 2008 года уехала в 2005. Почему. У старых камер с несбитыми часами EXIF по умолчанию 2005-01-01, а у сканов EXIF хранит дату оцифровки, а не съёмки. Что предложил агент. При расхождении года доверять имени папки, а не EXIF. Лежит в папке «2008-09 корпоратив», значит 2008, что бы ни говорил EXIF. По-человечески. Человек, который называл папку, знал год точно, камера нет.

Шаг 6. Гранулярность и финальная полировка

Первый автоматический результат смутил: одно событие дробилось на несколько папок по дням. Поправили в два прохода: день в месяц, а «папки-людей» и длящиеся истории (человек, ремонт) в год, потому что это субъекты, а не разовые события. Поездки и праздники остались помесячно. Для одного 2013 года это сократило около 200 папок-по-дням до 49.

Гранулярность до и после

Гранулярность до и после

Слева дробление по дням, справа: год для людей, месяц для разовых событий.

А дальше начинается то, что отличает «готово» от «вылизано». Проходя руками по уже разобранному архиву, замечаешь артефакты: где-то два почти одинаковых события стоит слить, где-то подправить имя. Но это уже не работа, а причёсывание. И сам факт, что осталась только полировка, говорит о главном: основной объём сделан, и сделан достойно.

Что в итоге

  • по всему OneDrive нашлось около 37 000 изображений и видео, разбросанных не только по фотоархиву, но и по самым разным папкам;

  • около 4 400 файлов лежали в свалках «разобрать», дампах с телефонов и старых бэкапах, к которым иначе не прикоснулись бы, все разобраны и разложены;

  • итог: примерно 36 000 фото и видео в ~490 папках-событиях за 26 лет, структура ГГГГ, человек или поездка плюс ГГГГ-ММ, событие;

  • люди тегами внутри файлов, и в фото, и в видео;

  • дубли в карантине, документы и нефото-материалы отдельно;

  • всё обратимо: каждое перемещение в undo-логе, удалённые письма в Корзине, дубли в карантине.

Стек: Claude Code (оркестратор), czkawka (дедуп), open_clip (теги), Qwen2.5-VL на MLX (описания событий), InsightFace (лица), exiftool (теги в файлы).

Полный импорт в Apple Photos я ещё не завершил. Но это уже дело техники: основная, тяжёлая работа (дедуп, события, лица, единая структура) сделана, и завести готовый архив в любую галерею теперь не страшно, бардак туда уже не переедет.

Итого

Активной работы пара часов. Несколько раз я просто оставлял машину молоть (распознавание лиц по всему архиву, описание событий) и уходил заниматься своими делами. Итог: задача, которую я не сделал бы никогда, закрылась за вечер. А началось всё с уведомления о паре гигабайт в почте.

И главное не в том, что «AI всё сделал сам», а в том что с этим инструментом я быстро собрал себе пайплайн решивший бытовой вопрос с 20 летней историей прокрастинации. Сработала именно связка:

  • тяжёлый перемол (десятки тысяч фото, лиц, хэшей) ушёл на бесплатные локальные модели;

  • фронтир-агент остался на оркестрации и контроле качества, причём проверку он во многом взял на себя;

  • человек на решениях, которые машина знать не может: что папка «разобрать» это не одно событие, что «по дням» плохо, что половина «фотографий» в одной свалке вообще не фото, а сохранённые из интернета референсы.

Те самые два исхода, «руками когда-нибудь» и «докупить квоту», наконец получили рабочую альтернативу. И обошлась она, за счёт локальных моделей, почти даром.

Именно это уже происходит и будет все больше происходить в работе. Будут решаться аналогичные nice to have вещи до которых никогда не дошли бы приоритеты и слот на ресурсы.

Автор: Xronofag

Источник