Back

Blog details

Multi-Language Video Captions and Transcripts for Developers

AIOZ Network
6 min readSeptember 08, 2026
aioz-streamguide
AIOZ Stream cover image with the headline Multi Language Captions and Transcripts for Developers

To serve multi-language captions on AIOZ Stream, upload one .vtt transcript per language, then mark one as the default, which is a single setting shared by every viewer. Picking the right language per viewer happens in the browser and player, not in the API.

TL;DR:

  • Each language is its own .vtt upload to the Media Transcript API, keyed by a BCP 47 code such as en, es or pt-BR.
  • Each video holds one transcript per language, and one is_default flag that applies to every viewer.
  • The HTML track rules let a browser prefer a track that matches the viewer's language over the default, though browser support varies.
  • So upload every language you need, set your main audience's language as the default once, and leave it alone.
  • Use regional tags such as en-GB only when the text differs. The docs reject a second transcript for a primary language that already exists, so test regional pairs first.

Updated Oct 19, 2026: rechecked against the current Media Transcript docs, added the primary-language rejection rule, a track-selection diagram and a closing API section, and shortened the sentences.

How do you add captions in multiple languages?

You make one upload per language: each call to the Media Transcript API sends one .vtt file for one BCP 47 language code. A video with English, Spanish and Japanese captions needs three uploads, because no single file carries several languages.

The docs say the transcript is user-provided, so you supply the file, and each video can have at most one transcript per language. You then set one of them as the default with a PATCH call. In the docs' own words, "the default transcript is the transcript the player loads by default." That flag is stored on the video, like its title, so it is the same for everyone who watches.

The Chapter vs Transcript API guide covers the single-file mechanics, while this guide covers what happens once you have several languages.

Can each viewer get a different default language?

Not through the API, because the Transcript API docs mention no Accept-Language header, no geo-detection and no per-viewer default. Whichever track you set last is the default for every viewer, unless the viewer picks another track.

One workaround developers try is to detect each viewer's locale on your server and flip is_default with a PATCH before serving the page, but that creates a race condition. Two viewers with different languages who load the same video at the same moment will keep overwriting each other's setting, and neither is sure to get the right one.

How does the browser pick a caption track?

The HTML rules for text tracks already hand the per-viewer choice to the browser. MDN describes the default attribute on a track element this way: "This attribute indicates that the track should be enabled unless the user's preferences indicate that another track is more appropriate."

Diagram: English, Spanish and Japanese .vtt tracks with English as default; a viewer whose browser is set to Spanish may get Spanish, a viewer set to French gets the English default
One default per video. A viewer's language settings decide whether another uploaded track wins.

So if your player exposes each language as its own text track, the browser may pick the one that matches your viewer's settings. The default then works as the fallback for viewers whose language you didn't upload. Browser support for this preference matching varies, so test your embed in Chrome, Safari and Firefox before you rely on it.

Regional language tags

Both the Chapter and Transcript APIs accept primary tags like en and regional tags like en-US or fr-CA. Use the regional tag only when the text differs between regions. British and American English differ enough in spelling that a captions team may localize them separately. Brazilian and European Portuguese differ enough in vocabulary that one file reads oddly to the other audience.

The W3C's guidance on language tags says the same thing in general terms: "you should only use a region subtag if it contributes information needed in a particular context to distinguish this language tag from another one; otherwise leave it out." Its golden rule is to keep the tag as short as possible.

There is also an AIOZ Stream rule to check, because the transcript docs say that if a transcript for that primary language already exists, the request is rejected. That suggests en-GB may be refused when en-US is already on the video. If you need two regional versions of one language, upload both to a test video before you plan around it.

A practical multi-language workflow

The workflow that holds up is simpler than fighting the single default. Upload a transcript for every language the video needs, and set the language most of your audience speaks as the default, once. Then let each track show up as its own option in the player.

Take a video with English, Spanish and Japanese captions for a mostly English audience. You upload all three, set en as the default and leave it. A viewer whose browser is set to Spanish can get the Spanish track without your code doing anything per request. A viewer with a French browser gets English, because you have no French file, and English is the sensible fallback.

If you need a strict guarantee, add a language menu or a ?lang= option in your own page and let the viewer choose. That choice lives in the viewer's session, so it never touches the shared default.

How AIOZ Stream handles it

We store each language as its own transcript resource on the video, and you add one with a multipart upload of the .vtt file. This request from the Media Transcript docs adds English:

curl --location --request POST 'https://api.aiozstream.network/api/media/media_id/transcripts/en' \
  --header 'stream-public-key: your_public_key_here' \
  --header 'stream-secret-key: your_secret_key_here' \
  --form 'file=@"/path/to/your/transcript.vtt"'

The documented 201 response returns the new track:

{
  "status": "success",
  "data": {
    "media_transcript": {
      "url": "https://api.aiozstream.network/api/media/media_id/transcripts/en.vtt",
      "language": "en",
      "status": "done",
      "description": "Transcript for the media in English",
      "is_default": true
    }
  }
}

To change the default, send {"is_default": true} with PATCH /media/{media_id}/transcripts/{lan}. GET /media/{media_id}/transcripts lists every language with its default flag, and DELETE removes one. If you delete the default transcript, the video has no default until you set a new one. The Node.js SDK doesn't wrap transcripts yet, so the docs call them with fetch, while the Go SDK v3.0.4 exposes the same tracks as captions.

What the docs don't cover yet: whether the player renders each language as a native text track, and whether two regional tags of one language can coexist. Next step: open the Media Transcript API docs and upload your second language.

Frequently Asked Questions

Can AIOZ Stream show different default captions to different viewers?
Not through the API. The is_default flag is one setting per video, and per-viewer choice happens in the browser or your own page.

Should I change is_default based on each viewer's locale?
No. Concurrent viewers would overwrite each other's setting, and the browser's own track matching already covers languages you uploaded.

How does a browser choose a caption track?
The HTML rules let it prefer a track that matches the user's language settings over the default track, and when nothing matches, the default loads.

Do I need regional tags like en-US and en-GB?
Only when the text differs by region. A plain en is enough otherwise, and the docs may reject a second transcript for the same primary language.

How many transcripts can one video have?
One per language, since the docs allow at most one transcript per language for each media item.

Does this apply to chapters too?
No. Chapters are also stored per language, but they have no is_default field, so the default question only applies to transcripts.

References

We only send updates when meaningful changes ship, and you can unsubscribe anytime

Related Content

blog thumbnail

What Is Video Encoding? Codecs, Containers and Bitrate

Video encoding compresses raw video with a codec, then a container packages it for playback. See how codecs, containers, bitrate and rate control fit together.

aioz-streamguide
8 min readNovember 05, 2026
blog thumbnail

Video Streaming Protocols: HLS, DASH, WebRTC, RTMP and SRT

Video streaming protocols move video from encoder to viewer. See how RTMP, SRT, HLS, DASH and WebRTC differ in latency, transport and where each one fits.

aioz-streamguide
7 min readNovember 04, 2026
blog thumbnail

What Is Decentralized Live Streaming and How Does It Work?

Decentralized live streaming sends a real-time broadcast through independently run nodes instead of one company's servers. Here's how each stage of it works.

aioz-streamguide
6 min readNovember 03, 2026
blog thumbnail

Video Streaming Glossary: Codecs, Protocols and Delivery A-Z

A video streaming glossary of 114 terms, from AAC and ABR to WebRTC and Widevine, each defined in plain English with sources and links to the deep posts.

aioz-stream
23 min readOctober 31, 2026
blog thumbnail

Monitor Livestream Health With Bitrate, FPS and Viewer Count

Read the AIOZ Stream Statistics panel: bitrate in and out, FPS in and out and current viewers, plus the documented rules for each and what the docs leave out.

aioz-streamguide
6 min readOctober 30, 2026
blog thumbnail

How to Embed a Livestream on Your Website (Link or iFrame)

Embed an AIOZ Stream livestream with the Share button's iframe or send the Public Playback URL as a link. Covers API fields, public access limits and doc gaps.

aioz-streamguide
6 min readOctober 27, 2026