# General Translation Knowledge Base: Comment traduire des sous-titres SRT sans casser la synchronisation ?
URL: https://generaltranslation.com/fr/kb/translate-srt-subtitles.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: Ne traduisez que le texte des sous-titres d’un fichier SRT ; conservez les numéros de sous-titre, les codes temporels, les lignes vides de séparation et les balises de formatage tels qu’ils figurent dans la source. Vérifiez ensuite la longueur des lignes et la vitesse de lecture au regard des exigences de votre plateforme de destination : le guide de Netflix pour l’anglais, par exemple, autorise 42 caractères par ligne et 20 caractères par seconde pour les programmes destinés aux adultes.
Category: Traduction
Last updated: 2026-10-20
Authors: Kevin Wu, Jackie Chen
Published: 2026-10-20

Le format SRT (SubRip) ne repose sur aucune spécification formelle. La Library of Congress le décrit comme [« not well standardized »](https://www.loc.gov/preservation/digital/formats/fdd/fdd000569.shtml) (peu standardisé) : les lecteurs et les plateformes n’acceptent donc pas tous la même chose, et le plus sûr est de garder un fichier traduit aussi simple que sa source.

## Contenu d&#39;un fichier SRT

Un fichier SRT est une liste de sous-titres séparés par des lignes vides. Chaque sous-titre comporte un numéro d&#39;ordre, une ligne de minutage au format `HH:MM:SS,mmm --> HH:MM:SS,mmm` (avec une virgule avant les millisecondes) et une ou plusieurs lignes de texte :

```text title="subtitles/en/intro.srt"
1
00:00:01,000 --> 00:00:03,500
Welcome back to the channel.

2
00:00:03,600 --> 00:00:06,200
Today we're looking at
<i>how subtitles are timed</i>.

3
00:00:06,400 --> 00:00:08,000
Let's get started.
```

Ce guide suit un workflow à minutage fixe : traduisez le texte en conservant la structure existante des sous-titres. Si la langue cible nécessite un minutage ou un découpage différent, effectuez ces modifications dans un éditeur de sous-titres en vous calant sur la vidéo, puis validez séparément le résultat modifié.

* **Les numéros de sous-titres**, dans l&#39;ordre, un par sous-titre.
* **Les lignes de minutage**, caractère pour caractère. Un point à la place de la virgule, ou une milliseconde décalée, peut amener un lecteur à rejeter le sous-titre ou à l&#39;afficher au mauvais moment.
* **La ligne vide entre les sous-titres.** En l&#39;absence de séparateurs, un lecteur peut fusionner, mal interpréter ou ignorer les sous-titres concernés. Les sous-titres suivants ont des horodatages absolus : leur minutage ne se décale pas automatiquement.
* **Les retours à la ligne à l&#39;intérieur d&#39;un sous-titre**, qui gardent chaque ligne assez courte pour rester lisible. Une traduction peut déplacer un retour à la ligne pour mieux équilibrer le texte, mais elle ne doit pas ajouter de troisième ligne.
* **Les balises** telles que `<i>`, `<b>` et `<font>`, ainsi que les balises de position telles que `{\an8}`, que les lecteurs interprètent comme du formatage. Leur affichage dépend du lecteur : YouTube, par exemple, n&#39;accepte que les fichiers SRT de base, ne reconnaît aucun balisage et exige de l&#39;UTF-8 brut ([fichiers de sous-titres pris en charge](https://support.google.com/youtube/answer/2734698)).
* **L&#39;encodage du texte.** Le format SRT n&#39;impose aucune norme d&#39;encodage : enregistrez donc les traductions en UTF-8, sauf si votre lecteur exige un autre encodage.

## Longueur de ligne et vitesse de lecture

Le minutage reste fixe alors que la longueur du texte traduit varie : un sous-titre confortable à lire en anglais peut donc défiler trop vite dans une autre langue. Netflix publie des limites propres à chaque langue. Son [English (USA) Timed Text Style Guide](https://partnerhelp.netflixstudios.com/hc/en-us/articles/217350977-English-USA-Timed-Text-Style-Guide) autorise 42 caractères par ligne, deux lignes au maximum et une vitesse de lecture allant jusqu’à 20 caractères par seconde pour les programmes destinés aux adultes (17 pour les programmes jeunesse). Le [guide allemand](https://partnerhelp.netflixstudios.com/hc/en-us/articles/217351587-German-Timed-Text-Style-Guide) conserve 42 caractères par ligne, mais abaisse la vitesse de lecture à 17 caractères par seconde pour les adultes et à 13 pour les enfants.

Une traduction peut nécessiter plus de caractères que sa source, alors que le temps disponible ne change pas. Calculez le nombre de caractères par seconde à partir de chaque sous-titre traduit et de sa durée ; la largeur du texte affiché est une tout autre mesure. Si un sous-titre dépasse les spécifications de livraison, reformulez-le sans en altérer le sens, puis vérifiez-le dans la vidéo.

## Sous-titre par sous-titre ou avec l&#39;ensemble du fichier comme contexte

Une réplique s&#39;étend souvent sur deux ou trois sous-titres. Traduire chaque sous-titre isolément préserve la structure, mais revient à traduire des fragments : en allemand, par exemple, le verbe se place à la fin de la proposition subordonnée, et peut donc se retrouver dans le sous-titre suivant. Traduire en s&#39;appuyant sur les sous-titres voisins comme contexte donne un résultat plus fluide, à condition de réinsérer le texte dans les mêmes sous-titres, avec le même minutage.

## Méthodes pour traduire un fichier SRT

| Approche                             | Gestion de la structure SRT                                                                       | Traduction automatique                                               | Contrôles de vitesse de lecture                                                      | Idéal quand                                                                       |
| ------------------------------------ | ------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------- |
| Subtitle Edit (gratuit, open source) | Lit et écrit le format SRT                                                                        | Google Translate, DeepL, API de LLM et modèles locaux                | Contrôles inspirés de Netflix : caractères par seconde, longueur et nombre de lignes | Une seule personne traduit et peaufine un fichier à la main                       |
| Traduction de documents DeepL        | Accepte le téléversement de fichiers `.srt`                                                       | DeepL                                                                | Aucun                                                                                | Vous voulez un premier jet rapide d’un seul fichier                               |
| Google Translate                     | Pas de téléversement SRT dans l’application grand public ni dans la traduction de documents Cloud | API texte uniquement ; vous devez reconstruire le fichier            | Aucun                                                                                | Vous comptez l’automatiser par script et gérer vous-même les fichiers             |
| CLI de General Translation           | Un traitement SRT dédié préserve le minutage des sous-titres et le balisage protégé               | Service de GT avec glossaire et instructions personnalisées partagés | Exécutez les contrôles ci-dessous et vérifiez le résultat sur la vidéo               | Sous-titres versionnés au rythme des livraisons du produit ou de la documentation |
| Soumettre le fichier à un LLM        | Lit le fichier comme du texte brut ; rien ne garantit que la structure soit préservée             | Le modèle de votre choix                                             | Seulement si vous le demandez, et sans vérification                                  | Un fichier ponctuel que vous vérifierez ligne par ligne                           |

Quelques précisions sur ce tableau. YouTube Studio n’y figure pas, car il sert à publier des sous-titres, pas à les traduire : une fois votre fichier traduit, ouvrez **Subtitles**, sélectionnez la vidéo, cliquez sur **Add language**, choisissez la langue et téléversez le fichier ([ajouter des sous-titres](https://support.google.com/youtube/answer/2734796)). Ce téléversement suppose que la traduction existe déjà. [Subtitle Edit](https://github.com/SubtitleEdit/subtitleedit) (sous licence MIT, pour Windows, macOS et Linux) propose une boîte de dialogue **Translate &gt; Auto-translate** avec des moteurs tels que Google Translate, DeepL, ChatGPT, Claude, Gemini et des modèles locaux via Ollama, ainsi qu’un outil de vérification **Tools &gt; Check and fix Netflix errors**. L’[API de documents](https://developers.deepl.com/api-reference/document) de DeepL compte `srt` parmi ses formats pris en charge. La [traduction de documents](https://docs.cloud.google.com/translate/docs/advanced/translate-documents) de Google accepte les fichiers Office et les PDF, tandis que le [site grand public](https://support.google.com/translate/answer/2534559?co=GENIE.Platform%3DDesktop) n’accepte que les fichiers `.docx`, `.pdf`, `.pptx` et `.xlsx`.

Utilisez Subtitle Edit lorsqu’une seule personne traduit et peaufine un fichier à la main : l’outil associe la traduction automatique à des contrôles de minutage et de vitesse de lecture. Utilisez la traduction de documents DeepL pour obtenir rapidement un premier jet d’un seul fichier. Choisissez General Translation lorsque les mêmes fichiers de sous-titres évoluent au fil des livraisons et doivent partager leur terminologie avec votre application et votre documentation ; confiez ensuite la relecture finale, vidéo à l’appui, à un éditeur de sous-titres.

## Vérifier le fichier traduit

Ce script Node.js vérifie qu’un fichier traduit contient le même nombre de sous-titres, les mêmes numéros de sous-titres et les mêmes codes temporels que la source, et qu’aucun sous-titre n’est vide. Ajoutez un troisième argument pour signaler les sous-titres qui dépassent une vitesse de lecture donnée, par exemple 17 caractères par seconde pour l’allemand :

```js title="check-srt.mjs"
// Utilisation : node check-srt.mjs <source.srt> <translated.srt> [nombre maximal de caractères par seconde]
import { readFileSync } from 'node:fs';

const TIMING = /^(\d{2}:[0-5]\d:[0-5]\d,\d{3}) --> (\d{2}:[0-5]\d:[0-5]\d,\d{3})$/;
const cues = (file) =>
  readFileSync(file, 'utf8')
    .replace(/^﻿/, '')
    .split(/\r?\n\s*\r?\n/)
    .map((block) => block.trim().split(/\r?\n/))
    .filter((lines) => lines[0])
    .map(([number, timing = '', ...text]) => ({ number, timing, text }));

const [srcFile, outFile, maxCps] = process.argv.slice(2);
if (!srcFile || !outFile || (maxCps !== undefined && !(Number(maxCps) > 0 && Number.isFinite(Number(maxCps))))) {
  throw new Error('Provide source and translated files, and an optional positive reading-speed limit.');
}
const [source, target] = [srcFile, outFile].map(cues);
const seconds = (tc) => tc.split(/[:,]/).reduce((acc, n, i) => acc + n * [3600, 60, 1, 0.001][i], 0);
const problems = [];
if (!source.length) problems.push('source has no cues');
if (source.length !== target.length) problems.push(`cue count: ${source.length} in source, ${target.length} translated`);

source.forEach((cue, i) => {
  const t = target[i];
  if (!t) return;
  if (cue.number !== t.number) problems.push(`cue ${i + 1}: number "${cue.number}" became "${t.number}"`);
  if (!TIMING.test(t.timing)) problems.push(`cue ${cue.number}: invalid timing line "${t.timing}"`);
  else if (cue.timing !== t.timing) problems.push(`cue ${cue.number}: timing changed to "${t.timing}"`);
  if (!t.text.join('').trim()) problems.push(`cue ${cue.number}: empty text`);
  const [, start, end] = TIMING.exec(t.timing) ?? [];
  const duration = start ? seconds(end) - seconds(start) : 0;
  if (start && duration <= 0) problems.push(`cue ${cue.number}: end must be after start`);
  if (maxCps && duration > 0) {
    // Compte les espaces et la ponctuation, mais pas les balises comme <i> ou {\an8}
    const chars = t.text.join(' ').replace(/<[^>]+>|\{\\an\d\}/g, '').length;
    const cps = chars / duration;
    if (cps > maxCps) problems.push(`cue ${cue.number}: ${cps.toFixed(1)} characters per second`);
  }
});

console.log(problems.length ? problems.join('\n') : `OK: ${source.length} cues, numbers and timecodes match`);
process.exitCode = problems.length ? 1 : 0;
```

Voici deux traductions du fichier d&#39;exemple. La version espagnole conserve tous les sous-titres. La version allemande condense trois sous-titres en deux et insère un point dans un code temporel :

```text title="subtitles/es/intro.srt"
1
00:00:01,000 --> 00:00:03,500
Bienvenidos de nuevo al canal.

2
00:00:03,600 --> 00:00:06,200
Hoy veremos
<i>cómo se sincronizan los subtítulos</i>.

3
00:00:06,400 --> 00:00:08,000
¡Empecemos!
```

```text title="subtitles/de/intro.srt"
1
00:00:01,000 --> 00:00:03,500
Willkommen zurück auf dem Kanal.
Heute sehen wir uns an,

2
00:00:03,600 --> 00:00:06.200
<i>wie Untertitel getimt werden</i>.
Los geht's!
```

Exécuté avec Node.js 24, le script valide le fichier espagnol mais rejette le fichier allemand. Le sous-titre 1 compte désormais 56 caractères pour 2,5 secondes :

```bash
$ node check-srt.mjs subtitles/en/intro.srt subtitles/es/intro.srt 20
OK: 3 cues, numbers and timecodes match

$ node check-srt.mjs subtitles/en/intro.srt subtitles/de/intro.srt 17
cue count: 3 in source, 2 translated
cue 1: 22.4 characters per second
cue 2: invalid timing line "00:00:03,600 --> 00:00:06.200"
```

Le script se termine avec le code 1 au moindre problème, ce qui permet de l&#39;exécuter en CI après la traduction. Il accepte les lignes de minutage simples présentées ici, sans les coordonnées de position facultatives. Il vérifie la correspondance des sous-titres, la validité du minutage, la présence de texte et, en option, une limite de vitesse de lecture. Il ne vérifie ni la préservation des balises, ni la longueur des lignes, ni leur nombre, ni le sens : pour cela, utilisez le vérificateur de sous-titres de la plateforme de destination et visionnez le résultat avec un relecteur qui parle la langue. Son décompte de caractères en JavaScript sert de contrôle préliminaire et ne remplace pas les règles de décompte propres à chaque plateforme.

## Comment traduire des fichiers SRT avec General Translation

Si vos fichiers de sous-titres sont stockés dans un dépôt et doivent être traduits dans plusieurs langues à chaque modification, sachez que la CLI de General Translation, `gt`, prend en charge les fichiers `.srt` depuis la version 2.22.2. Une fois la CLI installée et votre connexion effectuée (consultez le [Démarrage rapide de la CLI](/docs/cli/quickstart)), ajoutez une entrée `srt` sous `files` dans `gt.config.json`, avec un espace réservé `[locale]` dans le chemin :

```json title="gt.config.json"
{
  "defaultLocale": "en",
  "locales": ["es", "de"],
  "files": {
    "srt": {
      "include": ["subtitles/[locale]/**/*.srt"]
    }
  }
}
```

Exécutez ensuite [`npx gt translate`](/docs/cli/reference/commands/translate). La CLI lit les sous-titres source dans `subtitles/en/` et écrit les traductions dans `subtitles/es/` et `subtitles/de/`. Pour traduire vers l’anglais, définissez `defaultLocale` sur la langue source et ajoutez `"en"` à `locales`.

Seul le texte des sous-titres est traduit. Les numéros de sous-titre, les lignes de minutage (y compris les données de position qui suivent les horodatages), les lignes vides servant de séparateurs, les balises telles que `<i>` et `<font>`, ainsi que les balises de position `{\an1}` à `{\an9}` en début de ligne restent inchangés, tout comme les blocs dépourvus de ligne de minutage valide. Les lignes traduites conservent les fins de ligne du sous-titre d’origine, et les fichiers téléchargés utilisent l’encodage du fichier source. Les sous-titres inchangés peuvent réutiliser les traductions existantes, et le glossaire ainsi que les instructions personnalisées de votre projet s’appliquent également aux sous-titres. (Consultez la [référence du format SRT](/docs/cli/reference/formats/srt-files) et [Définir le contexte des traductions](/docs/platform/dashboard/guides/defining-context-for-translations).)

Les lignes de minutage restent strictement identiques à celles de la source : exécutez donc le script de vérification ci-dessus sur chaque fichier traduit, en particulier pour les langues dont le texte est plus long que celui de la source.

## Points clés

* Dans une traduction à minutage fixe, modifiez le texte des sous-titres en conservant leurs numéros, les lignes de minutage, les séparateurs et les balises de formatage. Toute modification volontaire du minutage ou des limites des sous-titres doit être vérifiée séparément en regard de la vidéo.
* Netflix autorise deux lignes de 42 caractères maximum, avec une vitesse de lecture plafonnée à 20 caractères par seconde en anglais et à 17 en allemand pour les programmes destinés aux adultes.
* La traduction de documents de DeepL et Subtitle Edit acceptent les fichiers SRT, contrairement au téléversement de documents de Google Translate.
* La CLI `gt` (version 2.22.2 ou ultérieure) traduit les fichiers SRT dès lors que vous ajoutez `files.srt.include` avec un chemin contenant `[locale]` et que vous exécutez [`npx gt translate`](/docs/cli/reference/commands/translate) ; seul le texte des sous-titres est traduit, le minutage restant identique à celui de la source.

## Related questions

- [Comment traduire du Markdown et du MDX sans casser la syntaxe ?](https://generaltranslation.com/fr/kb/translate-markdown-files.mdx): Traduisez la prose, le texte alternatif des images, les titres et descriptions du frontmatter, ainsi que les props de composants qui affichent du texte. Laissez inchangés les blocs de code, le code intégré, les imports, les noms de composants JSX, les clés du frontmatter et les URL des liens, sauf si une correspondance personnalisée des paramètres régionaux les réécrit. Placez les valeurs YAML traduites entre guillemets, puis lancez la compilation de votre site.
- [Comment traduire des fichiers JSON i18n ?](https://generaltranslation.com/fr/kb/translate-json-files.mdx): Traduisez uniquement les valeurs de type chaîne de caractères d’un fichier JSON de paramètres régionaux. Conservez telles quelles les clés non plurielles, les espaces réservés comme {{name}} et les balises, mais attendez-vous à ce que les clés de pluriel varient selon la langue : le polonais exige inbox_few et inbox_many. Utilisez un outil ou une API qui prend en charge le format, puis analysez et validez le résultat avant la relecture.
- [La traduction par IA est-elle assez précise pour une application en production ?](https://generaltranslation.com/fr/kb/is-ai-translation-accurate.mdx): Souvent, pour les langues les plus parlées, mais seulement après une évaluation concluante sur vos propres langues, vos chaînes de caractères d’IU et vos contenus plus sensibles. Lors du WMT25, Gemini 2.5 Pro a égalé ou surpassé les traductions humaines de référence pour 10 des 16 paires de langues, mais un benchmark portant sur des documents ne permet pas de savoir si de courtes chaînes de caractères d’interface sont prêtes à être livrées.
- [Alternatives à Google Translate : General Translation vs Google Translate](https://generaltranslation.com/fr/kb/general-translation-vs-google-translate.mdx): Google Translate permet de traduire rapidement un texte ponctuel, mais pour livrer un produit dans une autre langue, il faut aussi traduire chaque chaîne de caractères dans son contexte, garantir la cohérence des termes, gérer correctement les variables et les formes plurielles, prévoir une relecture et mettre en place un processus de livraison. General Translation comprend le contexte de chaque chaîne de caractères dans votre code et automatise l’ensemble du workflow de localisation, du code à la relecture, jusqu’à chaque livraison.

## Previous and next questions

- Previous question: [Comment traduire des fichiers JSON i18n ?](https://generaltranslation.com/fr/kb/translate-json-files.mdx)
- Next question: [Comment traduire du Markdown et du MDX sans casser la syntaxe ?](https://generaltranslation.com/fr/kb/translate-markdown-files.mdx)

## Sitemap

See the [Knowledge Base sitemap](https://generaltranslation.com/fr/kb/sitemap.md) for every article.
