Repository navigation
Conversation
A provider can offer models with and without speaker labels, so the notice names the model, as the Speaker labels row already does.
… OpenRouter Voxtral answers timed segments and no words, so a segments answer becomes cues timed from the episode's start, as words do. Both models take parts of 12 MB and 900 s, because 20 MB took 33 to 35 s to answer.
…t and save timed notes The OpenRouter stub answers them as they were measured: Voxtral with segments, or a 400 when asked for word times, and Qwen3 ASR with words and no speakers.
… ASR measure The branch this builds on leaves main.js at 106,873 gzip bytes, built with the same vite command from an export of its head. The two OpenRouter models and reading Voxtral's segment times add 211, which takes it to 107,084 and over the 106,970 budget. The budget rises by those 211 bytes to 107,181, so the 97 bytes of headroom stay as they were.
…were measured The fixture provider answers Voxtral with segments, or a 400 when asked for word times, and Qwen3 ASR with words and no speakers. The transcripts recipe covers both on a 70 min MP3.
Qwen3 ASR lists its words without punctuation and keeps it only in `text`, so its notes ran on as one unpunctuated stream with paragraphs cut at fixed lengths. Each word now takes its punctuated token from `text`.
Deploying podnotes with
|
| Latest commit: |
92b5a19
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://f4fd41f4.podnotes.pages.dev |
| Branch Preview URL: | https://feat-transcription-openroute-x04d.podnotes.pages.dev |
chhoumann
marked this pull request as ready for review
November 14, 2026 14:49
This branch has not been deployed
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
Users should be able to pick from current transcription models without anyone landing on a worse or retired one. This PR adds the two plain OpenRouter models (no speaker labels) that measured best this week against NPR human transcripts.
Summary
The OpenRouter
Modelrow now lists five models, in this order: Grok STT 2.0 (recommended), ElevenLabs Scribe v2, MAI-Transcribe 2, Voxtral Mini Transcribe 3, Qwen3 ASR 1.7B.mistralai/voxtral-mini-transcribe-3-0model,file,response_format=verbose_json, notimestamp_granularities(it returns 400 "Provider returned 400")segments[]withstart,end,text, nowordsqwen/qwen3-asr-1.7bmodel,file,response_format=verbose_json,timestamp_granularities[]=wordwords[]PartTranscriptgains a{ segments }variant. The wire shapes stay insideopenrouter.ts.Speaker labelsrow reads " does not label speakers." and the note is saved without labels, with a notice that stays on screen.master, so no released wording changes.Stacked on #542.
Verification
Commands, all with Node 22.23.2 through
fnm exec:npm run lint,npm run format:check,npm run typecheck,npm run build,npm run test(124 files, 2,894 tests),npm run test:tooling(48 tests),npm run docs:build: all exit 0.npm run test:e2e -- tests/e2e/journey-resilience.test.ts -t "J-TR-": 11 passed, including the new J-TR-11 (Voxtral) and J-TR-12 (Qwen3 ASR) on Obsidian 1.14.4.npm run size: gzip 107,084 bytes. The base commit 5eebf37, built from agit archiveexport with the same command, measured 106,873, so this PR adds 211 gzip bytes (728 raw). The gzip budget goes up by exactly those 211 bytes, from 106,970 to 107,181, which leaves the same 97 bytes of headroom as before.scripts/size-baseline.mdrecords this.Planted defects, each run with
npm run plant. Every one failed the named test and passed again once restored:timestamp_granularities[]=wordmistralai/voxtral-mini-transcribe-3-0 gets the upload as its measured multipart request, ...(unit), and J-TR-11 in real Obsidian, where the stub answers it with the measured 400timestamp_granularities(uses Voxtral's request)qwen/qwen3-asr-1.7b gets the upload as its measured multipart request, ...("words" in transcript ? start : 0) + item.start)Voxtral's segments from two parts of at most 900 s become paragraphs timed from the episode's startan answer with neither words nor segments writes no noteisTimedchecks forwordsonly)choosing it shows its API key row and its five models, Grok STT 2.0 recommendedspeakers: truechoosing mistralai/voxtral-mini-transcribe-3-0 says Speaker labels are not available, ...choice.label)with speaker labels on is saved without them, and the notice names the providers that label speakers and staysRuntime check in this worktree's isolated Obsidian 1.14.4 on Linux (headless, Xvfb), using a fresh vault and a fake key. The
.claude/skills/verify/net.mjsfixture provider answered every request, so no real key was involved. The local file wasFixtures/Two Voices.mp3, 70 min of 8 kbps mono, written with the recipe'sffmpegline (4,200,452 bytes). For each model I chose it in Settings > PodNotes >Modelwith the keyboard, leftSpeaker labelson, played the file throughPlay with PodNotesin the file menu, and ranTranscribe current episode from audiofrom the palette.multipart/form-dataPOSTs of 840,311 to 840,715 bytes (840 s each), one after the other, and no reel. The fixture answers a word-times request with a 400, and the note was saved, so the request did not ask for word times. The note has paragraphs at00:00:00,00:00:12,00:14:00(time=840.096),00:14:12,00:28:00and so on up to00:56:12, with no speaker labels. Clicking00:28:12moved the player to 1,693.66 s, 1.5 s past the link's 1,692.192 while it kept playing. The notice read "Saved without speaker labels, because Voxtral Mini Transcribe 3 does not label speakers. These providers do: ElevenLabs, Deepgram, OpenRouter."dev:errors: none.timestamp_granularities[]field. The note times match Voxtral's, and the notice names Qwen3 ASR 1.7B.data.jsonstoredtranscript.model: "qwen/qwen3-asr-1.7b".Two things in the screenshots come from elsewhere. The warning icon on the key is Obsidian's own "Secrets are not encrypted", because headless Linux has no keyring. The doubled "Two Voices" is Obsidian's inline title shown above the template's
# {{title}}.I have not run this against the real OpenRouter API. The lead verifies with a real key.
Real OpenRouter key (lead, after review)
Obsidian 1.14.4, Linux, palette command, speaker labels off, a 20 min local clip of E231 (expect 2 parts at 900 s), a pass-through request log:
wordscarry no punctuation (0 sentence ends in 3,785 words on Planet Money), while itstextdoes (322).dev:errorsnone.Review fix (lead)
text, matched in order with three tokens of lookahead, only when no word carries punctuation. Plants: keep the bare word on a match; one token of lookahead. Each is caught byQwen's words, which it lists without punctuation, take their punctuation from its text.Release impact
There are no settings or storage changes.
transcript.modelcan now hold two more OpenRouter IDs. An older PodNotes that reads them treats them as unknown and runs its recommended model, which is existing behavior. The speaker-label notice now names the model instead of the provider, and that notice has not been released yet.Note
Add Voxtral Mini Transcribe 3 and Qwen3 ASR 1.7B to OpenRouter transcription
Segmenttype in types.ts and cues.ts builds cues from words or segments.Macroscope summarized 92b5a19.
Note
Medium Risk
Changes OpenRouter request shapes, response parsing, and multi-part cue timing for production transcription paths; risk is mitigated by broad unit and E2E coverage but still touches external API behavior.
Overview
Adds Voxtral Mini Transcribe 3 and Qwen3 ASR 1.7B to OpenRouter’s transcription model list (five models total), with tighter per-part caps (12 MB / 900 s) and profiles that mark no speaker labels and no URL-based audio.
The OpenRouter integration now builds model-specific multipart requests (Voxtral: segment timing only, no word granularities; Qwen: word times with
timestamp_granularities[]=word). Responses can carry timed segments as well as words:PartTranscriptand cue assembly treat segments like timed cues across split parts. Qwen3 ASR restores punctuation on words from the responsetextwhen word tokens are bare.When speaker labels are requested but the model cannot provide them, the save warning names the selected model (e.g. “GPT Transcribe”, “Voxtral Mini Transcribe 3”) instead of the provider. Answers with neither words nor segments fail as empty speech rather than saving untimed text.
Verification and CI: E2E journey tests and fixture stubs for OpenRouter/
net.mjscover the new models; the plugin gzip bundle budget rises to 107,281 bytes (+211 for the models, +100 for Qwen punctuation).Reviewed by Cursor Bugbot for commit 92b5a19. Bugbot is set up for automated code reviews on this repo. Configure here.