Skip to content

Add Verbatim transcription mode to keep filler words - #8

Closed
wassgha wants to merge 3 commits into
mainfrom
cursor/editor-improvements-e2e4
Closed

Add Verbatim transcription mode to keep filler words#8
wassgha wants to merge 3 commits into
mainfrom
cursor/editor-improvements-e2e4

Conversation

@wassgha

@wassgha wassgha commented Jul 27, 2026

Copy link
Copy Markdown
Owner

Summary

Whisper is trained to emit "clean" transcripts and usually drops disfluencies ("um", "uh", …), which is why Remove fillers often has nothing to act on. This PR adds a Verbatim transcription mode that biases Whisper toward keeping them.

Why not CrisperWhisper? unsloth/CrisperWhisper / nyralabs/CrisperWhisper is exactly the right model (verbatim large-v3 fine-tune), and there is a browser ONNX export at onnx-community/CrisperWhisper-ONNX (~1 GB q4). In practice that export was compiled without output_attentions=True, so transformers.js cannot produce word-level timestamps (Model outputs must contain cross attentions to extract timestamps). Without those timestamps the editor's cut/timeline/export pipeline doesn't work, so it isn't usable here today.

Approach

  • Upload screen gains a Standard / Verbatim picker (lib/models.ts).
  • Both modes use the same onnx-community/whisper-base_timestamped weights (shared cache, same ~80 MB download and speed).
  • Verbatim mode builds Whisper's documented initial-prompt prefix and passes it as decoder_input_ids:
    <|startofprev|> Umm, let me think like, hmm… <|startoftranscript|> <|en|> <|transcribe|>
    Conditioning on a filler-rich prompt is a known trick that biases the decoder toward emitting fillers instead of cleaning them up. (transformers.js documents prompt_ids but doesn't implement it, so the tokens are constructed manually.)

Testing

Headless Chromium against a production build, same espeak filler video ("Um, so today… uh… Hmm… um…"):

Mode Words Fillers kept
Standard 22 Um, (1)
Verbatim 24 uh, Um, um, (3)

Verbatim transcript: "So today we are going to talk about, uh, editing videos with text. Um, I think, um, this is going to be really useful."

npm run lint and npm run build pass.

Follow-ups

  • Once someone re-exports CrisperWhisper ONNX with cross-attentions (or a smaller verbatim model with timestamps lands), we can swap Verbatim over to it for true verbatim accuracy.
  • Pair this with the still-open Remove fillers PR (Add one-click filler word removal #7) so the detected fillers can be cut in one click.
Open in Web Open in Cursor 

cursoragent and others added 3 commits July 27, 2026 00:21
- Transcript selection: continuous dimmed highlight that includes the
  spaces between words (native ::selection made transparent over words,
  selected spans marked imperatively with data-sel)
- Timeline word labels: bordered, background-filled pills sized to each
  word's duration with ellipsis truncation, red styling for cut words
- Remove the gradient R logo from the top bar and upload screen; the
  Rescript wordmark is the logo
- Progress reporting is now monotonic: model download percentage no
  longer drops when new files are discovered mid-download, and
  transcription progress is clamped to only move forward
- Drop the 'runs locally / models are cached' note from the progress card
- Hide the decorative right-hand tool rail until its tools are functional
- Only show the project title in the top bar once a file is loaded
@wassgha wassgha closed this Jul 27, 2026
wassgha added a commit that referenced this pull request Sep 3, 2026
Sentry has been collecting `RuntimeError: Aborted(CompileError:
WebAssembly.instantiate(): Compiling function #93 failed: Wasm SIMD
unsupported)`. Function #93 is `ffmpeg-core.wasm`: the module has 85
function imports and the reported offset lands in defined function #8.
The core simply will not compile on these machines, so the editor cannot
start at all.

`build.win` shipped x64 only, so Windows on Arm users run it under
emulation — where V8 turns Wasm SIMD off unless the emulated CPU reports
SSE4.1, which the older x64 emulators do not. Target arm64 as well.
Verified by packing one: the output is a PE32+ Aarch64 binary,
cross-built from an x64 host, which is what the release runner is.

Both arches go into one Rescript-Setup.exe — electron-builder's default
for NSIS with more than one arch. That leaves the download URL, artifact
name and update manifests untouched, at the cost of installer size;
splitting them would need `${arch}` in `nsis.artifactName` to avoid an
output-path collision, renaming the file every download link points at.

The probe is the part that holds either way. Every wasm binary the app
ships is a SIMD build — both ffmpeg cores list `+simd128` in
`target_features`, and onnxruntime is only distributed as
`ort-wasm-simd-threaded` — so there is nothing to fall back to, and the
honest thing is to say so. SharedArrayBuffer and SIMD are now one gate:
`useCrossOriginIsolated` becomes `useMediaEngineSupport`, which
distinguishes the two so each can give its own advice. Previously a
missing-SIMD machine got "Failed to process this file."

Also moves the last hardcoded English string in `lib/ffmpeg.ts` into the
catalog, so both engine-unavailable messages localize.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants