Finalize コマンドを送信する場合の Deepgram Live Audio (Nova) からの移行について説明します。
すべての移行ガイド
pip install cartesia
npm i @cartesia/cartesia-js
すでに Cartesia SDK を使用している場合は、バージョン
>=3.2.0 にアップグレードしてください接続
Deepgram の WebSocket URL と認証ヘッダーを Cartesia の/stt/websocket に置き換えます。
- wss://api.deepgram.com/v1/listen?model=nova-3&encoding=linear16&sample_rate=16000
+ wss://api.cartesia.ai/stt/websocket?model=ink-2&encoding=pcm_s16le&sample_rate=16000
- Authorization: Token <DEEPGRAM_API_KEY>
+ Authorization: Bearer <CARTESIA_API_KEY>
+ Cartesia-Version: 2026-03-01
cartesia_version クエリパラメーターとして渡し、API キーの代わりに短命のアクセストークンを access_token クエリパラメーターで使用します。
Cartesia SDK で手動ファイナライズ WebSocket に接続します:
import os
from cartesia import AsyncCartesia
client = AsyncCartesia(api_key=os.getenv("CARTESIA_API_KEY"))
async with client.stt.manual_finalize.websocket(
model="ink-2", encoding="pcm_s16le", sample_rate=16000
) as connection:
...
import os
from cartesia import Cartesia
client = Cartesia(api_key=os.getenv("CARTESIA_API_KEY"))
with client.stt.manual_finalize.websocket(
model="ink-2", encoding="pcm_s16le", sample_rate=16000
) as connection:
...
import Cartesia from "@cartesia/cartesia-js";
const client = new Cartesia({ apiKey: process.env.CARTESIA_API_KEY });
const connection = client.stt.manualFinalize.websocket({
model: "ink-2",
encoding: "pcm_s16le",
sample_rate: 16000,
});
// Server-side: Generate access-tokens using your API key
import Cartesia from '@cartesia/cartesia-js';
const client = new Cartesia({ apiKey: process.env.CARTESIA_API_KEY });
export async function GET() {
const { token } = await client.accessToken.create({
grants: { stt: true, tts: false, agent: false },
// How long the token lasts in seconds
// Allowed values: 0–3600
expires_in: 3600,
});
return Response.json({ token });
}
// Client-side
// 1. Fetch an access token from your server
// 2. Connect to Cartesia via WebSocket
import Cartesia from "@cartesia/cartesia-js";
async function getToken(): Promise<string> {
const res = await fetch('/replace-with-your-server');
const { token } = await res.json();
return token;
}
const audioContext = new AudioContext();
const client = new Cartesia({ token: await getToken() });
const connection = client.stt.manualFinalize.websocket({
model: "ink-2",
encoding: "pcm_f32le",
sample_rate: audioContext.sampleRate,
});
クエリパラメーター
| Deepgram Nova | Cartesia Realtime STT (Manual) | 備考 |
|---|---|---|
model=nova-3 必須 | model=ink-2 必須 | すべての選択肢についてはモデルを参照してください。 |
version=latest | — | モデルのバージョンは model パラメーターで制御できます。 |
encoding=linear16 | encoding=pcm_s16le 必須 | すべての選択肢についてはエンコーディングを参照してください。 |
sample_rate | sample_rate 必須 | 変更なし。 |
language | language | ink-2 は現在 en のみをサポートします。他の言語には ink-whisper を使用してください。 |
| — | cartesia_version=2026-03-01 必須 | 詳細は API 規約を参照してください。 |
channels、multichannel | — | WebSocket 接続ごとにモノラル音声ストリームを送信してください。 |
endpointing、vad_events | — | 代わりに自動ファイナライズの使用を検討してください。 |
keyterm、keywords | keyterm | キータームプロンプティングを参照してください。 |
mip_opt_out | — | 組織によって制御されます。 |
encoding
encoding
| Deepgram | Cartesia |
|---|---|
linear16 | pcm_s16le |
linear32 | pcm_s32le |
mulaw | pcm_mulaw |
alaw | pcm_alaw |
| 非対応 | pcm_f16le |
| 非対応 | pcm_f32le |
flac | 非対応 |
amr-nb | 非対応 |
amr-wb | 非対応 |
opus | 非対応 |
ogg-opus | 非対応 |
speex | 非対応 |
g729 | 非対応 |
音声の送信
どちらの API も、raw PCM 音声を同じ方法でバイナリ WebSocket フレームとして受け取ります。Cartesia は次のエンコーディングをサポートしていません:Cartesia の制御コマンドは JSON ではなく、プレーンなテキストフレームです。 バッファリングされた音声をすべてフラッシュし、トランスクリプトを出力するようモデルに強制するには:flac、amr-nb、amr-wb、opus、ogg-opus、speex、g729
- { "type": "Finalize" }
+ finalize
セッションを正常に閉じるには:
- { "type": "CloseStream" }
+ close
KeepAlive メッセージに相当するものはありません。接続には 3 分間のアイドルタイムアウトがあり、音声チャンクを送信するたびにリセットされます。接続を開いたままにするには、(無音であってもなくても)音声のストリーミングを継続してください。
# Equivalent to
# deepgram_connection.send_media(audio_chunk)
await connection.send_raw(audio_chunk)
# Equivalent to
# deepgram_connection.send_finalize()
await connection.send("finalize")
# Equivalent to
# deepgram_connection.send_close_stream()
await connection.send("close")
# Equivalent to
# deepgram_connection.send_media(audio_chunk)
connection.send_raw(audio_chunk)
# Equivalent to
# deepgram_connection.send_finalize()
connection.send("finalize")
# Equivalent to
# deepgram_connection.send_close_stream()
connection.send("close")
// Equivalent to deepgramConnection.sendMedia(audioChunk)
// @param {ArrayBufferLike} audioChunk - Note: Blob is not accepted
connection.sendRaw(audioChunk);
// Equivalent to
// deepgramConnection.sendFinalize({ type: "Finalize" })
connection.send("finalize");
// Equivalent to
// deepgramConnection.sendCloseStream({ type: "CloseStream" })
connection.send("close");
イベントのマッピング
Deepgram は 4 種類のサーバーメッセージを発行します。Cartesia はトランスクリプトチャンクに加えて、finalize および close コマンドへの確認応答を発行します。
Deepgram type | Cartesia type | 備考 |
|---|---|---|
Results | transcript | 主要なトランスクリプトイベント。下記のペイロード差分を参照してください。 |
UtteranceEnd | — | 相当するものはありません。詳細は移行ガイドのページを参照してください。 |
SpeechStarted | — | 相当するものはありません。詳細は移行ガイドのページを参照してください。 |
| — | flush_done | finalize への確認応答。 |
| — | done | close への確認応答。WebSocket が閉じる直前に送信されます。 |
Metadata | — | セッションのサマリー。サーバーがソケットを閉じる前に送信されます。 |
| — | error | クライアントまたはサーバーのエラー。 |
Results メッセージ:
{
"type": "Results",
"channel_index": [0, 1],
"duration": 1.7,
"start": 0.0,
"is_final": true,
"speech_final": true,
"channel": {
"alternatives": [
{
"transcript": "Hello world! This is the full transcript.",
"confidence": 0.98,
"words": [
{
"word": "hello",
"start": 0,
"end": 0.2,
"confidence": 0.9,
"punctuated_word": "Hello"
},
{
"word": "world",
"start": 0.2,
"end": 0.5,
"confidence": 0.9,
"punctuated_word": "world!"
},
{
"word": "this",
"start": 0.7,
"end": 0.9,
"confidence": 0.8,
"punctuated_word": "This"
},
...
]
}
]
},
"metadata": { ... }
}
transcript イベントになります:
{
"type": "transcript",
"is_final": true,
"text": "Hello world!",
"duration": 0.5,
"words": [
{
"word": "Hello",
"start": 0,
"end": 0.2
},
{
"word": " world!",
"start": 0.2,
"end": 0.5
}
],
"request_id": "2ff8af53-4d38-479d-8287-58940f01c701"
}
- Ink 2 はまだ
durationやwordsを返しません- Ink 2 と Whisper は現在、確定トランスクリプト(
is_final: true)のみを発行します
Cartesia の確定トランスクリプトはデルタです
import asyncio
from cartesia.types.stt import STTManualFinalizeWebsocketResponse
final_transcript = ""
def on_message(message: STTManualFinalizeWebsocketResponse) -> None:
global final_transcript
if message.type == "transcript" and message.is_final:
# Do not strip or add whitespace!
final_transcript += message.text
elif message.type == "flush_done":
print("All audio up until 'finalize' was transcribed")
elif message.type == "done":
print("All audio up until 'close' was transcribed")
elif message.type == "error":
print(f"Error: {message.message}")
# Equivalent to
# deepgram_connection.on(EventType.MESSAGE, on_message)
connection.on("event", on_message)
# Equivalent to
# asyncio.create_task(deepgram_connection.start_listening())
recv_task = asyncio.create_task(connection.dispatch_events())
import threading
from cartesia.types.stt import STTManualFinalizeWebsocketResponse
final_transcript = ""
def on_message(message: STTManualFinalizeWebsocketResponse) -> None:
global final_transcript
if message.type == "transcript" and message.is_final:
# Do not strip or add whitespace!
final_transcript += message.text
elif message.type == "flush_done":
print("All audio up until 'finalize' was transcribed")
elif message.type == "done":
print("All audio up until 'close' was transcribed")
elif message.type == "error":
print(f"Error: {message.message}")
# Equivalent to
# deepgram_connection.on(EventType.MESSAGE, on_message)
connection.on("event", on_message)
# Equivalent to
# threading.Thread(target=deepgram_connection.start_listening, daemon=True).start()
threading.Thread(target=connection.dispatch_events, daemon=True).start()
import Cartesia from '@cartesia/cartesia-js';
let finalTranscript = '';
// Equivalent to
// deepgramConnection.on("message", (message) => { ... });
connection.on("event", (message: Cartesia.STT.ManualFinalize.STTManualFinalizeWebsocketResponse) => {
switch (message.type) {
case "transcript":
if (message.is_final) {
// Do not trim or add whitespace!
finalTranscript += message.text;
console.log(`Transcript so far: ${finalTranscript}`);
}
break;
case "flush_done":
console.log("All audio up until 'finalize' was transcribed");
break;
case "done":
console.log("All audio up until 'close' was transcribed");
break;
}
});
// Equivalent to
// deepgramConnection.on("error", (error) => { ... });
connection.on("error", (error) => {
if (error.error) {
// Server sent error (may be a bad request or internal server error)
console.error(`Server sent an error: ${error.error.message}`);
} else {
// Client error
console.error(`Client had an error: ${error.message}`);
}
});
サーバーメッセージの例
Ink may break words. Nova’s transcripts are joined with spaces. Ink’s are not.
| Deepgram Nova | Cartesia Realtime STT (Manual) |
|---|---|
| SpeechStarted | — |
is_final: false "Ink" | is_final: true "Ink " |
is_final: false "Ink may break words." | is_final: true "may bre" |
is_final: true "Ink may break words." | is_final: true "ak words." |
| UtteranceEnd | — |
| SpeechStarted | — |
is_final: false "Nova's transcripts are joined with spaces." | is_final: true " Nova's transcripts are " |
is_final: true "Nova's transcripts are joined with spaces." | is_final: true "joined with spaces." |
| UtteranceEnd | — |
| SpeechStarted | — |
is_final: false "Ink's are not." | is_final: true " Ink" |
is_final: true "Ink's are not." | is_final: true "'s are not." |
| UtteranceEnd | — |
参考資料
API リファレンス
Cartesia Realtime STT (Manual)
完全なコード例
Cartesia SDK を使用