Перейти к содержанию

Метод извлечения лора ПЧК / Extraction Method

Источник: raw/*.srt — автоматические русские субтитры YouTube (DownSub), 87 файлов. Промежуточный слой: clean/*.txt — субтитры без таймкодов/индексов, склеенные в абзацы с маркером [ЧЧ:ММ:СС] в начале каждого абзаца (≈12 реплик).

Принципы

  1. Цитата важнее пересказа. Везде, где возможно, приводится дословная цитата с таймкодом: > «текст» — [00:12:34].
  2. Исправляются только ошибки распознавания речи и грамматика. Смысл, лексика и порядок слов сохраняются. Если исправление меняет смысл — оригинал приводится в скобках: Вёрджинвальд (в субтитрах: «Верджин вальд», «Вёрджинвальд»).
  3. При сомнении — сохранять и помечать. Ничего не выбрасывается. Маркеры:
  4. ? — неуверенное распознавание имени/термина
  5. [СЛУХ] — неточная расшифровка, вариант реконструкции
  6. [МЕТА] — реплика игроков/ведущего вне игры (шутка, обсуждение правил), но с лорным содержанием
  7. [ПРОТИВОРЕЧИЕ] — конфликт с данными другого выпуска
  8. [НЕЯСНО] — смысл фрагмента не восстановлен
  9. Имена собственные приводятся в наиболее частом написании; все встреченные варианты перечисляются в lore/index/naming.md.
  10. Разделение внутриигрового и внеигрового. Реплики ведущего (Мастера) как нарратив — лор; шутки актёров — помечаются [МЕТА], но сохраняются, если содержат лорный факт.

Структура файла выпуска (lore/episodes/PCHK_NN.md)

# ПЧК #NN — «Название»
Метаданные: video_id, участники, длительность
## Состав партии (игрок → персонаж)
## Синопсис по сценам (с таймкодами)
## Персонажи игроков (PC)
## NPC
## Локации
## Предметы и артефакты
## Способности, заклинания, механики
## Карты / броски / игровые сущности
## Загадки, головоломки, испытания
## Фракции, организации, религии
## Существа и бестиарий
## Лорные факты о мире
## Цитаты
## Неясное и помеченное

Пустые разделы удаляются. Разделы Q&A-выпусков — см. lore/qa/.

Сводные индексы (lore/index/)

characters.md, npcs.md, locations.md, items.md, abilities.md, bestiary.md, factions.md, puzzles.md, timeline.md, naming.md, cosmology.md — собираются после обработки всех выпусков, каждая запись со ссылкой на выпуск и таймкод.

Порядок обработки

  1. Пилот: выпуски 01, 02, 03 и 50, 51, 52 — проверка методики.
  2. Остальные выпуски 04–49 по порядку.
  3. Хроники Леониса Парфия (01–09, 10–20), OST.
  4. Q&A-подкасты (16–50).
  5. Сборка сводных индексов.

Сопоставление имён — только после ручной проверки

Автоматика сама решений не принимает. Каждая привязка живёт в своём проверенном вручную словаре, и сборка читает только их:

Словарь Что связывает
lore/marked/formy/*.md словоформа в тексте → понятие (по полному совпадению)
lore/marked/slovar.md, колонка «На экране» надпись на кадре → понятие; можно сузить до выпуска: ДВАРФ@PCHK_45
lore/marked/kadry.md какой кадр показывать наверху страницы
lore/marked/fandom_stati.md статья фан-вики → понятие
lore/marked/fandom_kartinki.md картинка дампа → понятие, и колонка «Выпуск» для галереи

Ранний контур с tools/candidates.py и lore/matching.md удалён: его 53 проверенные привязки перенесены в slovar.md.

Проверяются три вида решений:

Что Чем опасна ошибка
Псевдонимы — «Ангелин» и «Ангелин Колосажатель» одно лицо две страницы вместо одной или слияние разных героев
Поиск по части имени — искать ли «Балан» отдельно от «Дан Балан» страница набирает чужие цитаты: «Укус ≠ обращение» ловил каждое «укус»
Имена с экрана — «ПОЛИАС» на карточке это Пэлиас чужой портрет в карточке: «КАРГА» приписывалась мечу «Кара Гелиоса»

Полное имя сущности ищется всегда и в проверке не нуждается.


Размеченные ленты выпусков (lore/marked/)

Разбор в lore/episodes/ написан для человека: сущности из него выводятся. Размеченная лента — обратный порядок: сущности в ней объявлены.

Один файл на выпуск сводит расшифровку и разбор кадров на общую ось времени. Речь идёт абзацами с тайм-кодом, кадры — отдельными строками со знаком ▸, у каждой указан вид события, распознанный текст и имя файла кадра. Понятия в речи и в надписях помечены явно: Имя либо как сказано.

Порядок работы:

  1. Внести решение в lore/marked/slovar.md: каноническое имя, тип и — если имя видно на кадре — надпись с экрана. Формы речи там больше не задаются: их держат таблицы formy/.
  2. tools/markup.py PCHK_NN — собрать ленту (без аргументов — все выпуски).

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

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

Таблицы форм — единственный источник сопоставления

Отсечения окончаний больше нет нигде в сборке. Каждая словоформа выписана целиком в lore/marked/formy/ (по файлу на тип понятия) и вручную привязана к понятию; сопоставление идёт по полному совпадению. Прочерк вместо имени означает «это не упоминание».

Почему так: основа «Антошк» после отсечения окончания превращается в «Анто» и находит «Антон» — два разных персонажа склеиваются в одного. Никакая проверка отдельного выпуска этого не ловит, если имена стоят в разных местах корпуса.

У каждой формы указана область действия — файлы, где её проверили. Одно и то же слово в разных выпусках значит разное («Барон» — и Ворон Барон, и барон Эдвард), поэтому решение не переносится автоматически: новый выпуск добавляет свои строки осознанно.

tools/formtable.py   пересобрать таблицы из расставленной разметки
tools/remark.py      снять разметку и поставить заново строго по таблицам

Отсечения окончаний не осталось нигде в сборке: markcand.py, _legacy_stem.py, candidates.py, approved.py, collide.py и режим markup.py --check удалены. Нечёткое сравнение живёт только в imgcat.Matcher(guess=True) — режим сбора кандидатов, из сборки недостижимый: без проверенного словаря матчер бросает исключение.

Разметка рукописных разборов

tools/remark.py расставляет те же ссылки прямо в разборах. Разбор писал человек, портить его нельзя, поэтому скрипт проверяет себя: если снять со свежего файла все ссылки, должен получиться исходный текст буква в букву — иначе файл не записывается. Заголовки не размечаются: по ним разбирается структура файла.

Наследование словаря

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

Как называется статья

Заголовок — то, как имя написано: на карточке броска, на листе персонажа, в статье фан-вики. Не самая полная форма, произнесённая один раз при знакомстве. «Альбом в феврале» прозвучало дважды и нигде не написано, а на карточках стоит «АЛЬБО» и статья сообщества называется так же — значит, статья называется Альбо, а полная форма остаётся в строке «Также» и в разборе.

Проверка простая: если имя понятия ни разу не встречается в написанных источниках, а короткая форма стоит на карточках — заголовок надо менять. Переименование делает tools/renameents.py (SCREEN_NAME): оно переписывает и словарь, и все проставленные ссылки.

Один тип на понятие

Персонаж, сыгранный игроком, остаётся Персонаж и там, где он появляется как NPC. Иначе на одно имя выйдет две статьи. Расхождения ищет и правит tools/normtypes.py.

Слой фан-вики

Сторонний дамп не редактируется. tools/markwiki.py собирает из него производный lore/marked/fandom.md: заголовки, инфобоксы и вступления статей с той же разметкой. Заголовки, которых нет в словаре корпуса, остаются неразмеченными и перечислены в конце файла отдельным списком.


Сверка имени по независимым источникам (tools/crosscheck.py)

Расшифровка — это услышанное, а не написанное, и одного её голоса мало. Имя проверяется сразу по пяти источникам:

Источники строго по старшинству:

Источник Что это
1 кадры надпись на экране: карта мира, лист персонажа, карточка броска — написано авторами шоу
2 фан-вики статьи сообщества, заголовки, имена файлов картинок — написано рукой, но это пересказ
3 lore/tg/ официальный канал и разборы участников
4 clean2/ Whisper large-v3 — услышано
5 raw/*.srt субтитры DownSub — самый ненадёжный источник, берётся в расчёт, только если все остальные молчат совсем

Услышанное не спорит с написанным. «Соливуха» из расшифровки проигрывает надписи СОЛЕВУХА на карте мира из #28: безударные гласные распознаются плохо, а на карте имя написано.

Кадр с картой мира (#28, PCHK_28_part1/img/007_00204.jpg) — отдельно ценный источник: это список топонимов в авторском написании.

Точечный прогон. Если написанных источников нет, а расшифровка сомнительна, надо вырезать ffmpeg'ом полминуты вокруг спорного места и распознать отдельным файлом на GPU-машине (/workspace/spot.py, beam 5 и 10). На коротком куске без окружающего контекста Whisper ошибается заметно реже: «Морелло» из общего прогона на вырезке оказалось «Мариеллой», а «Роберт» из DownSub — «Рупертом» на обоих значениях beam.

uv run --python 3.11 python tools/crosscheck.py Голиаф глиаф

Осторожно с перекрытием: если одно написание — начало другого («Милош Клыков» внутри «Милош Клыкович»), счётчики складываются друг в друга, и сравнивать их нельзя. Такие пары проверяются по контексту, а не по числам.