Skip to main content

Retrieve Live Captions in Your Playback System

Implement the following steps to connect, authenticate, and display live captions provided by our transcription service in your web player or application.

Further information

Before integrating Live Captions, we recommend reviewing the main Live Captions documentation for background, concepts, and configuration details:

These sections explain prerequisites, language setup, and stream configuration needed before retrieving and displaying live captions in your player.

Choose your integration method​

Embed player with captions​

To embed a player with Live Captions into your website or application, nanoStream provides a ready-to-use iframe-based player, which you can use as a starting point before reaching for your own custom implementation. Live Captions are enabled by passing specific parameters in the player URL.

Assemble the iframe URL manually using the parameters described below. This approach is suited for API-driven or custom workflows where you generate streams dynamically and build your own embedding logic.

Required URL + Parameters​

The base embed URL is:
https://nmessenger.nanostream.cloud/client/embed/nanoplayer.html

The following table explains all parameters needed to enable live captions, including their purpose and example values:

ParameterDescriptionExample
group.apiurlBase API URL of your bintu instancehttps://bintu.nanocosmos.de
group.idStream ID or stream name of the video streamXXXXX-YYYYY
caption.channelCaption channel identifier, assembled as STREAMNAME-SOURCE_LANG-TARGET_LANGXXXXX-YYYYY-en-en
caption.tokenJWT token that authorizes access to the captions stream. Required for secure streams only.eyJhbGciOiJIUzI1NiIsInR5cCI6...
group.security.jwtokenJWT token for secure video playback. Required for secure streams only.eyJhbGciOiJIUzI1NiIsInR5cCI6...

For secure streams, the same JWT token is used for both video playback (group.security.jwtoken) and captions delivery (caption.token). All restrictions configured in the token (stream name, stream group, domain, expiration time, etc.) apply to both. For non-secure streams, these parameters can be omitted.

Security tokens

For secure streams, generate JWTs server-side and use short-lived tokens. Learn more about token creation and best practices here: Secure Playback (H5Live).

Caption Channel Format​

The caption.channel parameter defines which caption stream the player should load. It uniquely identifies the captions by combining the stream name/stream ID with the selected source and target languages.

The format is: STREAMNAME-SOURCE_LANGUAGE-TARGET_LANGUAGE

ElementDescriptionExample
STREAMNAME-SOURCEStream name or stream ID used for ingestion and playbackXXXXX-YYYYY
SOURCE_LANGUAGEUnique ID of the language spoken in the incoming audioEnglish: en
TARGET_LANGUAGEUnique ID of the language displayed as captionsGerman: de

Resulting caption channel: XXXXX-YYYYY-en-de

Multiple Caption Channels

If multiple target languages are configured for the stream, each language has its own caption channel.
Each caption language is addressed using its own caption.channel value.

Language codes

Language identifiers must follow the supported ASR language codes (e.g. en, en-US, de, fr, es-419).
Make sure the selected source and target languages exactly match the configuration of your Live Captions setup.
A complete list of supported languages and their IDs is available here: Supported Languages

iframe-based Live Captions Player​

The code snippet below demonstrates how to embed the live captions into your web page or application using an <iframe> element:

<iframe
src="https://nmessenger.nanostream.cloud/client/embed/nanoplayer.html?group.id=<STREAM_ID_OR_NAME>&caption.channel=<CAPTION_CHANNEL>&caption.token=<SECURITY_TOKEN>&group.security.jwtoken=<SECURITY_TOKEN>"
width="100%"
height="720"
frameborder="0"
allowfullscreen>
</iframe>

Replace <STREAM_ID_OR_NAME>, <CAPTION_CHANNEL>, and <SECURITY_TOKEN> with your actual values.

Example with real data of a demo stream
warning

The token included in the example expires on 2026-12-08.

<iframe
src="https://nmessenger.nanostream.cloud/client/embed/nanoplayer.html?group.id=nNCcf-ZexY6&caption.channel=nNCcf-ZexY6-de-de&caption.token=eyJhbGciOiJFZERTQSIsImtpZCI6Im5hbm9feDI1NTE5IiwidHlwIjoiSldUIn0.eyJhdWQiOiJzcGxheSIsImV4cCI6MTc5NjczMDg0MSwiaWF0IjoxNzY1MTk4NDkzLCJpc3MiOiJuYW5vY29zbW9zIiwibmJmIjoxNzY1MTk4NDkzLCJzdHJlYW1zIjpbIm5OQ2NmLVpleFk2Il0sInN1YiI6IjU4ODYyNTFjLTJmM2UtNGQ3YS1hYWQ4LWQ3YWU1ZDBhNTdhMCJ9._EFR028lTwF2wt1F46LU4byJiWNb3qmuDJkS9Z_Yf2lEn0a9lUWXytZR05P3tbg_wtohyu9N9clTRxT8tYxqDA&group.security.jwtoken=eyJhbGciOiJFZERTQSIsImtpZCI6Im5hbm9feDI1NTE5IiwidHlwIjoiSldUIn0.eyJhdWQiOiJzcGxheSIsImV4cCI6MTc5NjczMDg0MSwiaWF0IjoxNzY1MTk4NDkzLCJpc3MiOiJuYW5vY29zbW9zIiwibmJmIjoxNzY1MTk4NDkzLCJzdHJlYW1zIjpbIm5OQ2NmLVpleFk2Il0sInN1YiI6IjU4ODYyNTFjLTJmM2UtNGQ3YS1hYWQ4LWQ3YWU1ZDBhNTdhMCJ9._EFR028lTwF2wt1F46LU4byJiWNb3qmuDJkS9Z_Yf2lEn0a9lUWXytZR05P3tbg_wtohyu9N9clTRxT8tYxqDA"
width="100%"
height="720"
frameborder="0"
allowfullscreen>
</iframe>

iframe for Non-Secure Streams​

For non-secure streams, you can omit the token parameters. Only group.id and caption.channel are required:

<iframe
src="https://nmessenger.nanostream.cloud/client/embed/nanoplayer.html?group.id=<STREAM_ID_OR_NAME>&caption.channel=<CAPTION_CHANNEL>"
width="100%"
height="720"
frameborder="0"
allowfullscreen>
</iframe>

Replace <STREAM_ID_OR_NAME> and <CAPTION_CHANNEL> with your actual values.

What happens automatically​

Once you've created or copied your iframe URL with the parameters above and integrated it into your web page or application, you're ready to enjoy live captions! The captions will automatically appear over your video stream, no additional code or configuration is needed:

  • Connection to caption server is established
  • Captions appear as text overlay at the bottom of the video
  • Captions update in real-time as transcription happens
  • Reconnection is handled automatically if connection drops

Custom integration​

This section provides instructions for integrating live captions into your custom player or application.

To integrate the captions, we'll use the nanoStream Messenger JavaScript library, which establishes a WebSocket connection to the caption service and automatically delivers transcription results to a target HTML element that acts as your caption overlay.

1. Load the Caption Library​

Include the nanoStream Messenger JavaScript library in your HTML page or application:

<script src="https://nmessenger.nanostream.cloud/client/nmessenger.js"></script>
Initialization order

Make sure the script tag loads before you try to access NanoMessenger in your code. The safest approach is to initialize the client inside a DOMContentLoaded event listener in a separate script tag:

document.addEventListener("DOMContentLoaded", function() {
// Your caption initialization code here
const messenger = new NanoMessenger(/* ... */);
});

This library handles:

  • Establishing the WebSocket connection
  • Receiving the caption messages
  • Writing text into the configured overlay element and
  • automatic reconnection

2. Create a Caption Overlay​

Add a container element (e.g. <div>) that will receive and display the live captions:

<div id="caption-text" class="overlay-text"></div>

This element will act as the target container for all incoming live captions.

2.1 Optional styling​

You can freely style the caption overlay to match your UI design.
The example below positions the captions at the bottom of the player with a semi-transparent background:

<style>
.overlay-text {
position: absolute;
left: 0; right: 0; bottom: 5%;
margin: 0 auto;
padding: 0.5rem 0.75rem;
max-width: 80%;
font-family: system-ui, sans-serif;
font-size: 1rem;
line-height: 1.4;
text-align: center;
background: rgba(0,0,0,0.55);
color: #fff;
border-radius: 6px;
pointer-events: none;
z-index: 9999;
}
</style>
Good to know
  • position: absolute: Allows the overlay to float above the video
  • pointer-events: none: prevents captions from blocking player controls
  • z-index: 9999: ensures the captions stay above the player UI

3. Initialize the Messenger Client​

After loading the library and defining the overlay element, create a new NanoMessenger instance and connect it with your caption channel and secure token:

document.addEventListener("DOMContentLoaded", function() {
// Step 1: Create the messenger client
const messenger = new NanoMessenger(
"bintu-nmessenger.nanostream.cloud", // server
443, // port
{ overlayDiv: "caption-text" } // options
);

// Step 2: Connect to your caption channel
// For secure streams, pass your JWT token.
// For non-secure streams, pass null.
const captionToken = "your-caption-token"; // or null for non-secure streams

messenger.connect(
captionToken, // authentication token (JWT or null)
null, // user (optional)
"your-caption-channel", // caption channel ID
() => { // on success callback
console.log("Captions connected");
},
(error) => { // on error callback
console.error("Caption connection failed:", error);
}
);
});

Parameter Reference (Messenger Client)​

The following table explains all values used when initializing the NanoMessenger client and connecting to the caption channel.

Parameter / OptionWhere used DescriptionExample
Servernew NanoMessenger(server, port, options)Hostname of the caption delivery servicebintu-nmessenger.autodevops-prod.nanostream.cloud
Portnew NanoMessenger(server, port, options)Secure WebSocket port (always HTTPS/WSS)443
overlayDivoptions.overlayDivID of the HTML element that will receive and display the captions, as initialized here. Make sure they match."caption-text"
your-caption-token messenger.connect(token, ...)JWT token authorizing access to the caption stream. Required for secure streams. Pass null for non-secure streams.eyJhbGciOiJIUzI1NiIsInR5cCI6...
usermessenger.connect(token, ...)Optional user identifier (not required for captions)null
your-caption-channelmessenger.connect(token, ...)Caption channel identifier (STREAMNAME-SOURCE_LANG-TARGET_LANG)XXXXX-YYYYY-en-en 
Matching IDs

The overlay element must already exist in the DOM before the NanoMessenger client is initialized. If the ID does not match, captions will be received but not displayed.

4. Display Captions​

Once connected, the Messenger library automatically writes incoming captions into the target element.

When a caption like "Hello world" arrives, your HTML will automatically update:

<div id="caption-text">Hello world</div>

No additional code needed — the library manages everything.

What happens automatically​

With the above integration steps completed, you're ready to receive the live captions from your stream:

  • Connection to caption server is established
  • Captions appear in the specified target element
  • Captions update in real-time as transcription happens
  • Reconnection is handled automatically if connection drops

Use the Reference Implementation (Optional)​

If you prefer a ready-to-use solution:

  • Use the iframe caption player provided as a reference implementation or embed the example HTML snippet in your system.
  • If you want a custom UI, you can still use the same Messenger library — just style the overlay <div> as you like.

That’s it — load the library, create an overlay, initialize Messenger with channel and token (or null for non-secure streams), and captions will appear.

The receive-captions.html example below demonstrates how to use the reference implementation. It uses the same URL query parameters as the iframe caption player described in the Embed player with captions section.

tip

For a complete end-to-end example, see this interactive CodePen that integrates our nanoStream H5Live Player (nanoPlayer) with live stream captions delivered via NanoMessenger.

Non-Secure Streams

The CodePen example above uses a secure playback token. For non-secure streams, you can omit the caption.token and group.security.jwtoken parameters, or pass null for the caption token when using the NanoMessenger library directly.

See receive-captions.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Your player</title>
<link rel="stylesheet" href="https://nmessenger.nanostream.cloud/client/nmessenger.css" />
<style>
html,
body {
height: 100%;
margin: 0;
font-family: Inter, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial;
}
#playerDiv {
width: 100vw;
height: 100vh;
position: relative;
background: #000;
}
/* Messenger target div */
#captionText {
display: inline-block;
padding: 10px 16px;
border-radius: 12px;
background: rgba(0, 0, 0, 0.55);
color: #fff;
font-size: 20px;
font-weight: 500;
line-height: 1.4;
max-width: 80%;
word-break: break-word;
-webkit-backdrop-filter: blur(6px);
backdrop-filter: blur(6px);
}
</style>
</head>
<body>
<div id="playerDiv">
<!-- nmessenger writes messages here -->
<div class="overlayText">
<div id="captionText" aria-live="polite" role="log"></div>
</div>
</div>
<script src="https://nmessenger.nanostream.cloud/client/nmessenger.js"></script>
<script>
function nmessengerMain(options = {}) {
const CAPTION_SERVER = "bintu-nmessenger.autodevops-prod.nanostream.cloud";
const CAPTION_PORT = 443;
const params = new URLSearchParams(window.location.search);
const channel = params.get("caption.channel");
if (!channel) {
console.info("caption.channel not specified. Not initializing caption.");
return;
}
const token = params.get("caption.token");
messenger = new NanoMessenger(CAPTION_SERVER, CAPTION_PORT, options);
messenger.connect(
token,
null,
channel,
() => {
console.info("connect success");
messenger.receiveMessage({ user: "system", text: "<receiving messages>" });
},
(err) => {
console.error("Error:", err);
messenger.receiveMessage({ user: "system", text: "Connection error" });
}
);
}
document.addEventListener("DOMContentLoaded", function () {
const captionOptions = {
overlayDiv: "captionText",
};
nmessengerMain(captionOptions);
});
</script>
</body>
</html>

Troubleshooting​

Captions not appearing​

If captions do not appear in the player or custom overlay, check the following:

  1. Is the caption channel correct?

    • Verify that caption.channel (iframe) or your-caption-channel (custom integration) exactly matches the configured channel ID
    • Format must be: STREAMNAME-SOURCE_LANGUAGE-TARGET_LANGUAGE
    • Channel values are case-sensitive
    Learn more

    Learn more how the Caption Channel is assembled here: Caption Channel Format.

  2. Is the token valid? (secure streams only)

    • If you are using non-secure streams, tokens are not required — you can skip this step
    • JWT tokens expire — check if your token is still valid
    • Tokens are case-sensitive
    • In case of Embed player method: check if the token is passed in both caption.token and group.security.jwtoken (and are matching)
  3. Is the overlay element present?

    • For custom integration: Verify the element with ID caption-text (or your custom ID) exists in your HTML (Read more about the creation here.)
  4. Check browser console

    • Open browser developer tools (F12) and check for error messages

Connection keeps dropping​

The automatically reconnect feature is enabled by default, you don't need to do anything. If captions disconnect frequently:

  1. Check network connectivity - Test your internet connection
  2. Verify server availability - Contact support if the issue persists

"NanoMessenger is not defined" error​

For custom integration only:

This means you're trying to use the library before it has loaded. Make sure you initialize inside DOMContentLoaded:

// ✅ Correct
document.addEventListener("DOMContentLoaded", function() {
const messenger = new NanoMessenger(...);
});

// ❌ Incorrect - runs before library loads
const messenger = new NanoMessenger(...);

Getting Help​

If you encounter issues:

  1. Check the troubleshooting section above
  2. Verify all parameters (channel ID, tokens, stream ID) for the Embed Player or the Messenger Client
  3. Check browser console for error messages
  4. Contact our support team:
Need assistance?

We're here to support you throughout your Live Captions integration. If you would like to discuss your Live Captions requirements, pricing, or custom solutions, feel free to contact our sales team via nanocosmos.net/contact or by email at sales(at)nanocosmos.net.

We're happy to assist you in finding the best configuration for your workflow.