> ## Documentation Index
> Fetch the complete documentation index at: https://www.cometchat.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Transcription & Closed Captions

> Use CometChat Calls SDK v5 transcription on JavaScript to transcribe calls, show live closed captions, and retrieve transcripts after the call.

<Note>
  **Available since v5.0.5** — transcription and closed captions require CometChat Calls SDK v5.0.5 or later for JavaScript. See [Setup](/docs/calls/javascript/setup) to install or upgrade.
</Note>

Transcribe call sessions in real time and display live closed captions on screen. Transcripts are stored server-side and can be retrieved after the call using `TranscriptRequestBuilder`.

<Warning>
  Transcription must be enabled for your CometChat app. Contact support if you need to enable this feature.
</Warning>

## How It Works

Transcription and closed captions are two related but separate things:

| Concept             | What it does                                                                                                                                                                   |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Transcription**   | Server-side speech-to-text for the session. Starting it brings a transcriber into the call, which produces the transcript that is stored for later retrieval.                  |
| **Closed captions** | The on-screen overlay that renders the live transcript as it arrives. Captions are produced from the running transcription, so they only appear while transcription is active. |

Starting transcription is a prerequisite for captions — toggling captions on without an active transcription shows nothing.

## Starting Transcription

### Auto-Start Transcription

Configure transcription to start automatically when the session begins:

```javascript theme={null}
const callSettings = {
  autoStartTranscription: true,
  // ... other settings
};

await CometChatCalls.joinSession(callToken, callSettings, container);
```

**Default:** `false`

### Manual Transcription Control

#### Start Transcription

Begin transcribing during an active call:

```javascript theme={null}
CometChatCalls.startTranscription();
```

#### Stop Transcription

Stop the current transcription. Any captions currently on screen are cleared:

```javascript theme={null}
CometChatCalls.stopTranscription();
```

## Built-in UI Controls

### Transcription Button

By default, the transcription button in the control panel's **More** menu is hidden. To show it:

```javascript theme={null}
const callSettings = {
  hideTranscriptionButton: false,
  // ... other settings
};
```

**Default:** `true`

The menu item toggles between **Start Transcription** and **Stop Transcription** based on the current state.

### Closed Caption Button

By default, the closed-caption (CC) button in the control panel is hidden. To show it:

```javascript theme={null}
const callSettings = {
  hideClosedCaptionButton: false,
  // ... other settings
};
```

**Default:** `true`

<Note>
  Even with `hideClosedCaptionButton: false`, the CC button only appears once transcription is running for the session, because captions are generated from the live transcript.
</Note>

### Closed Caption Settings

When the CC button is visible, the settings dialog gains a **Closed Caption** tab where the user can pick the caption language and enable or disable the on-screen captions. The gear icon on the captions overlay opens the dialog directly on that tab.

## Caption Language

**Property:** `captionLanguage`

Sets the language used for transcription and captions.

```javascript theme={null}
const callSettings = {
  captionLanguage: "en-US",
  // ... other settings
};
```

**Default:** `en-US`

<Accordion title="Supported Language Codes">
  | Code    | Language                               |
  | ------- | -------------------------------------- |
  | `en-US` | English (United States)                |
  | `de-DE` | German (Germany)                       |
  | `en-GB` | English (United Kingdom)               |
  | `es-ES` | Spanish (Spain)                        |
  | `fr-FR` | French (France)                        |
  | `hi-IN` | Hindi (India)                          |
  | `hu-HU` | Hungarian (Hungary)                    |
  | `it-IT` | Italian (Italy)                        |
  | `ja-JP` | Japanese (Japan)                       |
  | `ko-KR` | Korean (South Korea)                   |
  | `lt-LT` | Lithuanian (Lithuania)                 |
  | `ms-MY` | Malay (Malaysia)                       |
  | `nl-NL` | Dutch (Netherlands)                    |
  | `pt-PT` | Portuguese (Portugal)                  |
  | `ru-RU` | Russian (Russia)                       |
  | `sv-SE` | Swedish (Sweden)                       |
  | `tr-TR` | Turkish (Turkey)                       |
  | `zh`    | Chinese Mandarin (Simplified, China)   |
  | `zh-TW` | Chinese Mandarin (Traditional, Taiwan) |
</Accordion>

## Retrieving Transcripts

After a call, use `TranscriptRequestBuilder` to list the transcript artifacts for a session. Each record is a **pointer to a downloadable transcript file**, not the transcript text itself.

<Note>
  The SDK must be initialized with `CometChatCalls.init()` and a user must be logged in. The auth token is read from the logged-in user at fetch time, so it automatically tracks re-logins.
</Note>

### Building a Request

```javascript theme={null}
const request = new CometChatCalls.TranscriptRequestBuilder()
  .setSessionId("v1.us.2547167fe69871fd.alice") // required
  .setLimit(10)                                  // optional
  .build();

const transcripts = await request.fetchNext();
```

| Method                            | Required | Description                                                                                          |
| --------------------------------- | -------- | ---------------------------------------------------------------------------------------------------- |
| `setSessionId(sessionId: string)` | Yes      | The session ID whose transcripts to fetch. An empty value throws `SESSION_ID_REQUIRED` at `build()`. |
| `setLimit(limit: number)`         | No       | Page size. Defaults to `30` and is clamped to the range `1`–`1000`.                                  |
| `build()`                         | Yes      | Returns a `TranscriptRequest`. Throws synchronously for pre-flight errors.                           |

### Paginating

A `TranscriptRequest` is a stateful cursor. Create one per session ID and drive it with `fetchNext()` and `fetchPrevious()`:

```javascript theme={null}
const request = new CometChatCalls.TranscriptRequestBuilder()
  .setSessionId(sessionId)
  .setLimit(10)
  .build();

let page = await request.fetchNext(); // page 1

while (page.length > 0) {
  page.forEach((transcript) => console.log(transcript.transcriptUrl));
  page = await request.fetchNext();   // page 2, 3, ... then [] at the end
}
```

* `fetchNext()` resolves the next page, or `[]` when there are no more pages. A session with no transcripts resolves `[]`.
* `fetchPrevious()` resolves the previous page, or `[]` when already on the first page. It never requests a page below `1`.
* Only one fetch may be in flight at a time. Calling `fetchNext()` or `fetchPrevious()` while another request is pending rejects with `REQUEST_IN_PROGRESS`; the original call is unaffected and still completes.

### Transcript Properties

| Property         | Type   | Description                              |
| ---------------- | ------ | ---------------------------------------- |
| `tid`            | String | Transcript ID                            |
| `mid`            | String | Meeting ID                               |
| `roomName`       | String | Room name of the meeting                 |
| `startTime`      | Number | Meeting start time, in epoch **seconds** |
| `endTime`        | Number | Meeting end time, in epoch **seconds**   |
| `url`            | String | Meeting URL                              |
| `transcriptDate` | String | Transcript date                          |
| `transcriptUrl`  | String | URL of the downloadable transcript JSON  |
| `metaData`       | Object | Arbitrary metadata                       |

<Note>
  Every property is optional. The server omits keys whose value is empty, so sparse records are normal and should not be treated as an error.
</Note>

### Reading the Transcript Content

`transcriptUrl` points at the transcript file. Fetch it yourself to read the actual utterances:

```javascript theme={null}
const [transcript] = await request.fetchNext();

if (transcript?.transcriptUrl) {
  const response = await fetch(transcript.transcriptUrl);
  const content = await response.json();
  console.log(content);
}
```

### Error Handling

`build()` throws synchronously; `fetchNext()` and `fetchPrevious()` reject. Both surface a `CometChatCallsException` carrying a `code`:

| Condition                     | Code                                                | Raised by                         |
| ----------------------------- | --------------------------------------------------- | --------------------------------- |
| `init()` was not called       | `NOT_INITIALIZED`                                   | `build()`                         |
| `sessionId` missing or empty  | `SESSION_ID_REQUIRED`                               | `build()`                         |
| No logged-in user             | `NOT_LOGGED_IN`                                     | `fetchNext()` / `fetchPrevious()` |
| A fetch is already in flight  | `REQUEST_IN_PROGRESS`                               | `fetchNext()` / `fetchPrevious()` |
| Network failure               | `NETWORK_ERROR`                                     | `fetchNext()` / `fetchPrevious()` |
| Missing or malformed response | `BAD_RESPONSE`                                      | `fetchNext()` / `fetchPrevious()` |
| Server-side API error         | The server's own code (e.g. `AUTH_ERR_EMPTY_APPID`) | `fetchNext()` / `fetchPrevious()` |

```javascript theme={null}
try {
  const transcripts = await request.fetchNext();
} catch (error) {
  console.error(error.code, error.message);
}
```

## Transcripts in Call Logs

Call logs can be filtered to transcribed calls, which also attaches each call's transcripts to the log:

```javascript theme={null}
const callLogRequest = new CometChatCalls.CallLogRequestBuilder()
  .setLimit(30)
  .setHasTranscriptions(true)
  .build();

const callLogs = await callLogRequest.fetchNext();

callLogs.forEach((callLog) => {
  callLog.getTranscriptions().forEach((transcription) => {
    console.log(transcription.getTid(), transcription.getTranscriptURL());
  });
});
```

`getTranscriptions()` returns an empty array when the server omitted transcripts, so it never needs a null check.

<Accordion title="Transcription Methods">
  | Method                | Returns | Description                             |
  | --------------------- | ------- | --------------------------------------- |
  | `getTid()`            | String  | The transcript ID                       |
  | `getMid()`            | String  | The meeting ID                          |
  | `getRoomName()`       | String  | The room name of the meeting            |
  | `getStartTime()`      | Number  | Meeting start time, in epoch seconds    |
  | `getEndTime()`        | Number  | Meeting end time, in epoch seconds      |
  | `getTranscriptDate()` | String  | The transcript date                     |
  | `getTranscriptURL()`  | String  | URL of the downloadable transcript JSON |
</Accordion>

## Complete Example

```javascript theme={null}
// 1. Join a session with transcription enabled
const callSettings = {
  sessionType: "VIDEO",
  autoStartTranscription: true,
  hideTranscriptionButton: false,
  hideClosedCaptionButton: false,
  captionLanguage: "en-US",
};

await CometChatCalls.joinSession(callToken, callSettings, container);

// 2. Control transcription during the call
CometChatCalls.startTranscription();
CometChatCalls.stopTranscription();

// 3. Retrieve transcripts after the call
const request = new CometChatCalls.TranscriptRequestBuilder()
  .setSessionId(sessionId)
  .setLimit(10)
  .build();

const transcripts = await request.fetchNext();
```

## Related Documentation

* [Session Settings](/docs/calls/javascript/session-settings)
* [Actions](/docs/calls/javascript/actions)
* [Call Logs](/docs/calls/javascript/call-logs)
