既存の録音の文字起こしにはGrok STT、原稿をプリセットの声で読み上げるにはGrok TTSを使います。まずSpicyAPIのPlaygroundで両方を試し、そのあとコードやエージェントから呼び出してください。これは保存済みファイルを扱うワークフローです。リアルタイムの音声会話にはリアルタイム用の転送方式が必要です。STTは音声1分あたり約0.002ドル、TTSは1,000文字あたり0.018ドルです。2026年9月のテストでは、どちらのルートも成人向けの録音や原稿を書かれたとおりに処理し、拒否もマスキングも途中切れのクリップもありませんでした。
料金、制限、各ルートの返すもの
| Grok STT | Grok TTS | |
|---|---|---|
| モデルID | xai/grok-stt/speech-to-text | xai/grok-tts/text-to-speech |
| 入力 | 音声URL、またはアップロードしたMP3/WAV(90 MB・10分まで)。長さは1秒〜2時間 | テキスト、1〜15,000文字 |
| 言語 | 25言語、または自動検出 | 20言語+自動検出 |
| 料金 | 1秒あたり0.0000333334ドル | 1,000文字あたり0.018ドル |
| 結果 | テキストと単語ごとの時刻付き文字起こし | 音声ファイル1つ |
| 保存期間 | アップロードした音声は1日 | 生成した音声は14日 |
| 非対応 | 話者ラベル | 声のクローン、参照音声の入力 |
より長い、またはサイズの大きい録音には公開URLが必要です。URLはM4A、FLAC、OGG、Opus、AAC、MP4、MKVも指せますが、プレーヤーや共有ページではなく、音声ファイルそのものを返す必要があります。STTはヘッダーのないPCM、μ-law、A-lawを受け付けません。
音声1時間は約0.12ドル、90秒の録音は約0.003ドルです。タスクはまず上限の2時間分、約0.24ドルを確保し、実際の長さが分かった時点で差額を解放します。1,800文字の原稿は0.0324ドル、フルテイク2回と240文字の差し替え録りで0.06912ドルです。スペース、句読点、読み上げタグも文字数に含まれ、TTS実行前に表示される見積もりが最終請求額になります。
まずPlaygroundで試す
文字起こし。 Grok STTのページを開き、Playgroundタブのまま進めます。
- Input audioでMP3またはWAV(90 MBまで)をアップロードするか、Asset URLに切り替えてAdd URLを押し、外部にある録音を指定します。
- Language、Normalize text、Key terms、Keep filler words、Transcribe channels separatelyが必要な場合だけAdvanced parametersを開きます。
- 料金の見積もりを確認し、ログインして実行します。文字起こしはOutputパネルに表示され、JSON表示で単語ごとの時刻を確認できます。
ナレーション。 Grok TTSのページを開きます。
- Textに原稿を貼り付けるか編集します(Sample scriptボタンで例文が入ります)。読み上げタグも使えます。
- Voiceを選びます。メニューには各声の名前、性別、言語が表示されます。Advanced parametersにはSpeed、Output format、Bitrate、Languageがあります。
- 実行し、Outputパネルでテイクを再生して、Downloadで保存します。
長いナレーション全体を作る前に、いちばん読みにくい名前や一文をここで試してください。Playgroundで不自然に聞こえる部分は、APIでも同じように不自然になります。
結果を左右する文字起こしの設定
Language(language)は省略すると自動検出になります。Normalize text(text_normalization)は数字、価格、日付を数字表記(「March 14」「$1,250」)にし、languageの指定が必要です。話した言葉をそのまま残したいときはオフのままにします。
Keep filler words(filler_words: true)は、通常は削除される「えー」「あのー」を残します。Key terms(keyterms)は、架空の名前やブランド名の表記を寄せるための指定で、1語50文字以内、最大100語です。単純な文字列ではなく、[{"term":"Mara"},{"term":"Jon"}]のようにオブジェクトで送ります。
Transcribe channels separately(multichannel: true)は、ファイルの各チャンネルを別々に文字起こしします(最大8チャンネル)。オフのままだと、左右に別々の話者がいるステレオ録音で、片方の話者が抜けて返ることがあります。各チャンネルの単語と時刻はoutput.transcript.channelsで読み取ります。結合されたテキストはチャンネルごとに1行で、完成した会話文ではありません。1つのモノラルチャンネルに混ざった2人は分離できず、このルートは話者ラベルも返しません。モノラルのインタビューには、別々に録音したチャンネルか話者分離ツールを使ってください。
次にコードから呼び出す
Python SDKをインストールし(pip install spicyapi、Python 3.11以上)、SPICY_API_KEYを設定して、この文字起こしからナレーションまでのフローを実行します。ファイルパスは、使用する権利のある録音に置き換えてください。
import uuid
from spicyapi import SpicyClient, output_assets
client = SpicyClient() # reads SPICY_API_KEY from the environment
# 1. Transcribe a local recording (uploads are free and kept for one day)
source = client.upload_file("./interview.mp3")
stt = client.create_task(
model="xai/grok-stt/speech-to-text",
input_data={"audio_url": source["uri"], "multichannel": True},
idempotency_key=str(uuid.uuid4()), # new key per new request; reuse only to retry the same one
)
done = client.wait_for_terminal(stt["taskId"])
if done["state"] != "succeeded":
raise RuntimeError(f"STT task {stt['taskId']} ended as {done['state']}")
print(done["output"]["text"]) # edit this into your script
# 2. Narrate the edited script
script = "Chapter Three. The storm kept them in the cabin. [breath] <slow>Neither of them pretended to be reading.</slow>"
tts = client.create_task(
model="xai/grok-tts/text-to-speech",
input_data={"text": script, "voice_id": "rex", "language": "en", "speed": 0.9},
idempotency_key=str(uuid.uuid4()), # new key per new request; reuse only to retry the same one
)
final = client.wait_for_terminal(tts["taskId"])
if final["state"] != "succeeded":
raise RuntimeError(f"TTS task {tts['taskId']} ended as {final['state']}")
# 3. Copy the MP3 link to your own storage now; generated audio is kept for 14 days
print(output_assets(final)[0]["url"])べき等キーを再利用するのは、応答を受け取れなかった同じリクエストを再試行するときだけです。アップロード、待機、エラー、再試行、期限切れのダウンロードリンクの更新については、Python SDKリファレンスとタスクガイドを参照してください。
エージェントに実行させる
アシスタントに文字起こしとナレーションを任せたい場合は、CLIかMCPサーバーを渡します。どちらも料金を表示し、有料の呼び出しの前に確認を求めます。Skillはそのどちらにも指示を追加します。
- CLI。
spicyapiはターミナルから1つのタスクを実行します(npx @spicyapi/cliならインストール不要です)。
``bash spicyapi files upload ./interview.mp3 # prints a spicy:// URI spicyapi tasks create --model xai/grok-stt/speech-to-text \ --input-json '{"audio_url": "spicy://YOUR-UPLOAD-URI", "multichannel": true}' --wait ``
- MCPサーバー。 MCPサーバーをアシスタントに追加し、「Transcribe ./interview.mp3 with Grok STT, with each channel separate.」と頼みます。
spicyapi_upload_file、spicyapi_task_create(料金の確認で止まります)、spicyapi_task_waitの順に呼び出されます。
``json { "mcpServers": { "spicyapi": { "command": "npx", "args": ["--yes", "--package=@spicyapi/mcp", "spicyapi-mcp"], "env": { "SPICY_API_KEY": "YOUR_SPICY_API_KEY" } } } } ``
- Skill。
npx skills add spicyapi-ai/spicy-skillでAgent Skillをインストールすると、コーディングアシスタントが最新のスキーマを読み、べき等キーを再利用するようになります。Skill単体ではタスクを実行できないため、CLIまたはMCPと併用してください。
文字起こしから原稿、そして声へ
音声合成の前に文字起こしを編集します。名前、句読点、読み方を変えたい箇所を直してください。架空の名前には短いkey termsリストが役立ちますが、文字起こしは録音の内容を反映するものなので、名前は音声と照らして確認します。
TTSにはプリセットの声が71種類あります。デフォルトはeveです。eve、ara、leo、rex、salは対応するすべての言語を話し、残りの66種類は1言語向けに調整されていて、APIでは意味の分からないIDとして表示されます。Grok TTSのモデルページの声のメニューから選んでください。各声の名前、性別、言語が表示されます。ナレーション全体を合成する前に、いちばん難しい名前を含む短い一節を試してください。
読み上げの表情は原稿の中に書きます。インラインタグは置いた位置で音を出します:[pause]、[long-pause]、[breath]、[inhale]、[exhale]、[sigh]、[laugh]、[chuckle]、[giggle]、[cry]。囲み型のタグは、中の言葉の読み方を変えます:<whisper>、<soft>、<slow>、<loud>、<build-intensity>など。タグは読み上げられず演技として実行されますが、料金にはカウントされます。例:
{"text": "Chapter Three. The storm kept them in the cabin for two more days. [breath] By the second night, <slow>neither of them pretended to be reading anymore.</slow>", "voice_id": "rex", "speed": 0.9, "language": "en"}speedは0.7から1.5までです。bitrateはMP3にのみ適用されます。再生にはMP3、編集にはWAVを使ってください。8 kHzの生のpcm、mulaw、alawは電話システム向けで、ブラウザでは再生できません。SSMLは非対応です。上記のタグを使ってください。
2人の登場人物がいるシーンでは、話者ごとのセリフを別々の声で個別に合成し、編集でつなぎます。1回のリクエストで読めるのは1つの声だけです。つなぎ目の自然な間は、ゼロまで詰めずに残してください。
テイクを確認するには、生成した音声をSTTに通して原稿と比べます。欠けた言葉や変わった言葉、途中で切れた終わり、読み上げられてしまったタグはたいてい見つかり、短いクリップなら費用は1セントの何分の1かです。そのうえで、冒頭、終わり、指摘された行を聞いて確かめます。Grokのプリセットで足りない場合は、モデル一覧に他の音声オプションがあります。比較記事「Uncensored text-to-speech APIs compared」は今のところ英語版のみです。
よくある問題と対処
| 症状 | 対処 |
|---|---|
| ステレオ通話の片側しか出ない | multichannelを有効にし、output.transcript.channelsを読む |
| モノラルの2人の話者を分けられない | 別々のチャンネルで録音するか、話者分離ツールを使う |
keytermsが拒否される | termキーを持つオブジェクトを最大100件まで送る |
| 正規化のリクエストが拒否される | 対応するlanguageコードを追加する |
| WAVでMP3のビットレートが拒否される | bitrateを省略する |
| 生の音声が再生できない | MP3かWAVを使うか、プレーヤーで生フォーマットとサンプリング周波数を設定する |
| STTがURLを拒否する | HTMLページではなく音声ファイルそのものを返すURLにする |
| ダウンロードリンクが期限切れ | 同じタスクをもう一度照会して新しいアセットURLを取得する |
| ダウンロードが403を返す | User-Agentヘッダーを送る(Pythonの既定値はブロックされる) |
| タスクがまだrunningのまま | 同じタスクIDを待ち続ける。代わりのジョブは作らない |
STTの単語タイムスタンプは元の録音に属します。TTSは単語ごとの時刻なしで音声を返すため、テキストや速度を変えると古いタイムスタンプは無効になります。字幕は完成した合成テイクに合わせて作り直してください。







