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

# Audio archive

> Persist the dictation microphone audio you stream to Corti, and finalize it into a downloadable recording

<iframe className="w-full aspect-video rounded-xl" src="https://www.youtube.com/embed/d6WKOaS9_Ts?start=583&end=617" title="Archive Dictation Audio — walkthrough" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowFullScreen />

<Info>
  **Follow along with the runnable example.** This guide walks through the [Audio archive example](https://github.com/corticph/corti-examples/tree/main/sdk/typescript/applets/src/applets/dictation-audio-archive) in `corti-examples` — bootstrap your build from it or use it as reference.
</Info>

Some workflows need to keep the audio a user dictated — for playback, quality review, or later re-transcription. This guide shows where to capture that audio and how to persist it *while* streaming to Corti.

It builds on the raw-SDK path from the [Microphone](/stt/guides/dictation-microphone) guide, where your app owns `MediaRecorder` directly — that's the point at which each audio chunk is available to both send and keep.

***

## Tee each chunk

The only change from a plain raw-SDK session is what you do in `ondataavailable`: append the chunk to a local archive **and** send it to Corti. Both consume the same blob.

```ts title="JavaScript" theme={null}
recorder.ondataavailable = async (e) => {
  if (e.data.size === 0) return;
  await appendChunk(e.data);                       // persist locally
  // pass e.data.arrayBuffer() to socket.sendAudio() to stream to Corti
};
```

***

## Session lifecycle

Model recording as a session with three controls, so a user can pause and resume without dropping the connection:

| Control         | Effect                                                                |
| :-------------- | :-------------------------------------------------------------------- |
| **Record**      | Open a new session (or resume a paused one) and start capturing       |
| **Stop**        | Flush buffered audio, then pause the recorder — the socket stays open |
| **End session** | Flush, finalize the archive, and close the socket                     |

The key detail is **flushing before you pause or end**: calling `socket.sendFlush()` tells the server to return transcripts for audio it has already received, so nothing is lost at the boundary.

```ts title="JavaScript" theme={null}
// Stop: emit a final chunk, then pause (keep the socket open).
async function stop() {
  recorder.requestData();   // force a last ondataavailable
  recorder.pause();
}
```

<Note>
  Call `socket.sendFlush()` after pausing — the server returns any buffered transcripts and then a `flushed` message signalling completion. See the [audio archive example](https://github.com/corticph/corti-examples/tree/main/sdk/typescript/applets/src/applets/dictation-audio-archive) in `corti-examples` for the full socket flush implementation.
</Note>

***

## Finalize the archive

On **End session**, assemble the collected chunks into a single `Blob` using the recorder's actual MIME type, then build a playback/download URL.

```ts title="JavaScript" theme={null}
const mimeType = recorder.mimeType || "audio/webm"; // what MediaRecorder actually produced
const blob = new Blob(chunks, { type: mimeType });
const url = URL.createObjectURL(blob);              // <audio src>, or a download link
```

Capture a little metadata alongside the blob so the archive is useful later — the device label, the actual capture MIME, segment start/end reasons and durations, and total chunk/byte counts. Derive the file extension from the MIME type (`audio/webm` → `.webm`, `audio/mp4` → `.m4a`) and give the file a timestamped name.

<Warning>
  This example stores audio in the browser for demonstration. In production, dictation audio is often sensitive — persist it to a secure server-side store, and apply your organization's retention and access policies rather than keeping it client-side.
</Warning>

***

## Next steps

<CardGroup cols={2}>
  <Card title="Microphone" icon="microphone" href="/stt/guides/dictation-microphone">
    The raw-SDK capture path this archive builds on.
  </Card>

  <Card title="File Transcription" icon="file-audio" href="/stt/guides/dictation-file-transcription">
    Re-transcribe an archived recording offline via `/transcripts`.
  </Card>

  <Card title="Example code" icon="github" href="https://github.com/corticph/corti-examples/tree/main/sdk/typescript/applets/src/applets/dictation-audio-archive">
    The complete, runnable Audio archive example in `corti-examples`.
  </Card>
</CardGroup>

<Note>Please [contact us](mailto:help@corti.ai) for help or questions.</Note>
