QR payloads are grammars
A QR code carries text, and the scanner decides what to do by the prefix. A URL opens a browser; a
WIFI: string joins a network; BEGIN:VCARD adds a contact; a
upi://pay? link starts a payment. Each grammar has its own escaping rules, and an
unescaped delimiter is the usual reason a code scans but does nothing.
| Payload | Measured output |
|---|---|
Wi-Fi, SSID Cafe;Guest, password p:a,s"s | WIFI:T:WPA;S:Cafe\;Guest;P:p\:a\,s\"s;; |
UPI, shop@upi, £12.50, note “Order 7” | upi://pay?pa=shop%40upi&pn=Shop&am=12.50&tn=Order%207 |
| vCard, one phone and one email | BEGIN:VCARD … TEL;TYPE=CELL:… … EMAIL;TYPE=INTERNET:… … END:VCARD |
The Wi-Fi example shows both layers at once: the semicolons and colons inside the values are escaped with backslashes because they are the grammar's delimiters, while the UPI payload uses percent encoding because it is a URL. One payload cannot be escaped with the other's rules.
Barcodes and the check digit
A retail barcode is not free text. EAN-13 is twelve digits plus a check digit computed from them:
positions 1–12 weighted 1 and 3 alternately, summed, and the check digit brings the total to the next
multiple of ten. For 400638133393 the weighted sum is 89, so the check digit is 1 and the
full code is 4006381333931. A scanner validates that digit, which is why a mistyped code
is refused rather than printed.
Code 128 is the general-purpose symbology for identifiers and shipping labels; it carries printable ASCII and any length, and the encoder computes its own checksum. The two are not interchangeable: a retail till expects EAN-13 and a warehouse label usually expects Code 128. Printing also matters — quiet zones (11 modules left and 7 right for EAN-13, 10 each side for Code 128) and a module wide enough to survive the printer's resolution.
Subtitles: timing is the format
SRT, WebVTT and ASS/SSA all store cues, and the timing line is the part that must be exact. SRT writes milliseconds after a comma, WebVTT after a dot, and ASS uses centiseconds with no zero-padded hour. The same cue measured through the converter:
| Format | Timing | Note |
|---|---|---|
| SRT | 00:00:01,500 --> 00:00:03,000 | Comma before milliseconds |
| WebVTT | 00:00:01.500 --> 00:00:03.000 | Dot; WEBVTT header |
| ASS | 0:00:01.50,0:00:03.00 | Centiseconds; hour not padded |
Writing milliseconds into an ASS file is a real timing bug: a player reads the fraction as
centiseconds, so .500 becomes five seconds, not half of one. Styling is the other lossy
direction — ASS supports fonts, positions and colours; SRT and WebVTT do not, so converting away from
ASS keeps the words and drops the presentation.
Error correction and physical size
QR error correction is redundant data, not a licence to make the symbol unreadable. Level M is the usual default; Q or H survives more damage but makes the symbol denser, and a denser symbol needs a larger print for the same camera. The practical rule is to fix the physical size first: each module should be at least 0.4 mm across, so a version-3 code (29 modules) needs at least 12 mm, and a logo or a scuff should be treated as damage that the chosen level must cover.
Subtitles have no equivalent redundancy: a mistyped time or a missing blank line between cues is a lost cue, not a degraded one. Validate the file in the player that will show it, not only in the converter's preview, because the player is the parser that matters.
Why the failures are silent
A scanner that cannot parse a payload does not display an error; it simply does not act. A player given a malformed cue does not complain; it shows nothing for that interval. This is why testing the destination matters more than trusting the preview: scan the printed symbol with two phones, and play the subtitle file in the player that will actually be used. A code that scans on the generating screen can still fail on paper if the modules are too small.
The shared property of all three formats is that they are parsed by strict grammars with no redundancy. There is no checksum in a subtitle file and no error correction in a QR payload's text — the symbol's error correction protects the modules, not the meaning. Escaping and exact timing are the whole defence.