Hoppa till huvudinnehållet

Grok Voice Transcribe 2.0 API-handledning: Bygg en realtids­transkriberare för supportsamtal

Lär dig bygga en realtids­transkriberare för supportsamtal med Grok Voice Transcribe 2.0 API i Python, och lägg sedan till diarisation, Smart Turn och 8 kHz telefonljud.
Uppdaterad 5 okt. 2026  · 12 min läs

Utforska med AI

ChatGPTClaudePerplexity

SpaceXAIs Grok Voice Transcribe 2.0 är en tal‑till‑text‑modell. I den här Grok Voice Transcribe 2.0 API-handledningen skickar du inspelningar över REST och liveströmmat ljud via en WebSocket. API:et returnerar text, ordtider, valfria talar-ID:n och slut‑på‑tur‑händelser; det besvarar inte uppringaren.

Ett supportsamtal är svårare än en ren berättarröst. Det har korta pauser, ovana namn, flera talare och kontaktuppgifter som läses upp över en 8 kHz-lina. Vårt projekt Qivora Sync ger handledningen en röd tråd: en kund rapporterar en misslyckad filsynk, agenten samlar in kontaktuppgifter och en eskaleringsingenjör ansluter. Samma Python-klient hanterar först inspelningen och senare live‑ljud.

För tal‑till‑tal, där modellen själv svarar uppringaren, se vår Grok Voice Think Fast 2.0-handledning. Koden för denna finns i GitHub‑repo:t.

TL;DR

Ont om tid? Här är vad samtalet visade.

  • POST /v1/stt hanterar inspelat ljud och wss://api.x.ai/v1/stt hanterar live‑ljud, med gemensamma kontroller för diarisation, nyckeltermer, utfyllnadsord och ljudhantering.

  • En nyckelterm rättade det påhittade produktnamnet, men starkt partisk vokabulär drog ett svagt eko mot det namnet i en live‑talartest.

  • Talar­etiketter var stabila på den rena mixen men blev opålitliga vid 8 kHz.

  • Det arabiska skiftet förblev i arabisk skrift, och format=true rättade telefonnumret, men bara halvt rättade e‑posten.

  • Vid den långa pausen mitt i numret passerade Smart Turn varje testad tröskel, så tröskeljustering ensam räckte inte.

Vad är Grok Voice Transcribe 2.0?

Grok Voice Transcribe 2.0 (grok-voice-transcribe-2.0) är SpaceXAIs tal‑till‑text‑modell. REST‑sökvägen transkriberar en färdig fil, medan WebSocket‑sökvägen hanterar live‑ljud.

SpaceXAIs tillkännagivande av Grok Voice Transcribe 2.0 lyfter fram telefonsamtal, flera talare, inloggningsuppgifter och flerspråkigt tal. För benchmark‑jämförelser, se vår översikt av Grok Voice Transcribe 2.0.

Bygga en realtids­transkriberare för supportsamtal

Det kontrollerade Qivora Sync‑scenariot ligger fast medan ljud och API‑inställningar varierar. Samtalet innehåller ett påhittat produktnamn, utfyllnadsord, ett språkskifte, uppdiktade kontaktuppgifter, en paus under diktering och en tredje talare.

Qivora Syncs supportsamtalspipeline: tre talare in i Grok Voice Transcribe 2.0, ut som en diariserad live‑transkription

Tre talare blir en live‑transkription. Bild av författaren.

Skapa tre‑talar‑samtalet

Det kontrollerade scenariot använder tre distinkta röster från Grok Text to Speech API. Varje språkavsnitt syntetiseras separat och fogas samman med ffmpeg så att skiftpunkterna ligger fast. API:et accepterar även language=auto; separata förfrågningar är ett experimentdesignval, inte ett API‑krav.

Definiera den förväntade transkriptionen

Innan första begäran, definiera den förväntade texten, talare, produktstavning, kunduppgifter, utfyllnadsord och pauser. Varje uppsättning får då samma mål.

Konfigurera Grok Voice Transcribe 2.0 i Python

Installera beroenden innan du skickar ljud.

Förutsättningar

Du behöver Python 3.10 eller senare, en xAI API‑nyckel och ffmpeg för att bygga ljudet. Python‑klienterna använder requests, websockets och python-dotenv.

Dokumentationen för tal till text anger att 2.0 är standard när du utelämnar model, och att grok-voice-transcribe-1.0 nådde slut på livscykeln den 2 oktober 2026. Jag skulle ändå låsa den versionsangerade ID:n.

Installera beroenden och bygga ljud

Klona repo:t, lägg till din nyckel i .env och bygg exempel­ljudet:

git clone https://github.com/KhalidAbdelaty/grok-voice-transcribe-2.0.git
cd grok-voice-transcribe-2.0
pip install -r requirements.txt
cp .env.example .env    # then paste your key into .env
python project/scripts/make_fixtures.py

Setup‑kommandot skapar dialogen och ljudfilerna som används senare. Om du har en egen inspelning, hoppa över det kommandot.

En .env som skrivs på Windows kan lämna ett \r i nyckeln, och requests avvisar headern innan något når SpaceXAI. Rensa nyckeln innan du lägger till den i auktoriseringsheadern.

Etablera en baslinje för batchtranskribering

En baslinje är modellen med allt avstängt, så att varje senare ändring har något att jämföra med. Den första begäran skickar filen och en låst modell:

import os
import requests
from dotenv import load_dotenv

load_dotenv()
api_key = os.environ["XAI_API_KEY"].strip()

with open("support_call.wav", "rb") as audio_file:
    response = requests.post(
        "https://api.x.ai/v1/stt",
        headers={"Authorization": f"Bearer {api_key}"},
        data=[("model", "grok-voice-transcribe-2.0")],
        files={"file": ("support_call.wav", audio_file, "audio/wav")},
    )

response.raise_for_status()
result = response.json()

Svaret innehåller text, detekterat language, duration och en tidsatt words array. REST‑referensen visar per‑ords‑confidence, men den dök inte upp i batchsvaren för detta scenario. Jag skulle betrakta fältet som valfritt och kontrollera varje API‑svar innan användning. Lägg valfria fält före file; senare fält kan ignoreras.

Baslinjen tog bort utfyllnadsord, behöll arabiskan i arabisk skrift och lämnade de upplästa siffrorna separata. Det påhittade produktnamnet stavades konsekvent fel.

Lägga till diarisation, nyckeltermer och textformatering

En supporttranskription behöver talaretiketter, korrekt produktstavning och användbara kunduppgifter. Varje inställning är ytterligare ett formfält:

data = [
    ("model", "grok-voice-transcribe-2.0"),
    ("diarize", "true"),         # a speaker id on every word
    ("keyterm", "Qivora Sync"),  # repeat the field for more terms
    ("language", "en"),          # required by format
    ("format", "true"),          # inverse text normalization
    ("filler_words", "false"),   # the default; true keeps "uh" and "um"
]

Lägg till ett alternativ i taget på samma ljud. Börja med talaretiketter.

Gruppera ord till talarturer

Talar‑diarisation ger ord numeriska talar‑ID:n, inte namn. Gruppera efterföljande ord med samma ID för att bygga turer:

def group_turns(words):
    turns = []
    for word in words:
        if turns and turns[-1]["speaker"] == word.get("speaker"):
            turns[-1]["words"].append(word["text"])
            turns[-1]["end"] = word["end"]
        else:
            turns.append({"speaker": word.get("speaker"), "start": word["start"],
                          "end": word["end"], "words": [word["text"]]})
    for turn in turns:
        turn["text"] = " ".join(turn.pop("words"))
    return turns

På rent ljud höll varje känd tur sig till ett konsekvent talar‑ID. Att mappa namn efter första förekomstens ordning fungerar bara när samtalsordningen redan är känd; produktionssystem behöver sin egen talarmappning.

Diariserad transkription av Qivora Sync-samtalet som visar tre separata talarturer med tidsstämplar

Rent ljud håller talaretiketter konsekventa. Bild av författaren.

Använda nyckelterms‑bias för produktnamn

Nyckelterms‑bias är en ledtråd per begäran, inte träning. Skicka keyterm=Qivora Sync (upp till 100 termer, 50 tecken vardera), så lutar modellen mot den stavningen när ljudet stödjer det.

Nyckeltermen rättade baslinjens fel i produktnamnet utan att ändra den omgivande transkriptionen.

I en separat live‑talartest drog starkt partisk vokabulär ett svagt eko mot nyckeltermen. Det innebär inte att nyckeltermer skapar falsk text av sig själva; det betyder att tvetydigt ljud fortfarande behöver en ekokontroll.

Transkribera språkbyten engelska–arabiska

Som baslinjen visade förblev Khalids arabiska i arabisk skrift. Resultatet var detsamma med automatisk detektion och med language=en, eftersom language väljer formateringsregler snarare än att tvinga ett utdata‑språk.

Formatera upplästa telefonnummer och e‑postadresser

Baslinjen behöll upplästa siffror separata. Inverse Text Normalization (ITN) gör om dessa talade former till skriftliga. format=true slår på detta och kräver language, annars misslyckas begäran med 400.

Telefonnumret blev en sammanhängande siffersträng. E‑posten normaliserades bara delvis: interpunktionen förbättrades, men det upplästa ”at” och bokstaverade domänen behövde fortfarande städas.

Det ojämna resultatet är frustrerande. ITN formaterar text; det validerar inte kontaktdata. Jag skulle validera båda fälten innan lagring.

ITN kan också skriva om vanliga tidsuttryck till förkortade enheter. I det formaterade batchsvaret för detta scenario normaliserades bara översta text; words‑arrayen behöll den talade formen.

Behålla eller ta bort utfyllnadsord

Som baslinjen visade tas utfyllnadsord bort från text och words som standard. filler_words=true tog tillbaka Khalids ”eh” och ”öhm” där de förväntades. Ha dem av för supportanteckningar och på för en ordagrann QA‑logg.

Batchutdata täcker talare, vokabulär, formatering och kontroll av utfyllnadsord. Skicka nu samma ljud som en liveström.

Strömma Grok Voice Transcribe 2.0 över WebSocket

Strömningsvägen använder frågeparametrar snarare än ett setup‑meddelande. Vänta på transcript.created, skicka rått binärt ljud (ingen base64) och stäng med {"type": "audio.done"}. Vår handledning om GPT Live Transcribe använder samma mönster med en annan modell.

Börja med händelserna och anslut sedan klienten.

Batch använder dokumenterade format=true med language=en. Strömningsdokumentationen säger att language slår på ITN, men i ett live‑test ändrade language=en ensamt inte transkriptionen. WebSocket‑frågelistan innehåller inte format, så denna handledning behandlar strömmande ITN som ett beteende att verifiera snarare än att förlita sig på.

Läsa partiella och slutliga händelser

Varje transkriptionsuppdatering är en transcript.partial‑händelse med två booleans. Interimtext kan fortfarande ändras. En chunk‑final (is_final=true) låser cirka 3 sekunders text medan turen är öppen, och en yttrande‑final (speech_final=true) stänger turen.

Strömningsflöde för händelser från transcript created via interim, chunk-final, utterance-final och transcript done

Strömningslägen för texten mot slutgiltighet. Bild av författaren.

Strömma 16 kHz PCM‑ljud i Python

För strömning, resampla först källan till mono 16‑bitars PCM vid 16 kHz. Kärnklienten skickar 100‑millisekunders block i realtidstakt medan en annan uppgift tar emot transkriptionshändelser:

import asyncio, json, os, wave
import websockets
from dotenv import load_dotenv 

load_dotenv()

url = ("wss://api.x.ai/v1/stt?model=grok-voice-transcribe-2.0"
       "&sample_rate=16000&encoding=pcm&interim_results=true&diarize=true")
headers = {"Authorization": f"Bearer {os.environ['XAI_API_KEY'].strip()}"}

async def stream_call(path):
    async with websockets.connect(url, additional_headers=headers) as ws:
        assert json.loads(await ws.recv())["type"] == "transcript.created"

        async def send():
            with wave.open(path, "rb") as wf:
                assert wf.getframerate() == 16000
                assert wf.getnchannels() == 1
                assert wf.getsampwidth() == 2
                while chunk := wf.readframes(1600):
                    await ws.send(chunk)
                    await asyncio.sleep(0.1)
            await ws.send(json.dumps({"type": "audio.done"}))

        async def receive():
            async for raw in ws:
                event = json.loads(raw)
                if event["type"] == "transcript.partial":
                    print(event["text"])
                elif event["type"] == "transcript.done":
                    break

        await asyncio.gather(send(), receive())

Interimtext växte ungefär var halva sekund. Detta är en lokal mätning, inte officiell latens.

Terminal som visar en partiell textning som uppdateras innan den blir en slutlig transkriptionsrad

Partiella bildtexter stabiliseras till slutlig transkription. Bild av författaren.

Chunk‑finaler fryser text utan att stänga turen. Smart Turn styr när speech_final stänger den.

Hålla transkriptionsblock i ordning

Att bara visa den aktiva händelsen får tidigare ord att försvinna efter varje block‑final, eftersom nästa interim börjar om från inkommande ljud.

Behåll varje låst block, lägg till nuvarande interim och låt yttrande‑finalen ersätta båda.

Texten kan växa utan att tappa tidigare block. När visningsläget är hanterat återstår gränserna mellan turer som strömningsproblem.

Använda Smart Turn för upptäckt av tur‑slut

Smart Turn utvärderar varje tystnad och uppskattar om talaren är klar. Den finns för Khalids nummer, ”zero one zero, five five five, [paus], one two three four”, där tystnad ensam inte kan avgöra en tankepaus från ett slut.

Testa Smart Turn‑tröskeln

Tröskeln är inte transkriptionssäkerhet eller VAD‑tröskeln. Det är sannolikheten för tur‑slut som en tystnad måste passera innan speech_final avfyras; under den förblir turen öppen. Två frågeparametrar sätter den:

params += [
    ("smart_turn", "0.7"),           # end-of-turn probability needed to close
    ("smart_turn_timeout", "3000"),  # close anyway after 3 s of silence
]

Dokumentationen kallar 0,5 balanserad, 0,7 konservativ för nummerserier och 0,9 mycket konservativ. I detta scenario gav pauser kortare än standardfönstret för endpointing ingen användbar Smart Turn‑bedömning. Det är ett observerat resultat, inte en dokumenterad tidsregel.

I strömningstestet fortsatte inte den observerade tystnadstimern när ljudramar stoppades. Att fortsätta skicka digital tystnad låter Smart Turn stänga yttrandet.

Att förlänga pausen under numrerdiktering gör beteendet synligt. Korta pauser stannar inom en tur, medan en lång paus delar upp den vid varje tröskel när förtroendet överstiger alla tre inställningar.

Tidslinje för telefonnummer‑yttrandet som visar tal, pauser och tur‑sluts‑förtroende vid varje tröskel

Långa pauser kan dela upp numrerdiktering. Bild av författaren.

Mänskliga uppringare är mindre förutsägbara. En kort sifferföljd kan se färdig ut. Sedan fortsätter uppringaren.

Om Smart Turn stänger under numrerdiktering, vänta kort och slå ihop en fortsättning innan du svarar.

Ställa in en Smart Turn‑timeout

smart_turn_timeout stänger en tur efter en fast tystnad, även när Smart Turn är osäker. På den snabba tre‑talar‑strömmen grupperade Smart Turn flera kända turer innan en timeout tvingade stängningen.

Om du redan vet var turer slutar, skicka {"type": "finalize"} vid varje gräns; annars, para ihop Smart Turn med en timeout.

När gränserna är under kontroll måste samma uppringare klara en 8 kHz‑lina.

Transkribera 8 kHz telefonljud

Telefonljud här är 8 kHz G.711 mu‑law, skapat från samma samtal:

ffmpeg -i support_call.wav -ar 8000 -ac 1 -f mulaw support_call_8k.raw

Rått telefoni‑ljud har ingen container, så ange audio_format=mulaw och sample_rate=8000 i batchformuläret, eller encoding=mulaw&sample_rate=8000 på socketen. Kontrollera text och talaretiketter separat.

Jämföra rent och telefonljud

De tidigare fynden om nyckeltermer, formatering och språkskifte ändrades lite vid 8 kHz.

Talaretiketter blev mindre tillförlitliga. Telefonversionen införde ett extra talar‑ID och tilldelade en avslutande tur till fel person. Att bara räkna segment döljer båda misstagen.

Den fladdriga versionen bandbegränsar samtalet till 300–3400 Hz, kodar det som 8 kHz mu‑law och tappar varje 20‑millisekunders paket med sannolikheten 0,03. Ett fast slumpfrö på 7 behåller samma luckor vid varje uppspelning.

Den paketförlusten ändrade inte den engelska transkriptionen mycket i detta exempel, och de upplästa kontaktuppgifterna förblev i ordning. Detta resultat gäller endast detta exempel.

Telefonsimulering smalnar av ljudet och tappar paket. Bild av författaren.

Justera VAD för telefonljud

Voice activity detection (VAD) avgör om ljudet är tal alls. Dokumentationen föreslår att sänka vad_threshold för svagt telefon‑tal, med risk för strötext från brus.

Att sänka vad_threshold ändrade inget på rent telefonljud eftersom det inte fanns något svagt tal att återvinna. Nollresultatet stödjer en regel: sänk tröskeln bara när telefon‑tal försvinner.

Använda multikanals­transkription för separata talare

Använd ett nytt batchformulär utan diarize:

data = [
    ("model", "grok-voice-transcribe-2.0"),
    ("multichannel", "true"),
]

API:et detekterar kanalantal från en WAV eller annan container. För rått multikanalsljud, lägg till ("channels", "3"); WebSocket‑multikanalsinmatning kräver också ett uttryckligt kanalantal.

Skicka formuläret med multikanalsfilen via REST‑begäran som visats tidigare, läs sedan result["channels"]. Varje element innehåller ett index, transkriptionstext och tidsatta ord. I det kontrollerade trekanals‑scenariot innehöll varje kanal bara sin tilldelade talare. Strömning använder samma uppdelning och lägger till channel_index i sina händelser.

Jag skulle använda separata ben när telefonsystemet tillhandahåller dem. Till skillnad från diarisationen i avsnittet om telefonljud, drar en känd uppdelning inte slutsatser om talare.

Bygga den kompletta Python‑transkriberaren för support

Den kompletta klienten exponerar en grupp inställningar och bygger sedan REST‑formulär eller WebSocket‑URL separat. Delade inställningar omfattar diarisation, nyckeltermer, utfyllnadsord, ljudkodning och turhantering; formatering följer de transportspecifika regler som täckts tidigare.

Tillämpa slutinställningarna på en telefonkvalitetsinspelning och kontrollera sedan produktstavning, språkskiften, kontaktuppgifter och talaretiketter separat. I det kontrollerade scenariot klarade textkontrollerna medan en talaretikett fortfarande krävde granskning. Spara inställningar och talarmappning med varje transkription så att senare jämförelser använder samma setup.

Utforska den fullständiga röstagent‑demon

Supporttranskriptions‑handledningen slutar med den slutliga kontrollen. Repo:t innehåller också en separat röstagent‑utbyggnad med genererade svar, uppläst utdata, avbrott och ekohantering.

Transcribe behåller samma roll i den demon: den producerar text. En språkmodell skriver svaren, och Grok TTS läser upp dem.

Livesamtal byter ljudväg mitt i konversationen. Video av författaren.

Begränsningar i Grok Voice Transcribe 2.0

Supporttranskriptioner kan innehålla namn, telefonnummer och e‑postadresser. SpaceXAIs säkerhets‑FAQ säger att de lagrar API‑data krypterade i vila i 30 dagar för missbruksgranskning. SpaceXAI säger också att de inte tränar på data utan tillåtelse. Berättigade team kan slå på Zero Data Retention på teamnivå.

Behåll API‑nyckeln på din server. Dokumentationen för tal till text säger att du ska proxy:a WebSocket via din backend.

Ett kontrollerat samtal kan inte representera varje accent, rum eller telefonlina. Kontrollera inställningarna med ljud från den avsedda miljön innan du använder dem i produktion.

Vanliga fel och felsökning

De flesta fel här beror på ljudformatering eller sockethantering:

  • InvalidHeader ... return character(s) in header value är Windows‑\r i nyckeln.

  • En 400 kan betyda en saknad file eller url, ett format som inte stöds, rått ljud utan sample_rate, eller format=true utan language.

  • I strömningstestet fortsatte inte tystnadstimern när ljudramar stoppades; att fortsätta skicka digital tystnad lät turen stängas.

  • cannot call recv while another coroutine is already running recv betyder att två korutiner läser en socket. Ge varje anslutning en enda läsare.

  • I denna Windows‑setup kapade ljudbehandlingen på inmatningsvägen tysta stavelser. Att stänga av den eller använda exklusiv inspelning fixade inmatningen.

Om inget av dessa fall passar, jämför råhändelserna med källjudet för att isolera orsaken.

Prissättning för Grok Voice Transcribe 2.0

SpaceXAIs prissida listar transkription till 0,10 USD per timme över REST och 0,20 USD per timme vid strömning. Tillkännagivandet säger att diarisation, tidsstämplar och nyckeltermer ingår. Beräkna kostnad utifrån ljudets varaktighet snarare än antal begäranden.

Varje öppen ström debiterar sin egen ljudvaraktighet. En andra lyssnare lägger till strömningskostnad och dubblar STT‑minuterna bara när båda strömmarna tar emot samma fulla varaktighet.

Avslutande tankar

Jag skulle inte utvärdera en samtalstranskriberare enbart på rent ljud. Avsnittet om telefonljud visar varför.

API:et returnerar transkriptionsdata; klienten äger fortfarande konversations­status och validering. Behåll också den versionsangerade modell‑ID:n. Behandla de andra inställningarna som startpunkter och testa dem mot mål‑ljudet.

Nästa utbyggnader är en SIP‑telefoninmatning, vokabulär per samtal och en CRM‑export. Om du vill ha en agent i stället för en transkriberare, täcker vår Grok Voice Agent API‑handledning den vägen.

FAQs

Stöder Grok Voice Transcribe 2.0 realtids­transkribering?

Ja, över WebSocket, och inte bara som rå PCM. En klient med begränsad bandbredd kan strömma encoding=opus, cirka 4 KB/s jämfört med 48 KB/s för 24 kHz PCM, så länge varje ram bär ett Opus‑paket. Opus är endast mono, så det stöder inte multikanalsströmning.

Stöder Grok Voice Transcribe 2.0 talar‑diarisation?

Sätt diarize=true på båda ändpunkterna. I den diariserade strömningsresponsen för detta scenario innehöll orden också ett odokumenterat fält speaker_confidence. Jag skulle inte bygga applikationslogik kring det. Behandla talar‑ID:n som etiketter lokala för begäran eller session, inte som beständig identitetsigenkänning.

Kan Grok Voice Transcribe 2.0 transkribera flera språk i en inspelning?

Automatisk detektion kan bevara ett språkskifte mitt i inspelningen utan ledtråd. Parametern language styr formatering för 25 listade språk, inklusive arabiska (ar), så testa relevant kod mot ditt eget ljud innan du förlitar dig på formaterat utdata.

Vad är skillnaden mellan Smart Turn och VAD?

VAD frågar om ljud är tal; Smart Turn frågar om talet är färdigt. vad_threshold är som standard 0,5 i batch och 0,08 på strömmen. endpointing är som standard 400 millisekunder och anger tystnaden som behövs innan ett yttrande kan stängas.

Kan jag transkribera en inspelning från en URL i stället för att ladda upp en fil?

Använd batch‑ändpunktens fält url i stället för file. SpaceXAI laddar ner inspelningen server‑side, och ett misslyckat nedladdning förs tillbaka som 502.

Ämnen
Artificiell intelligens
AI-agenter

Lär dig AI med DataCamp!

Lärstig

Associate AI Engineer för utvecklare

26 tim
Lär dig hur du integrerar AI i mjukvaruapplikationer med hjälp av API:er och bibliotek med öppen källkod. Börja din resa mot att bli AI Engineer idag!
Se detaljerRight Arrow
Starta Kursen
Se merRight Arrow