Jak naprawić kodowanie napisów SRT bez utraty oryginalnego tekstu
Zdiagnozuj zniekształcony tekst w plikach SRT, odróżnij błędy dekodowania od utraconych znaków i stwórz osobną kopię w UTF-8 za pomocą bezpiecznego narzędzia w Pythonie i powtarzalnych próbek.

Jeśli w Twoich napisach SRT pojawia się café zamiast café, nie zapisuj od razu pliku jako UTF-8. Najpierw zachowaj nienaruszoną kopię jego bajtów, znajdź kodowanie, które odtworzy poprawne słowa, i zapisz zweryfikowany tekst w osobnym pliku. Zapisanie błędnych znaków w nowym kodowaniu utrwali jedynie te błędy.
Kluczowa różnica polega na rozróżnieniu między poprawnym kodowaniem a prawidłowym tekstem. W poniższym eksperymencie z dwoma kwestiami jeden uszkodzony plik przechodzi rygorystyczną weryfikację UTF-8 i nie zawiera znaków zastępczych. Mimo to tekst w języku francuskim nadal jest błędny. Inny plik przechodzi ten sam test po tym, jak sześć oryginalnych znaków zostało zastąpionych przez �.
W tym poradniku znajdziesz lokalne narzędzie w Pythonie do analizy i konwersji, pliki źródłowe do pobrania oraz powtarzalny test. Narzędzie to służy do diagnozy na poziomie plików i jawnej konwersji — nie zapewnia automatycznego wykrywania kodowania, synchronizacji wideo ani gwarancji odzyskania brakujących liter.
Najpierw ustal, co dokładnie jest uszkodzone
Rozszerzenie .srt określa format napisów, a nie gwarantowane kodowanie. SRT zawiera numery kwestii, znaczniki czasu, tekst i separatory; według dokumentacji formatu SRT w Bibliotece Kongresu jest to zwykły tekst bez jednego narzuconego standardu kodowania znaków.
Potraktuj widoczny objaw jako powód do zbadania problemu, a nie jako gotową diagnozę:
| Widoczny objaw | Co sprawdzić | Właściwy kolejny krok |
|---|---|---|
| Znaki diakrytyczne lub symbole wyglądają nieprawidłowo w jednej aplikacji | Czy ponowne otwarcie nienaruszonego pliku przy użyciu znanego kodowania źródłowego daje poprawny tekst? | Jeśli tak, użyj tego jawnego dekodowania przed wyeksportowaniem nowej kopii. |
café pozostaje w pliku poprawnie odczytanym jako UTF-8 | Czy plik UTF-8 został wcześniej błędnie odczytany w innym kodowaniu i w tej postaci zapisany? | Wróć do oryginalnych bajtów lub przeanalizuj dokładną historię konwersji. Ponowne zapisanie w UTF-8 nie jest naprawą. |
� pojawia się w miejscu litery lub symbolu | Czy znak U+FFFD jest rzeczywiście zapisany w pliku, czy to bieżąca aplikacja wstawia go podczas wyświetlania niemożliwych do zdekodowania bajtów? | Zbadaj nienaruszony plik źródłowy. Zapisany znak zastępczy nie pozwala ustalić pierwotnego znaku. |
| W odtwarzaczu pojawiają się kwadraty, ale zaufany edytor tekstu pokazuje właściwe znaki | Czy bazowe punkty kodowe są poprawne? Czy odtwarzacz na pewno wczytuje ten sam plik? | Zanim zmodyfikujesz plik, sprawdź dekodowanie w odtwarzaczu, obsługę znaków w używanej czcionce lub ustawienia renderowania. |
Znaki i ich wyświetlane kształty to dwie różne rzeczy. Dokumentacja Unicode w Pythonie odróżnia punkty kodowe od glifów renderowanych przez czcionkę. Poprawny tekst w edytorze sugeruje problem po stronie odtwarzacza, ale nie dowodzi, że zainstalowanie konkretnej czcionki go rozwiąże. Na potrzeby tego artykułu nie testowano żadnej czcionki ani odtwarzacza.
Zabezpiecz bajty, a następnie sprawdź dekodowanie
Pobierz subtitle_encoding.py i umieść go obok pliku SRT, który chcesz zbadać. Te polecenia wymagają zainstalowanego Pythona 3 i nie potrzebują żadnych dodatkowych pakietów. Lokalne testy przeprowadzono przy użyciu Pythona 3.14.3 w systemie macOS. Jeśli Twoja instalacja w systemie Windows korzysta z programu uruchamiającego Python, zastąp py -3 poleceniem python3; to środowisko nie było tutaj testowane.
Otwórz terminal w tym folderze. W poniższych przykładach zastąp input.srt rzeczywistą nazwą swojego pliku. Ścieżki zawierające spacje pozostaw w cudzysłowach.
Utwórz nienaruszoną kopię
python3 subtitle_encoding.py backup "input.srt" "original-bytes.srt"
Plik docelowy nie może jeszcze istnieć. Narzędzie kopiuje bajty bez ich dekodowania, odczytuje kopię i wyświetla jej skrót SHA-256. Blokuje także użycie ścieżki źródłowej jako docelowej. Zachowaj tę kopię zapasową nawet po przygotowaniu działającego pliku z napisami.
Sprawdź UTF-8 bez zapisywania zmian
python3 subtitle_encoding.py inspect "original-bytes.srt"
Raport zawiera strict_utf8, utf8_bom, wybrane dekodowanie oraz — jeśli dekodowanie się powiedzie — podgląd tekstu i replacement_characters . Domyślny widok tekstu używa utf-8-sig, co pozwala na obsługę początkowej sygnatury UTF-8.
strict_utf8: falseoznacza, że bajty nie przeszły pomyślnie weryfikacji UTF-8. To nie wskazuje jednak, jakie inne kodowanie jest prawidłowe.strict_utf8: trueoznacza, że można je zdekodować jako UTF-8. To nie oznacza jednak, że tekst jest poprawny.- Liczba znaków zastępczych większa od zera oznacza, że wybrane dekodowanie wygenerowało znaki U+FFFD. Sprawdź je przed utworzeniem nowego pliku.
Inspekcja wyświetla bezpieczny dla standardu ASCII format JSON, dzięki czemu czcionka terminala nie zafałszuje tożsamości znaku: \u00e9 oznacza é, a \ufffd oznacza znak zastępczy. Aby szczegółowo zbadać podejrzany wiersz, podaj jego fizyczny numer wiersza — a nie numer sekwencji napisów:
python3 subtitle_encoding.py inspect "original-bytes.srt" --encoding cp1252 --line 3
To jest test tylko do odczytu dla Windows-1252, kodeka Pythona cp1252 . Używaj go wtedy, gdy ustawienia eksportu lub pochodzenie pliku uzasadniają ten wybór, a nie dlatego, że akurat w tym przykładzie pojawił się język francuski. Raport wiersza podaje nazwę każdego znaku i wyświetla jego punkt kodowy; U+20AC to znak euro.
Wybieraj kodowanie na podstawie dowodów, a nie pierwszego udanego podglądu
Zapytaj twórcę pliku o rzeczywiste kodowanie eksportu, sprawdź ustawienia programu eksportującego lub porównaj zawartość z zaufanym oryginalnym transkryptem. Przejrzyj imiona i nazwiska ze znakami diakrytycznymi, interpunkcję, symbole walut oraz reprezentatywne linie w całym pliku. Jeśli nie znasz danego języka, sam fakt poprawnego zdekodowania tekstu przez narzędzie nie zastąpi takiej weryfikacji.
Określenie „ANSI” nie jest wystarczająco precyzyjne, aby dobrać odpowiedni kodek źródłowy. Standardy Windows-1252 i Latin-1 również nie są wymienne. W zaprezentowanym eksperymencie pojedynczy bajt 80 dekoduje się do € w kodowaniu cp1252, ale do znaku sterującego U+0080 w kodowaniu latin-1. Obie operacje kończą się sukcesem. Tylko wiedza o pochodzeniu pliku pozwala stwierdzić, który wariant jest poprawny.
Inne języki mogą korzystać z odmiennych starszych kodowań, ale sama nazwa języka nie przesądza o wyborze konkretnego z nich. Jeśli historia pliku jest nieznana, a proponowane odczyty się wykluczają, wstrzymaj się z konwersją i zdobądź pewniejsze informacje o źródle.
Konwertuj dopiero wtedy, gdy tekst źródłowy jest czytelny
W przypadku pliku źródłowego potwierdzonego jako Windows-1252 utwórz osobny plik UTF-8:
python3 subtitle_encoding.py convert "original-bytes.srt" "repaired-utf8.srt" --from-encoding cp1252
python3 subtitle_encoding.py inspect "repaired-utf8.srt"
Konwerter rygorystycznie dekoduje cały plik źródłowy, koduje ten tekst w formacie UTF-8, sprawdza, czy ponowne zdekodowanie wyniku zwraca ten sam tekst, i odczytuje zapisane bajty. Nie modyfikuje numerów napisów, znaczników czasu, dialogów, tagów ani znaków końca linii. Nowa sekwencja bajtów może być inna, nawet jeśli zdekodowany tekst pozostaje identyczny.
Narzędzie celowo odmawia:
- nadpisania istniejącego pliku docelowego;
- kontynuowania pracy po napotkaniu błędu w trybie ścisłego dekodowania; oraz
- zapisu tekstu zawierającego znak U+FFFD, nawet jeśli znalazł się tam celowo.
To ostatnie ograniczenie wynika z ostrożności: narzędzie to nie jest w stanie rozstrzygnąć, co miał oznaczać znak zastępczy. Usunięcie go tylko po to, by polecenie się powiodło, zatarłoby ślady, zamiast przywrócić tekst. Dostępna dla języka Python dokumentacja obsługi błędów wyjaśnia, dlaczego opcje replace oraz ignore różnią się od rygorystycznego dekodowania: zastępują one lub odrzucają problematyczne dane. Żadna z nich nie powinna być stosowana na tym etapie konwersji.
W przypadku wystąpienia błędu wejścia/wyjścia nie używaj uszkodzonego wyniku. Może pozostać częściowo zapisany nowy plik; zachowaj oryginał i przy kolejnej próbie użyj nowej nazwy pliku docelowego. Pełny opis działania narzędzia i instrukcję obsługi znajdziesz w pliku README do pobrania.
A co z UTF-8 z BOM?
BOM w UTF-8 to początkowa sekwencja bajtów EF BB BF. Kodek utf-8-sig w Pythonie usuwa tę sygnaturę podczas dekodowania i dodaje ją podczas kodowania.
W przypadku potwierdzonego pliku źródłowego UTF-8 ze znacznikiem BOM użyj --from-encoding utf-8-sig. Narzędzie standardowo zapisuje pliki w formacie UTF-8 bez BOM; dodawaj --with-bom tylko wtedy, gdy wymagają tego specyfikacje aplikacji docelowej. Zmiana znacznika BOM nie zamieni café na café. Ten eksperyment nie gwarantuje kompatybilności z żadnym konkretnym odtwarzaczem, edytorem ani platformą do przesyłania plików.
Pięć małych plików pokazuje, dlaczego poprawność UTF-8 to za mało
W eksperymencie wykorzystano dwie całkowicie autorskie kwestie francuskich napisów. Nie pochodzą one z filmu, od klienta ani z żadnego produktu tłumaczeniowego:
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 września 2026 r. skrypt oparty na bibliotece standardowej języka Python 3.14.3 wygenerował pięć reprezentacji bajtowych i porównał każdą z nich ze znanym tekstem źródłowym. Są to deterministyczne testy bajtów i ciągów znaków, a nie test porównawczy jakości tłumaczenia. Zapisz podlinkowane pliki na dysku, zamiast kopiować ich podgląd z przeglądarki: to właśnie różnice w bajtach stanowią sedno tego eksperymentu.
| Plik do pobrania | Bajty | Ścisły UTF-8? | Poprawny tekst po zdekodowaniu jako UTF-8? | Zapisano U+FFFD w tekście UTF-8 |
|---|---|---|---|---|
| Oryginalny UTF-8 | 132 | Tak | Tak | 0 |
| Oryginalny Windows-1252 | 125 | Nie | Niemożliwy do zdekodowania jako UTF-8; poprawny przy cp1252 | Nie dotyczy |
| Błędny dekoder, ponownie zapisany jako UTF-8 | 147 | Tak | Nie | 0 |
| Znaki zastępcze, ponownie zapisane jako UTF-8 | 137 | Tak | Nie | 6 |
| Poprawnie przekonwertowane UTF-8 | 132 | Tak | Tak | 0 |
Każda kopia zachowuje te same dwa ciągi sygnatur czasowych. Poprawnie przekonwertowany plik jest bajt po bajcie identyczny z oryginałem w formacie UTF-8. Dwa uszkodzone pliki UTF-8 dowodzą czegoś węższego, ale przydatnego: ani poprawne kodowanie, ani niezmienione sygnatury czasowe nie świadczą o prawidłowej treści napisów. Zgodność sygnatur czasowych nie mówi również nic o tym, czy ta wymyślona ścieżka pasuje do prawdziwego wideo.
Aby samodzielnie odtworzyć te pięć plików, pobierz reproduce.py i uruchom go, podając nazwę katalogu, który jeszcze nie istnieje:
python3 reproduce.py encoding-experiment
Skrypt zapisuje pliki testowe oraz results.json zawierający pełny tekst, przekształcenia, skróty hash, wersję środowiska wykonawczego i asercje. Porównaj go z zapisanymi wynikami eksperymentu; sygnatura czasowa generowania będzie się różnić. Skrypty i oryginalne pliki demonstracyjne zawierają licencję MIT.
Testy lokalnego konwertera sprawdzały również odmowę nadpisania istniejącego pliku wyjściowego, odmowę w przypadku ścieżki źródłowej, błąd nieprawidłowego kodeka, odmowę przy znaku U+FFFD, zachowanie znaków CRLF oraz jawne generowanie BOM. Testy te weryfikują zachowanie narzędzia na plikach. Nie sprawdzają renderowania w odtwarzaczu, synchronizacji z prawdziwymi multimediami ani tłumaczenia w BookTranslator.
Co zrobić, jeśli uszkodzone znaki zostały już zapisane
Zapisane mojibake: zbadaj dokładną historię
Nasza kopia mojibake powstała w wyniku znanego schematu: oryginalne bajty UTF-8 zostały zdekodowane jako Windows-1252, a następnie te błędne znaki zapisano jako UTF-8. W rezultacie otrzymujemy café oraz uszkodzoną sekwencję symbolu euro €.
Ponieważ w tej konkretnej transformacji nie utracono żadnych bajtów, skrypt odtwarzający może ją odwrócić: ponownie zakodować błędny tekst za pomocą cp1252, a następnie zdekodować wynikowe bajty jako UTF-8. Weryfikuje on odzyskany tekst względem oryginału.
To dowód na działanie tego konkretnego schematu, a nie instrukcja, aby stosować globalną operację „naprawy mojibake” do każdego pliku SRT. Plik może zawierać prawidłowe znaki, mieszaną historię kodowania lub tekst zmieniony już przez wcześniejszą próbę naprawy. Zawsze w pierwszej kolejności korzystaj z nienaruszonego pliku źródłowego i standardowej ścieżki konwersji. Jeśli dysponujesz tylko zapisanym mojibake, zabezpiecz ten plik i ustal, jak powstał, zanim podejmiesz próbę transformacji odwrotnej na innej kopii.
Zapisane znaki zastępcze: brakująca litera nie jest tam w ogóle zakodowana
Plik testowy z utratą danych powstał przez zdekodowanie bajtów Windows-1252 jako UTF-8 z włączoną opcją zastępowania znaków, a następnie zapisanie wyniku. Różne pierwotne znaki zamieniły się w ten sam znacznik � . Zapisany znacznik nie niesie wystarczających informacji, aby ustalić, jaki pierwotny znak znajdował się na tej pozycji.
Nie należy mylić tego ze zwykłym widokiem � w aplikacji. Jeśli oryginalne bajty pozostały nienaruszone, poprawne dekodowanie może nadal odzyskać tekst — tak jak ma to miejsce w przypadku naszego źródła Windows-1252. Zbadaj plik źródłowy przed stwierdzeniem trwałej utraty danych.
Jeśli w jedynej zachowanej kopii brakujący tekst faktycznie zastąpiono znakami U+FFFD lub zwykłymi znakami zapytania, wyeksportuj dane ponownie, pozyskaj czyste źródło lub zweryfikuj ręczną transkrypcję z wiarygodnymi materiałami. Zwykły znak zapytania może być także poprawnym znakiem interpunkcyjnym; sama jego obecność niczego nie dowodzi. Prawdopodobne dopasowanie wygenerowane przez model to tylko domysł, a nie odzyskane dane z pliku.
Zadbaj o czytelne źródło — nie poprzestawaj na udanym poleceniu
Przed zaakceptowaniem naprawionego pliku porównaj reprezentatywne słowa i symbole z zaufanym źródłem, upewnij się, że linie napisów i znaczniki czasu nie uległy zmianie, a następnie otwórz nowy plik w docelowej aplikacji. Skrypt jedynie zachowuje zdekodowany tekst; nie jest walidatorem składni SRT ani testem poprawności odtwarzania.
Jeśli napisy są już czytelne i nie potrzebujesz innej wersji językowej, zadanie jest ukończone. Jeżeli konieczny jest bezpośredni podgląd wideo lub dalsza edycja, nasze porównanie programów do napisów wyjaśnia przeznaczenie poszczególnych narzędzi.
Dopiero gdy tekst źródłowy jest w pełni poprawny — i faktycznie potrzebujesz innego języka — przejdź do Tłumacza napisów w BookTranslator oraz procesu tłumaczenia napisów z wykorzystaniem AI. Naprawę kodowania, tłumaczenie i weryfikację gotowej ścieżki traktuj jako oddzielne zadania. Pomyślne ukończenie jednego z nich nie gwarantuje powodzenia pozostałych.
Powiązane wpisy





