Skip to main content
SubtitleMatrix

JSON Subtitle Format

What this format can express

Text styling
Fonts, colour, outline, shadow
On-screen positioning
Yes
Karaoke timing
Yes
Line breaks inside a cue
Yes
Timeline
Start and end time for every cue
Timing resolution
1 ms
Timing stored as frame numbers
No
Right-to-left text
Yes

Examples

A typical JSON file, and what is read out of it

File

{
  "version": 1,
  "title": "Fixture: typical",
  "fps": 25,
  "styles": {
    "Default": {
      "name": "Default",
      "fontFamily": "Arial",
      "fontSize": 20,
      "primaryColor": "#FFFFFF",
      "bold": false,
      "italic": false
    }
  },
  "generator": "subtitlematrix fixtures",
  "cues": [
    {
      "id": "1",
      "start": 0,
      "end": 2000,
      "lines": [
        "Hello world.",
        "Second line."
      ],
      "style": "Default",
      "position": {
        "x": 100,
        "y": 200,
        "align": "center"
      }
    },
    {
      "id": "2",
      "start": 2500,
      "end": 4000,
      "lines": [
        "Plain line.",
        {
          "text": "Styled line.",
          "tags": [
            {
              "kind": "italic",
              "start": 0,
              "end": 6
            }
          ]
        }
      ]
    },
    {
      "id": "3",
      "start": 4500,
      "end": 6000,
      "lines": [
        "Roger: I am here."
      ],
      "speaker": "Roger"
    }
  ]
}

What it holds

3 cues, 5 lines of text

  0 ms → 2000 ms
    Hello world.
    Second line.
    [Default; position 100,200 (center)]
  2500 ms → 4000 ms
    Plain line.
    Styled line.   [italic ×1]
  4500 ms → 6000 ms
    Roger: I am here.
    [speaker Roger]

Outside the cues:
  styles     Default
  other keys version, title, fps, generator — carried through untouched

The right-hand side is not a converted file — it is what this site reads out of the left-hand side, and what every conversion of that file starts from.

An awkward JSON file, and what is still read out of it

File

{
    "cues": [
        { "start": "0:00:01,5", "end": "0:00:03,0", "text": "Unpadded timecode." },
        { "start": 4000.5, "end": 5000, "lines": ["Fractional start.", { "text": "Second.", "tags": [] }] },
        { "start": 9000, "end": 8000, "lines": ["End before start."] },
        { "start": "nope", "end": 12000, "lines": ["No readable start."] },
        { "start": 13000, "lines": ["No end at all."] }
    ],
    "generator": "subtitlematrix boundary",
    "styles": {},
    "title": "Fixture: boundary"
}

What it holds

3 cues, 4 lines of text

  1500 ms → 3000 ms
    Unpadded timecode.
  4001 ms → 5000 ms
    Fractional start.
    Second.
  9000 ms → 9001 ms
    End before start.

Outside the cues:
  other keys generator, title — carried through untouched

Reported while reading — repaired or skipped, never silently:
  2 × entries with no readable start and end time (they are not cues, so they were skipped)
  1 × cue times that were not whole milliseconds (they were rounded to the nearest millisecond)
  1 × cues whose end time was not after their start time (they were given a 1ms duration)

Real files arrive with a byte-order mark, Windows line endings, a stray line before a timecode, or a timecode that cannot be read at all. None of it throws: whatever cannot be understood is reported rather than dropped in silence.

Convert SubtitleMatrix JSON to another format

Each of these runs entirely in your browser. The labels say what that direction costs before you open it.

Converting into this format

SubtitleMatrix JSON is one of the subtitle formats this site handles, and this page is its reference: what it can store, what it cannot, and a page for every format you can convert it to.

The table above is the whole of it — there is no hidden feature list. When a row says no, that is exactly what is lost by converting into JSON, and each conversion page linked below says so before you open a file.

Every one of those conversions runs in your browser. Nothing is uploaded and no account is needed, which matters for material under an NDA, a patient record or a broadcast embargo.

Frequently asked questions

What is a JSON file?

`.json` here is this site's own subtitle shape: a version field, an optional style table, and an array of cues whose times are milliseconds. It is deliberately lossless with respect to everything the other formats can express, and it is meant for scripts and pipelines rather than for players.

Does JSON store styling?

Yes, and more than the others do: a style table of fonts, sizes, colours, outlines and margins, plus per-cue codes inside the text, so one line can be bold, coloured and placed without any named style. Karaoke timing is stored too. Here the table is a `styles` object keyed by style name, and the per-cue styling rides in each line's `tags` array instead of as codes inside the text — which is why nothing has to be escaped on the way in or out.

Does every JSON cue store both a start and an end?

Yes, and a moment in a JSON file reads `4126`. That is as fine as JSON goes — to the millisecond — and the number is exact, so a cue can be short, long, or overlap the next one without anything being implied.

Which format should I convert JSON to?

Nothing on this site takes everything a JSON file holds, so there is no free direction — each conversion page names its own list of losses. Pick the target by which of those lists you can live with, not by which format you have seen most often.

Can I open a JSON file in a text editor?

Yes. Yes, if you keep the commas and quotes straight. The times are milliseconds as plain numbers, so a cue at 1.25 seconds is `"start": 1250`.