AssemblyAI Universal-3.6 Pro Realtime STT - #741
Merged
Merged
Conversation
AssemblyAI formats spoken numbers as digits, so the clock-time clip came back as "party of 4" and failed a check that only knew the word. Co-authored-by: Thierry Schellenbach <thierryschellenbach@gmail.com>
Streams 16 kHz PCM to the v3 socket, gathering 20 ms call frames into the 50-1000 ms the server takes, and refuses a session whose Begin reports another model or preset, since unknown query parameters are silently ignored. Close sends Terminate so the tail settles. Calls default to the max_accuracy preset: balanced ends a turn at a 390 ms pause mid-sentence. Co-authored-by: Thierry Schellenbach <thierryschellenbach@gmail.com>
Registers the provider, maps silence_ms to max_turn_silence, reads mode and the two turn silences from overwrites, and lists the model in router.yaml at $0.45 an hour with keyterms and endpointing. Co-authored-by: Thierry Schellenbach <thierryschellenbach@gmail.com>
…i-stt Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # CHANGELOG.md
tschellenbach
marked this pull request as ready for review
October 4, 2026 05:16
kanat
pushed a commit
that referenced
this pull request
Oct 5, 2026
* test(sttsuite): accept the party of four written as a digit AssemblyAI formats spoken numbers as digits, so the clock-time clip came back as "party of 4" and failed a check that only knew the word. Co-authored-by: Thierry Schellenbach <thierryschellenbach@gmail.com> * feat(stt): AssemblyAI Universal-3.6 Pro Realtime provider Streams 16 kHz PCM to the v3 socket, gathering 20 ms call frames into the 50-1000 ms the server takes, and refuses a session whose Begin reports another model or preset, since unknown query parameters are silently ignored. Close sends Terminate so the tail settles. Calls default to the max_accuracy preset: balanced ends a turn at a 390 ms pause mid-sentence. Co-authored-by: Thierry Schellenbach <thierryschellenbach@gmail.com> * feat(sttrouter): route to assemblyai/universal-3-6-pro Registers the provider, maps silence_ms to max_turn_silence, reads mode and the two turn silences from overwrites, and lists the model in router.yaml at $0.45 an hour with keyterms and endpointing. Co-authored-by: Thierry Schellenbach <thierryschellenbach@gmail.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Universal-3.6 Pro Realtime (
universal-3-6-pro, launched 2026-09-29) is first on Coval's streaming STT WER leaderboard (2.2% WER, 138 ms to final segment, October 2026). Artificial Analysis has not benchmarked it yet. It adds 32 languages with code-switching, keyterms and word-aware end-of-turn detection to the STT router.Facts checked against AssemblyAI's own docs and pricing page, and confirmed on the live socket:
Authorization: <api key>, noBearerprefix (socket_test.goTestTheKeyTravelsAsItIsInTheAuthorizationHeader)speech_modelenumuniversal-3-6-pro, and Begin echoes it back asconfiguration.modelHow it works
sequenceDiagram participant C as Call (20 ms frames) participant P as assemblyai.STT participant S as streaming.assemblyai.com/v3/ws P->>S: dial with speech_model, mode, keyterms_prompt, language_codes and Authorization S-->>P: Begin with configuration Note over P: refuse if the model or preset differs from what was asked C->>P: ProcessAudio 20 ms P->>S: binary PCM, gathered to at least 50 ms and split at 1000 ms S-->>P: Turn with end_of_turn false P-->>C: Transcript ModeReplacement S-->>P: Turn with end_of_turn true P-->>C: Transcript ModeFinal C->>P: Close P->>S: tail padded to 50 ms, then Terminate S-->>P: last Turn, Termination, close 1000assemblyai.go:351)StartTestAMisspeltModelIsRefusedRatherThanServedByTheDefault(live),TestASessionOpenedOnAnotherModelIsRefusedassemblyai.go:389)TestCallAudioIsGatheredIntoFramesTheServerAccepts, live suite atChunkMs: 20mode=max_accuracybalancedended a turn at the 390 ms pause after "a map." in the fixtureTestACallGetsThePresetThatDoesNotEndATurnMidSentence, liveTestWordsArriveWhileTheCallerIsStillSpeakingassemblyai.go:410)TestClosingSendsTheLastAudioAndAsksForTheTurnToSettle, liveTestClosingSettlesTheTailOfTheCallrouter.yamlsilence_mssetsmax_turn_silence.overwritessetsmode,min_turn_silenceandmax_turn_silenceTestAssemblyAITakesItsPresetFromOverwritesAndRefusesOneItHasNotsttsuiteclock testTestAMidUtteranceClockTimeSettlesAsOneTranscriptWhat the router config declares, per router-stt:
keyterms(100 terms, 50 characters each),endpointing, realtime, 32 languagesdiarize, language detection, redaction, profanity filter. The model can do these, but nothing here sends themThe data policy is
trains_on_data: "yes"andretention: unspecified, because self-serve accounts are in the model-improvement program until an admin opts out.Live suite: all 8 tests pass against the real API, and the default turn settles about 760 ms after the last word. Free-tier accounts allow about 5 new sessions per minute. One earlier run, started straight after a burst of probe sessions, failed two tests in 60 ms each. That fits the rate limit, but I did not capture the error message, so it is unverified.
Changes
acceleration/internal/stt/assemblyai, with unit tests, fake-socket tests and theintegrationsuitesttrouter, plus arouter.yamlentry forassemblyai/universal-3-6-prosttsuiteaccepts a digit for "four"CHANGELOG.mdentry