Как исправить кодировку субтитров SRT без потери исходного текста
Диагностируйте искаженный текст в SRT, отличайте ошибки декодирования от безвозвратно утерянных символов и создавайте копию в UTF-8 с помощью надежного Python-скрипта.

Если в субтитрах SRT отображается café вместо café, не спешите сразу пересохранять файл в UTF-8. Сначала сохраните нетронутую копию исходных байтов, найдите кодировку, которая корректно отображает слова, и запишите проверенный текст в отдельный файл. Пересохранение неверно прочитанных символов в новой кодировке лишь зафиксирует ошибку навсегда.
Здесь важно различать валидную кодировку и корректный текст. В приведенном ниже эксперименте с двумя репликами один поврежденный файл успешно проходит строгую проверку на UTF-8 и не содержит символов замены. При этом французский текст в нем все равно отображается неверно. Другой файл проходит ту же проверку, но шесть исходных символов в нем уже безвозвратно заменены на �.
В этом руководстве представлен локальный Python-инструмент для проверки и конвертации, исходные файлы для загрузки и воспроизводимый тест. Инструмент предназначен для диагностики на уровне файлов и явного перекодирования — он не занимается автоматическим угадыванием кодировок, синхронизацией видео и не обещает восстановить безвозвратно утерянные буквы.
Шаг 1. Определите, что именно повреждено
Расширение .srt указывает лишь на формат субтитров, но не гарантирует конкретную кодировку. SRT содержит номера реплик, таймкоды, текст и разделители; в описании формата SRT Библиотеки Конгресса США он характеризуется как обычный текстовый формат без единого стандарта кодирования символов.
Видимые искажения — это повод разобраться в проблеме, а не готовый диагноз:
| Что вы видите | Что проверить | Следующий шаг |
|---|---|---|
| Диакритические знаки или символы отображаются некорректно в одном приложении | Отображается ли текст правильно, если открыть нетронутый файл с явным указанием исходной кодировки? | Если да, используйте именно это явное декодирование перед экспортом новой копии. |
café остается в файле, корректно прочитанном как UTF-8 | Был ли UTF-8 ранее ошибочно прочитан как другая кодировка и сохранен? | Вернитесь к исходным байтам или выясните точную историю преобразования. Повторное сохранение в UTF-8 не исправит проблему. |
� появляется на месте буквы или символа | Действительно ли U+FFFD сохранен в файле, или текущая программа подставляет его при отображении нераспознанных байтов? | Изучите исходный файл без изменений. Сохраненный символ замены не позволяет узнать, каким был исходный символ. |
| В плеере видны пустые квадратики, но в надежном текстовом редакторе символы отображаются корректно | Правильны ли исходные кодовые точки? Тот ли файл открыт в плеере? | Прежде чем менять файл, проверьте настройки декодирования, поддержку шрифтов или параметры рендеринга в плеере. |
Символы и их отображение на экране — это разные вещи. В документации Python по Unicode проводится четкое различие между кодовыми точками и глифами шрифта. Корректный текст в редакторе указывает на вероятную проблему на стороне плеера, но не гарантирует, что установка определенного шрифта все исправит. Никакие конкретные шрифты или плееры в рамках этой статьи не тестировались.
Создайте резервную копию байтов, затем проверьте декодирование
Скачайте скрипт subtitle_encoding.py и поместите его рядом с нужным файлом SRT. Для выполнения этих команд потребуется установленный Python 3 без каких-либо сторонних пакетов. Локальные тесты проводились на Python 3.14.3 под macOS. Если на Windows вы используете лаунчер Python, замените py -3 на python3; эта среда здесь не тестировалась.
Откройте терминал в этой папке. В приведенных примерах замените input.srt на фактическое имя вашего файла. Если в путях есть пробелы, заключайте их в кавычки.
Создайте нетронутую копию
python3 subtitle_encoding.py backup "input.srt" "original-bytes.srt"
Целевой файл не должен существовать заранее. Утилита копирует байты без декодирования, перечитывает созданную копию и выводит ее хеш SHA-256. Она также отклоняет путь к источнику, если он указан как целевой. Сохраните эту резервную копию даже после того, как получите рабочий файл субтитров.
Проверьте UTF-8 без сохранения изменений
python3 subtitle_encoding.py inspect "original-bytes.srt"
Отчет включает strict_utf8, utf8_bom, выбранный вариант декодирования и — если декодирование прошло успешно — предпросмотр текста, а также replacement_characters . В текстовом представлении по умолчанию используется utf-8-sig, корректно обрабатывающий начальную сигнатуру UTF-8.
strict_utf8: falseозначает, что байты не прошли проверку UTF-8. Это не подсказывает, какая именно кодировка верна.strict_utf8: trueозначает, что их можно декодировать как UTF-8. Это не гарантирует, что сам текст правильный.- Ненулевое количество замен означает, что выбранное декодирование привело к появлению символов U+FFFD. Обязательно проверьте их перед созданием нового файла.
Режим проверки выводит безопасный ASCII-совместимый JSON, чтобы шрифт терминала не скрыл реальную кодовую точку: \u00e9 означает é, а \ufffd обозначает символ замены. Чтобы детально изучить подозрительную строку, запросите ее физический номер в файле, а не номер реплики:
python3 subtitle_encoding.py inspect "original-bytes.srt" --encoding cp1252 --line 3
Это тест только для чтения для Windows-1252, кодека cp1252 в Python. Используйте его, если настройки экспорта или история файла подтверждают этот выбор, а не просто потому, что в данном примере оказался французский язык. Отчет по строке называет каждый символ и выводит его кодовую точку; U+20AC — это знак евро.
Выбирайте кодировку на основе фактов, а не по первому удачному предпросмотру
Узнайте у создателя файла фактическую кодировку экспорта, проверьте настройки программы-экспортера или сверьтесь с надежным оригинальным транскриптом. Проверьте имена с диакритикой, пунктуацию, символы валют и типичные строки по всему файлу. Если вы не знаете языка, даже успешно сработавший декодер не сможет выполнить эту проверку за вас.
Обозначение «ANSI» слишком неточно, чтобы выбрать по нему исходный кодек. Windows-1252 и Latin-1 также не взаимозаменяемы. В приведенном эксперименте одиночный байт 80 декодируется как € в кодировке cp1252, но как управляющий символ U+0080 при кодировке latin-1. Обе операции завершаются успешно. Лишь знание исходного контекста позволяет понять, какой вариант задумывался изначально.
Для других языков могут использоваться иные устаревшие кодировки, однако название языка само по себе не определяет точную кодировку. Если происхождение файла неизвестно, а варианты прочтения не совпадают, остановитесь перед конвертацией и найдите более надежные свидетельства об источнике.
Конвертируйте только тогда, когда исходный текст стал читаемым
Если для исходного файла подтверждена кодировка Windows-1252, создайте отдельный файл в UTF-8:
python3 subtitle_encoding.py convert "original-bytes.srt" "repaired-utf8.srt" --from-encoding cp1252
python3 subtitle_encoding.py inspect "repaired-utf8.srt"
Конвертер строго декодирует весь исходный файл, кодирует этот текст в UTF-8, проверяет, что декодирование полученного результата возвращает тот же самый текст, и считывает записанные байты обратно. Он не изменяет номера реплик, таймкоды, реплики, теги или символы окончания строк. Новая последовательность байтов может отличаться, даже если декодированный текст остается в точности тем же.
Он принципиально отказывается:
- перезаписывать существующий файл назначения;
- продолжать работу при ошибке строгого декодирования; или
- записывать текст, содержащий U+FFFD, даже если этот символ присутствовал намеренно.
Последнее ограничение обусловлено мерами предосторожности: этот инструмент не может определить, что именно должен был обозначать символ замены. Удаление этого символа ради успешного выполнения команды лишь уничтожило бы улики, а не восстановило текст. В документации по обработчикам ошибок Python объясняется, чем режимы replace и ignore отличаются от строгого декодирования: они подменяют или отбрасывают проблемные данные. Ни тому, ни другому не место на этом этапе конвертации.
При возникновении ошибки ввода-вывода не используйте поврежденный результат. Может остаться незавершенный новый файл; сохраните оригинал и выберите новое имя файла назначения для следующей попытки. Подробное описание работы инструмента и инструкция по его использованию приведены в файле README для скачивания.
А как насчет UTF-8 с BOM?
UTF-8 BOM представляет собой начальную последовательность байтов EF BB BF. В Python utf-8-sig кодек считывает эту сигнатуру при декодировании и добавляет ее при кодировании.
Если исходный файл заведомо в кодировке UTF-8 с BOM, используйте --from-encoding utf-8-sig. Обычно утилита сохраняет UTF-8 без BOM; добавляйте --with-bom только в том случае, если этого явно требует целевая программа. Изменение BOM не сможет превратить café в café. Данный эксперимент не гарантирует совместимость с каким-либо конкретным плеером, редактором или платформой загрузки.
Пять небольших файлов показывают, почему валидности UTF-8 недостаточно
В эксперименте используются две полностью составленные вручную реплики французских субтитров. Они не взяты из фильма, от клиента или из сервиса перевода:
1
00:00:01,000 --> 00:00:04,000
Émile dit : « Le prix est de 12,50 €. »
2
00:00:05,000 --> 00:00:08,000
Le café est fermé.
13 сентября 2026 года скрипт на базе стандартной библиотеки Python 3.14.3 сгенерировал пять байтовых представлений и сравнил каждое из них с исходным эталоном. Это детерминированные проверки байтов и строк, а не бенчмарк качества перевода. Сохраняйте файлы по ссылкам на диск, а не копируйте их текст из окна браузера: вся суть эксперимента именно в различии байтов.
| Файл для загрузки | Байты | Строгий UTF-8? | Корректный текст при декодировании как UTF-8? | Содержит U+FFFD в тексте UTF-8 |
|---|---|---|---|---|
| Исходный UTF-8 | 132 | Да | Да | 0 |
| Исходный Windows-1252 | 125 | Нет | Не декодируется как UTF-8; корректен в cp1252 | Не применимо |
| Ошибочный декодер, пересохранен как UTF-8 | 147 | Да | Нет | 0 |
| Символы подстановки, пересохранен как UTF-8 | 137 | Да | Нет | 6 |
| Корректно преобразованный UTF-8 | 132 | Да | Да | 0 |
В каждой копии сохранены те же две строки с временными метками. Корректно преобразованный файл байт в байт совпадает с оригиналом в UTF-8. Два поврежденных файла в UTF-8 доказывают более узкий, но важный факт: ни валидная кодировка, ни неизмененные таймкоды сами по себе не гарантируют правильность текста субтитров. Совпадение таймкодов также ничего не говорит о том, подойдет ли эта тестовая дорожка к реальному видео.
Чтобы воспроизвести эти пять файлов самостоятельно, скачайте reproduce.py и запустите его, указав имя еще не существующей папки:
python3 reproduce.py encoding-experiment
Скрипт создаст тестовые файлы и results.json , содержащий полный текст, преобразования, хеши, версию среды выполнения и проверки. Сравните его с зафиксированными результатами эксперимента; дата и время генерации будут отличаться. Скрипты и исходные учебные файлы распространяются под лицензией MIT.
Проверки локального конвертера также охватывали отказ при наличии существующего выходного файла, отказ при указании исходного пути, сбой из-за неподходящего кодека, отказ при обнаружении U+FFFD, сохранение CRLF и явную запись BOM. Эти тесты проверяют корректность работы инструмента с файлами. Они не оценивают рендеринг в медиаплеерах, синхронизацию с реальным видео или перевод в BookTranslator.
Если поврежденные символы уже были сохранены
Сохраненные кракозябры: выясните точную предысторию
Наша копия с кракозябрами возникла по известной цепочке: исходные байты UTF-8 были декодированы как Windows-1252, а затем эти ошибочные символы сохранили в UTF-8. В итоге получились символы вроде café и поврежденная последовательность знака евро €.
Поскольку в этом конкретном преобразовании байты не были потеряны, тестовый скрипт может обратить его вспять: повторно закодировать поврежденный текст через cp1252, а затем декодировать полученные байты как UTF-8. Скрипт сверяет восстановленный текст с оригиналом.
Это подтверждает работоспособность метода именно для этой конкретной цепочки, а не является универсальным указанием применять функцию «исправить кракозябры» ко всем SRT без разбора. Файл может содержать корректные символы, следы нескольких разных сбоев или текст, уже искаженный предыдущей попыткой исправления. Всегда отдавайте предпочтение нетронутому исходнику и штатному процессу конвертации. Если же остался только файл с сохраненными кракозябрами, сохраните его копию и точно выясните, как именно возникли искажения, прежде чем пытаться выполнить обратное преобразование на отдельной копии.
Сохранённые символы замены: недостающая буква здесь просто не закодирована
Пример с безвозвратной потерей был создан декодированием байтов Windows-1252 как UTF-8 с включённой подстановкой и последующим сохранением результата. Различные исходные символы превратились в один и тот же маркер � . Сохранённый маркер не содержит достаточно информации, чтобы определить, какой именно исходный символ находился на этой позиции.
Не путайте это с ситуацией, когда вы просто видите � в приложении. Если исходные байты не были затронуты, правильное декодирование всё ещё может восстановить текст — как это происходит с нашим исходником в Windows-1252. Проверьте сам исходник, прежде чем констатировать потерю данных.
Если в единственной оставшейся копии отсутствующий текст действительно был заменён на U+FFFD или обычные вопросительные знаки, выполните повторный экспорт, запросите чистый исходник заново или сверьте ручную расшифровку с надёжным материалом. Обычный вопросительный знак также может быть штатным знаком препинания; само по себе его наличие ничего не доказывает. А правдоподобный вариант, предложенный нейросетью, — это всего лишь догадка, а не восстановленные данные из файла.
Главное — читаемый исходник, а не просто успешное выполнение команды
Прежде чем признать файл исправленным, сравните характерные слова и символы с надёжным источником, убедитесь, что строки реплик и таймкодов не изменились, и откройте новый файл в том приложении, где он будет использоваться. Скрипт сохраняет декодированный текст, но не проверяет синтаксис SRT и не заменяет тестирование при воспроизведении.
Если теперь субтитры читаются без проблем и перевод не требуется, задача решена. Если же вам нужен визуальный просмотр на видео или дальнейшее редактирование, наш обзор программ для работы с субтитрами поможет разобраться в назначении различных инструментов.
Только когда исходный текст приведён в порядок — и вам действительно нужен перевод на другой язык — переходите к переводчику субтитров от BookTranslator и процессу перевода субтитров с помощью ИИ. Рассматривайте исправление кодировки, перевод и финальный просмотр дорожки как отдельные задачи. Успех одной из них не гарантирует правильности остальных.
Похожие статьи





