Skip to content

Guides

Subtitles showing weird characters: fixing the encoding

The timing is perfect and the words are wrong: café comes out as café, or as caf?, or a whole Russian line reads as Ïðèâåò. Nothing is corrupt. The file was written in one text encoding and read in another, and the symptom tells you which way round. One conversion to UTF-8 ends it for every player you will ever use.

Read the symptom first

A subtitle file is a run of bytes, and every letter beyond plain ASCII is stored differently depending on which encoding the author used. The player has to guess the encoding to turn those bytes back into letters, and when it guesses wrong the wrong letters have a shape. Three shapes cover nearly every case:

  • Pairs of symbols where one accented letter should be: é for é, ñ for ñ, ’ for a curly apostrophe. The file is UTF-8, where an accented letter is two bytes, and the player is reading it one byte at a time as a legacy Western encoding. The file is correct; the player chose wrong.
  • A question mark or where each accented letter should be, with the rest of the line intact. The file is in an old single-byte encoding and the player is reading it as UTF-8. A byte above 127 standing alone is not valid UTF-8, so the decoder gives up on that one character and moves on. The file needs converting.
  • The wrong alphabet, one letter for one letter: Ïðèâåò where Привет should be, or Greek and Turkish text that comes out as accented Western letters. The file is in one legacy code page and the player is reading it as another, almost always windows-1252, the Western default. The letter count is right because both are one byte per letter; only the table differs. The file needs converting, and the language tells you from what.

Why subtitle files, of all things

An SRT file has no header. It does not say what encoding it is in, because the format was invented before that was a question anyone asked, and WebVTT is the only subtitle format that settled the matter by requiring UTF-8. So an .srt is just bytes, and every program that opens one guesses. Subtitle sites hold twenty years of uploads, most typed on Windows machines whose default text encoding was the regional code page of wherever the author lived. A player set to a different default reads them wrong, and it reads them wrong in the shape above.

Players offer a setting for this: VLC has a default subtitle encoding in its subtitle preferences, and most others have the same knob. Changing it fixes one file and breaks the next one from somewhere else, and it does nothing for your TV, your phone or whoever you send the file to. As with a timing shift, the fix that holds is written into the file. Convert it to UTF-8, which every player made in the last fifteen years reads without being told, and the question never comes up again.

Convert the file

You need one fact you cannot read from the file: which encoding it was written in. Guess from the language, and check by converting:

  • Western European (French, Spanish, German, Portuguese, Italian, the Nordics): windows-1252. ISO-8859-1 is nearly the same table and either name usually works.
  • Central European (Polish, Czech, Slovak, Hungarian, Croatian, Romanian): windows-1250.
  • Cyrillic (Russian, Ukrainian, Bulgarian, Serbian in Cyrillic): windows-1251, also written cp1251.
  • Greek windows-1253; Turkish windows-1254; Hebrew windows-1255; Arabic windows-1256; Baltic windows-1257.

On a Mac or Linux, iconv is already installed and does the whole job in one line:

iconv -f windows-1251 -t utf-8 film.srt > film.utf8.srt

If you already have ffmpeg for extracting tracks, it converts too, and it is worth knowing the flag because ffmpeg refuses a legacy-encoded SRT outright without it, with the message Invalid UTF-8 in decoded subtitles text; maybe missing -sub_charenc option:

ffmpeg -sub_charenc windows-1251 -i film.srt film.utf8.srt

On Windows, Notepad opens the file, and Save As has an encoding menu; choose UTF-8 and save under a new name. Whichever route you take, open the result and look at one accented line. If the letters are right, the guess was right. If they are a different set of wrong letters, the file was in a neighbouring code page; try the next name on the list. If they are the same wrong letters as before, the file was already UTF-8 and the problem is the player’s setting, not the file.

What the studio does with encodings

DriftFix is a timing tool, but it has to read the bytes to retime them, so it takes a position on this. It reads a file with a UTF-16 byte-order mark as UTF-16, a file that decodes cleanly as UTF-8 as UTF-8, and anything else as windows-1252, because that is the most common legacy case by a wide margin. It always writes the corrected file as UTF-8, keeping a UTF-8 byte-order mark if the original had one and adding none otherwise. Two consequences follow.

  • A Western-encoded file that also needs retiming comes out converted for free. Fix the delay or the drift as usual and the download is UTF-8. Nothing to do.
  • A file in any other code page must be converted first. The studio does not guess Cyrillic, Greek or Central European tables, so a cp1251 file loaded directly is read as Western and comes out as UTF-8 that spells the same wrong letters. Run iconv or ffmpeg on it, then load the UTF-8 copy for the timing repair.

And a limit worth stating plainly: the studio needs a real shift, a framerate preset or a pair of anchors before it will write a file. If the timing is already right and only the letters are wrong, it has nothing to do, and one of the commands above is the whole fix.

If it is still wrong after converting

  • Same symptom, same letters. The player is forcing a code page. Set its default subtitle encoding to UTF-8 or to its automatic setting, then reload the file.
  • Right letters in one player, wrong in another. A very old player that only recognises UTF-8 by its byte-order mark. Save the file once more as UTF-8 with BOM; Notepad offers it as a separate option, and iconv does not add one, so use the editor route for this case.
  • Right letters, wrong timing. A different problem, and now the file is in a form every tool reads. Start with the delay guide and the studio below.

Pairs of symbols mean a UTF-8 file read as Western; question marks mean a Western file read as UTF-8; the wrong alphabet means the wrong code page. Convert once to UTF-8 with the code page of the language, in iconv, ffmpeg or Notepad, and the file is right in every player. The studio converts Western files as a side effect of any timing repair; everything else, convert first.