Aller au contenu principal
SubtitleMatrix

Convertir JSON en ASS

Ou collez le texte d'un sous-titre

Ce que cette conversion change

1 élément perdu ou à décider

  • Précision

    la précision du minutage — l'horloge de la sortie est plus grossière, chaque code temporel est donc arrondi au 10 ms le plus proche

Ce rapport de pertes vient de la matrice de capacités de ces deux formats, pas du fichier particulier que vous avez chargé. Un fichier précis peut perdre davantage s'il utilise des fonctionnalités que le format autorise mais que la matrice ne modélise pas.

Cette page transforme un document JSON de sous-titres en script ASS. Elle accepte la forme que produit ce site — un numéro de version, une table `styles` et un tableau `cues` — comme la forme simple où le fichier n’est qu’une liste de blocs. Dans les deux cas, chaque bloc fournit un `start` et un `end` en millisecondes entières, un tableau `lines` et, s’il y en a un, un `style` qui renvoie à une entrée de la table.

Les deux formats ne mesurent pas le temps à la même finesse : le JSON écrit `4126` là où ASS écrit `0:00:04.13`. Les styles, la position et le karaoké passent donc, mais chaque horodatage est arrondi au centième de seconde. La liste ci-dessus vient des capacités des deux formats, pas de votre fichier : elle est la même avant tout dépôt.

Un fichier isolé convient, et une saison entière aussi : la file les traite dans l’ordre et les résultats descendent ensemble dans un seul ZIP. Rien ne quitte le navigateur.

Exemples

Un fichier JSON typique, converti en ASS

Entrée

{
  "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"
    }
  ]
}

Sortie

[Script Info]
Title: Fixture: typical
ScriptType: v4.00+

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Default,Arial,20,&H00FFFFFF,,,,0,0,,,,,,,,,,,,,,

[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:00.00,0:00:02.00,Default,,0,0,0,,{\pos(100,200)}Hello world.\NSecond line.
Dialogue: 0,0:00:02.50,0:00:04.00,Default,,0,0,0,,Plain line.\N{\i1}Styled{\i0} line.
Dialogue: 0,0:00:04.50,0:00:06.00,Default,,0,0,0,,Roger: I am here.

Dans cette sortie, seule la précision est perdue : les millisecondes deviennent des centièmes. Le reste correspond bloc par bloc.

La même conversion sur une entrée abîmée

Entrée

[
    { "start": 0, "end": 1000, "lines": ["First."] },
    { "start": 1000, "end": 2000, "text": "Second." },
    "not an object",
    { "start": 2000, "end": 3000, "lines": ["Third."], "class": "top" }
]

Sortie

[Script Info]
ScriptType: v4.00+

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Default,Arial,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,2,2,2,10,10,10,1

[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:00.00,0:00:01.00,Default,,0,0,0,,First.
Dialogue: 0,0:00:01.00,0:00:02.00,Default,,0,0,0,,Second.
Dialogue: 0,0:00:02.00,0:00:03.00,Default,,0,0,0,,Third.

C’est le genre de dégâts des vrais fichiers : fins de ligne mélangées, espaces parasites, champs vides. Comparez avec l’exemple propre ci-dessus pour voir ce que le lecteur pardonne.

Questions fréquentes

Sous quelle forme un bloc JSON sort-il dans un script ASS ?

Chaque bloc devient une ligne `Dialogue:` dans la section `[Events]`, avec un champ de calque à l’endroit où le SRT mettrait un numéro. La table `styles` part dans `[V4+ Styles]`, les couleurs en `\c&HBBGGRR&`, les positions en `\pos(x,y)` ou `{\anN}`. L’ordre des blocs est conservé.

Pourquoi les millisecondes du JSON sont-elles arrondies dans un fichier ASS ?

ASS stocke le temps au centième de seconde, pas au millième. Un `start` JSON de 4126 ms devient `0:00:04.13`, et aucun bloc ne bouge de plus de 5 ms. Le texte, l’ordre et les durées restent ceux de votre fichier.

Le style et le karaoké d’un fichier JSON passent-ils vraiment dans un script ASS ?

Oui : la table `styles` alimente les styles ASS, les balises de ligne deviennent des codes `\b1`, `\i1` et `\c&H…&`, et les plages karaoké deviennent des balises `\k`. L’arrondi au centième est donc la seule perte de cette direction.

Comment un bloc JSON de deux lignes est-il écrit dans ASS ?

Les deux entrées du tableau `lines` restent un seul bloc, séparées par `\N`, la façon dont ASS écrit un saut de ligne dur. Un lecteur les affiche ensemble.

Puis-je revenir d’un script ASS vers le JSON d’origine ?

Oui, avec une autre liste : ASS vers JSON perd le contenu propre au format, comme `[Script Info]`, `[Fonts]` et les blocs `Comment:`. Cette liste diffère de celle ci-dessus parce que les deux formats ne gardent pas les mêmes choses.

Outils associés