Из субтитров в текст: убрать тайм-коды — это лёгкая половина
Любой формат субтитров кодирует одно и то же: короткие отрезки речи, приколотые к тайм-кодам. Превратить это обратно в читаемый текст выглядит как скрипт на пять строк — выкинуть числа, выкинуть стрелки, склеить остальное. Запустите такой скрипт на настоящем файле субтитров — и получите почти правильный результат, а это хуже, чем очевидно неправильный, потому что заметить проблему можно только прочитав.
Ломают его две вещи. Субтитры разбиты по ширине экрана, а не по концу предложения, поэтому наивная склейка даёт прозу, порубленную каждые шесть слов. А автоматические субтитры прокручиваются, повторяя текст из реплики в реплику, — при конкатенации каждое предложение выходит по два-три раза. Инструмент разбирается с обоими случаями. Загрузите или вставьте файл выше — результат появится сразу, прямо в этой вкладке браузера.
Проблема ползущих повторов
Вот на чём люди и обжигаются. Автоматические субтитры на YouTube и в большинстве живых систем не выдают отдельных блоков текста. Они выдают движущееся окно, чтобы зритель видел, как слова накапливаются. В файле это выглядит так:
- Реплика 1: съешь же ещё
- Реплика 2: съешь же ещё этих мягких
- Реплика 3: этих мягких французских булок
Склеенные без раздумий, они дают «съешь же ещё съешь же ещё этих мягких этих мягких французских булок» — двенадцать слов там, где сказано было семь. На часовом докладе это увеличивает длину примерно втрое и делает расшифровку бесполезной для чтения, поиска и пересказа.
Лечится это тем, чтобы оставлять от каждой реплики только новое. Для каждой очередной реплики инструмент ищет самую длинную цепочку слов, которая одновременно является хвостом уже собранного текста и началом новой реплики, и выбрасывает её. На примере выше получается «съешь же ещё этих мягких французских булок» ровно один раз. Сравнение идёт с ограниченным окном последних слов, а не со всей расшифровкой: на трёхчасовом файле это остаётся быстрым и не удаляет фразу, которая законно повторилась через двадцать минут.
Как собрать предложения обратно
Строка субтитра рассчитана на экран: примерно сорок символов, по две строки за раз, разрыв там, где текст упёрся в край. Предложения спокойно растягиваются на три-четыре реплики. Оставить по строке на реплику — получить документ, который формально и есть расшифровка, а практически нечитаем.
Режим абзацев накапливает реплики и делает разрыв, когда сходятся два условия: текста набралось на абзац и текущая реплика заканчивается знаком конца предложения. Так разрыв никогда не попадает в середину мысли. Жёсткий потолок всё же заставляет разорвать абзац рано или поздно, потому что некоторые говорят очень долго без единой точки, а сплошная стена текста нечитаема по-своему. Смена говорящего всегда начинает новый абзац — это важно для интервью и панельных дискуссий.
Четыре формата, одна идея
Формат определяется по содержимому самого файла, а не по расширению: файлы субтитров переименовывают постоянно, и .txt с данными SubRip внутри — обычное дело.
- SubRip (.srt) — числовой индекс, диапазон тайм-кодов с запятой в дробной части, затем текст. Самый распространённый и самый простой формат.
- WebVTT (.vtt) — стандарт браузеров. Точка вместо запятой в дробной части плюс необязательные блоки
NOTE,STYLEиREGION, которые речью не являются и убираются до разбора. VTT ещё разрешает инлайновую разметку:<v Speaker>называет говорящего,<c.classname>задаёт оформление, а голые метки времени внутри реплики подсвечивают слова по-караоке. Всё это разворачивается, а тег голоса становится подписью говорящего. - YouTube (.sbv) — пара тайм-кодов через запятую на отдельной строке, затем текст. Ни индекса, ни разметки.
- Advanced SubStation (.ass и .ssa) — список событий с объявленным порядком колонок. Парсер читает эту строку
Format:, а не полагается на позиции: поле с текстом стоит последним именно затем, чтобы в нём могли быть запятые. Блоки переопределений в фигурных скобках — это указания по оформлению, они убираются; переносы\Nстановятся пробелами. Колонка Name, если она заполнена, — это говорящий.
Говорящие, звуковые эффекты и что оставлять
Атрибуция говорящего приходит тремя разными путями в зависимости от формата: отдельным полем в ASS, тегом голоса в VTT или голым соглашением ИМЯ: в начале строки в SRT, где поля для говорящего нет вовсе. Все три распознаются и приводятся к одному виду на выходе. Эвристика для третьего случая нарочно узкая — цепочка прописных букв, за которой стоит двоеточие, — потому что строчный префикс подошёл бы к обычным предложениям с двоеточиями и растерзал бы расшифровку.
Скобочные звуковые пометки вроде [MUSIC], (laughter) и [APPLAUSE] по умолчанию сохраняются, а переключатель их убирает. Что правильно — целиком зависит от задачи: для поискового архива или записи для доступности они часть содержания, а для доклада, который вы отдаёте модели на пересказ, — шум.
Три формы вывода
Пресеты покрывают то, чего люди обычно и хотят. Чистая расшифровка — сплошные абзацы без тайм-кодов: читать, цитировать, отдавать модели. С метками времени сохраняет абзацы, но помечает каждый временем начала — это то, что нужно, когда расшифровка служит способом вернуться к моменту в видео. Строки субтитров оставляет по строке на реплику с её тайм-кодом и без удаления повторов — ближайшее к исходному файлу, полезно, когда вы проверяете сами субтитры, а не читаете их насквозь.
Рядом с результатом инструмент сообщает распознанный формат, число реплик, число слов, покрытую длительность и количество удалённых повторов. Последняя цифра — самая честная: если она большая, источник был автоматическим и ползущим, и видно, какая доля сырого файла была повторами.
Ничего не покидает браузер
Файлы субтитров не всегда публичные. Их порождают записи интервью, внутренние общие созвоны, судебные заседания, врачебные консультации и невыпущенные материалы. Разбор идёт на JavaScript в этой вкладке, поэтому файл читается локально и никуда не загружается. Поэтому же конвертация мгновенная, а смена настройки перерисовывает результат сразу, а не гоняет ещё один запрос туда-обратно.