メインコンテンツへスキップ

Realtime STT (Auto) のトラブルシューティング

当社の /stt/turns/websocket エンドポイントは、ユーザーターンがモデルによって自動的にファイナライズされるため、「Realtime STT (Auto)」と呼んでいます。

Realtime STT (Auto): トランスクリプトエラー

transcript フィールドは ターン内で累積的 です。各 turn.updateturn.eager_endturn.end イベントには、これまでのターンの全文がすでに含まれています。最終的なトランスクリプトだけが必要な場合は、完了したターンごとに 1 つずつ、各 turn.end から transcript プロパティを取得してください。transcript はそのまま連結してください。strip() で空白を取り除いたり、正規化したり、独自の区切り文字を追加してはいけません。
import json

full_audio_transcript = ""
turns: list[str] = []
async for message in websocket:
    event = json.loads(message)
    if event["type"] == "turn.end":
        # transcripts across turns should be
        # concatenated without formatting!
        full_audio_transcript += event["transcript"]

        # per-turn transcript
        turns.append(event["transcript"])
turn.updateturn.eager_end イベントのトランスクリプトを連結するのは、テキストの重複の典型的な原因です。各更新は累積的なので、それらを連結するとトランスクリプトの一部が繰り返されます。 turn.updateturn.eager_end は、トランスクリプトのチャンクではなく、ターン状態の更新として扱ってください。最終トランスクリプトは turn.end のみから読み取ってください。
セッションの音声をすべて送信し終えたら、{"type": "close"} を送信して、バッファリングされている音声をフラッシュし、残りのイベントを発行するようモデルに伝えます。モデルが完了すると、サーバーがソケットをクローズします。サーバーは文字起こしの精度を高めるために音声を一定量バッファします。close コマンドを送信しなかったり、メッセージの読み取りを早期に停止したりすると、バッファされた音声は処理されません。最後の 1 秒の音声を気にしないのであれば、これは問題ありません。
await websocket.send(json.dumps({"type": "close"}))
async for message in websocket:
    event = json.loads(message)
    if event["type"] == "turn.end":
        turns.append(event["transcript"])
        # do not stop reading from the websocket!
print("server closed the connection")
Ink 2 は現時点で英語のみをサポートしています。他言語の概念は持たず、すべてを英語として文字起こししようとします。
モデルは、接続時に宣言した encodingsample_rate を使ってバイト列をデコードします。これらのパラメーターが正しくなくても、Cartesia のサーバーは エラーを返さない場合がありますパラメーターを検証するには、音声データを保存し、ffplay で再生してみてください:
# encoding=pcm_s16le
# sample_rate=16000
# 1 channel (the API expects mono)
ffplay -f s16le -ar 16000 -ac 1 audio.raw

# general format
ffplay -f <encoding_without_pcm_prefix> -ar <sample_rate> -ac <num_channels_must_be_one> <file_path>
再生がおかしく聞こえる場合 (かなり明らかにわかるはずです)、encodingsample_rate がデータと一致していません。音声がきれいに再生されるように修正し、その同じ値を API に送ってください。適切なパラメータを見つけるには STT 入力音声エンコーディング を参照してください。

Realtime STT (Auto): 高レイテンシー

Cartesia の API は連続した音声ストリームを想定しています。 音声の送信を停止すると、サーバーはユーザーが無音であると見なすのではなく、追加の音声チャンクが到着するのを待ちます。これは通常、ネットワークの遅延に対応するために望ましい挙動ですが、クライアントが音声入力をミュートしている間、無音 (すべてゼロ) を送信し続ける必要があることも意味します。
プッシュ・トゥ・トーク型のアプリ (ユーザーがボタンを押している間に話すなど) を構築している場合や、所定のポイント (特定の評価など) でトランスクリプトを「フラッシュ」したい場合は、リアルタイム STT (Manual) への切り替えを検討してください。ターン検出は、turn.end で運ばれる最終トランスクリプトに 0.5 秒程度の遅延を追加します。 セットアップが許すなら、manual エンドポイントを使い、ユーザーの発話が終わった時点で "finalize" を送信することで、ターン検出によるレイテンシのオーバーヘッドを取り除けます。

Realtime STT (Auto): サーバーエラー

Cartesia のリアルタイム WebSocket エンドポイントは、音声がほぼ発話と同じ速度で到着することを想定しています。 ソケットに一度に大量の音声をプッシュすると、サーバー側のバッファをオーバーロードする可能性があり、内部サーバーエラーとして現れる場合があります。小さなチャンク (各 50〜200 ミリ秒) でストリーミングし、リアルタイムに合わせて、ウォールクロック 1 秒あたり平均 1 秒の音声を送るようにペースを調整してください。JavaScript の例 もご覧ください。完全なファイルを一度に文字起こししたい場合は、ファイル全体を 1 回のリクエストで受け付ける Batch STT の利用を検討してください。

Realtime STT (Manual) のトラブルシューティング

当社の /stt/websocket エンドポイントは、ユーザーターンがクライアントによって手動でファイナライズされるため、「Realtime STT (Manual)」と呼んでいます。

Realtime STT (Manual): トランスクリプトエラー

transcript イベントは、音声全体のトランスクリプトではなく、最後の確定トランスクリプト以降のデルタ を運びます。is_finaltrue のすべてのイベントの text を追記してください:
import json

transcript = ""
async for message in websocket:
    event = json.loads(message)
    if event["type"] == "transcript" and event["is_final"]:
        # delta, appended exactly as received
        transcript += event["text"]
is_final が true のすべての transcript イベントを必ず含めてください。
{ "type": "transcript", "is_final": false, "text": "Ignore this" }
{ "type": "transcript", "is_final": true, "text": "This is a" }
{ "type": "transcript", "is_final": true, "text": " single sentence." }
text をトリミングしないでください
"Trimming may"
" join words."
"Trimming mayjoin words."
text を空白を挟んで結合しないでください
"Insert"
"ing spaces is not safe"
"Insert ing spaces is not safe"
セッションの音声をすべて送信し終えたら、"close" を送信して、バッファリングされている音声をフラッシュし、残りの transcript イベントを発行するようモデルに伝えます。すべての音声が処理されると、サーバーは { "type": "done" } を送信し、その後でソケットをクローズします。サーバーは文字起こしの精度を高めるために音声を一定量バッファします。close コマンドを送信しなかったり、メッセージの読み取りを早期に停止したりすると、バッファされた音声は処理されません。最後の 1 秒の音声を気にしないのであれば、これは問題ありません。
await websocket.send("close")
async for message in websocket:
    event = json.loads(message)
    if event["type"] == "transcript" and event["is_final"]:
        transcript += event["text"]
    elif event["type"] == "done":
        print("done! expect the server to close the connection soon with code=1000")
        # optional: stop reading messages and close the socket yourself
print("server closed the connection now")
WebSocket 接続を確立する際に、クエリパラメーターとして ?language=xx (xx を ISO 639-1 言語コードに置き換え) を必ず含めてください。このエンドポイントはまだ言語検出をサポートしていません。対応言語については Models を参照してください。
モデルは、接続時に宣言した encodingsample_rate を使ってバイト列をデコードします。これらのパラメーターが正しくなくても、Cartesia のサーバーは エラーを返さない場合がありますパラメーターを検証するには、音声データを保存し、ffplay で再生してみてください:
# encoding=pcm_s16le
# sample_rate=16000
# 1 channel (the API expects mono)
ffplay -f s16le -ar 16000 -ac 1 audio.raw

# general format
ffplay -f <encoding_without_pcm_prefix> -ar <sample_rate> -ac <num_channels_must_be_one> <file_path>
再生がおかしく聞こえる場合 (かなり明らかにわかるはずです)、encodingsample_rate がデータと一致していません。音声がきれいに再生されるように修正し、その同じ値を API に送ってください。適切なパラメータを見つけるには STT 入力音声エンコーディング を参照してください。
finalize は、ユーザーの発話が終わった後にのみ送信するようにしてください。発話の途中でファイナライズすると、文字起こしエラーが発生します。

Realtime STT (Manual): 高レイテンシー

文字起こしは finalize コマンドによってトリガーされます。ユーザーが発話を終えたことを示したとき、または VAD がユーザーの発話終了を検出したときに送信して「ターンをファイナライズ」してください:
await websocket.send("finalize")
finalize を送信しない場合、モデルは無音ベースの自動ファイナライズにフォールバックします。これは設計上、より低速です。ユーザーの発話が終わったことを確認するため、無音が続くのを待つ必要があるからです。finalize は必要なだけ何度でも送信してください。セッションを恒久的にクローズする close と混同しないでください。finalize は、音声ストリームの妥当なタイミングでのみ送信する必要があります。発話の途中でファイナライズすると、文字起こしエラーが発生します。
ユーザーが発話を開始・終了するタイミングが分からない場合は、 リアルタイム STT (Auto) を試してみてください。 モデルがターンの境界を検出し、ユーザーの発話が終わったらすぐに最終トランスクリプトを発行します。“manual” から “auto” に切り替えると、すぐに最終トランスクリプトのレイテンシが改善されます。 “manual” エンドポイントは、クライアントが finalize を送信することを想定し、ユーザーの発話による最後のトランスクリプトチャンクを保留するためです。“auto” エンドポイントは、クライアントから音声以外を送ることを想定していません。最終トランスクリプトの準備ができ次第、turn.end イベントで送信します。
Cartesia の API は連続した音声ストリームを想定しています。 音声の送信を停止すると、サーバーはユーザーが無音であると見なすのではなく、追加の音声チャンクが到着するのを待ちます。これは通常、ネットワークの遅延に対応するために望ましい挙動ですが、クライアントが音声入力をミュートしている間、無音 (すべてゼロ) を送信し続ける必要があることも意味します。

Realtime STT (Manual): サーバーエラー

Cartesia のリアルタイム WebSocket エンドポイントは、音声がほぼ発話と同じ速度で到着することを想定しています。 ソケットに一度に大量の音声をプッシュすると、サーバー側のバッファをオーバーロードする可能性があり、内部サーバーエラーとして現れる場合があります。小さなチャンク (各 50〜200 ミリ秒) でストリーミングし、リアルタイムに合わせて、ウォールクロック 1 秒あたり平均 1 秒の音声を送るようにペースを調整してください。JavaScript の例 もご覧ください。完全なファイルを一度に文字起こししたい場合は、ファイル全体を 1 回のリクエストで受け付ける Batch STT の利用を検討してください。