Changelog

Everything that shipped, release by release.

Scenaristo ships often and in the open. This page collects every release since the first signed build, written out in full: the features, the reasons behind them, and the fixes that made them behave. Newest first.

v0.2.4

Latest
TimelineWaveforms

The timeline opens on the whole recording, and the waveform underneath it stops fighting you.

The whole file, on open

Opening the timeline used to drop you into an arbitrary window of the recording. It now starts zoomed to the entire file, so the first thing you see is the shape of the whole thing: where the talking is, where the silences fall, and how much of it there is.

A waveform that keeps up

Four separate defects were making the waveform feel unreliable at speed, and all four are gone. The refined, high-resolution pass arrives sooner and lands with far less of a visual jolt. The mini strip draws its bars at the width it actually has rather than a width it assumed, and its playhead now lands on the waveform it names. Zoom refinement, which was quietly unable to fire at all, fires.

v0.2.3

SupportPerformance

Getting help without leaving the app, plus two decode paths that stopped doing redundant work.

Ask for help from inside the editor

Reporting a bug, sending feedback, and asking a question no longer mean hunting for a link. All three live in the app now, pointed at the right place.

Less work per waveform fetch

Two performance changes target the same hot path. The resolved output rate is memoized, so a windowed fetch opens the container once instead of once per call. And a lazily parsed Matroska index gets nudged into shape rather than walked end to end, which matters most on the long MKV recordings where that walk was most expensive.

v0.2.2

WaveformsRotationFixes

Waveforms stop loading whole files into memory, and rotated footage finally arrives the right way up.

Waveforms that never load the whole file

Waveform decoding is streaming now: memory scales with the number of buckets drawn rather than the length of the recording, and no whole file of PCM is ever held. Peaks are fetched in windows sized to the current zoom, so the cost of drawing tracks what you are actually looking at. Loudness measurement got the same treatment and streams rather than materializing the whole timeline. While audio is still being read, the strip says so instead of drawing a convincing line of silence.

Rotated footage, the right way up

Video shot on a phone carries a display matrix telling players which way to turn it. Decoded pixels honor that matrix now, and the probe reports display dimensions rather than the stored ones, so a portrait recording stops arriving on its side and stops exporting that way too.

Also in this release

  • An implausibly sparse container index is distrusted rather than believed.
  • A bulk filler strike rides one core compound instead of a covering band.
  • An empty project looks empty: a real waveform, no stale card.
  • Every modal answers Escape and Enter.
  • One reference-counted core://event subscription replaces the per-consumer ones.
  • libav’s log level is clamped, so the decoder stops flooding stderr.
  • Windows code signing moved from PFX and signtool to SSL.com eSigner.
  • Each Sentry release is tagged with the shipped tag rather than the frozen crate version.

v0.2.1

Windows

Windows joins the release channel.

Windows builds ship

The release channel publishes Windows alongside macOS, with a public-repo publish step and a windows.json updater manifest so installed copies can update themselves.

An encode ladder that degrades gracefully

Windows export runs a ladder of encoders: vendor hardware encoders first, a Media Foundation fallback underneath, and zero-copy wiring through the middle. A false positive on AMD’s AMF encoder used to dead-end the export instead of stepping down to h264_mf. It steps down now.

Also in this release

  • Hardware accelerated FFmpeg and CrispASR are built for Windows in CI, with libass provisioned and bundle DLLs mapped flat next to the executable.
  • Native File menu enable and disable calls are marshalled onto the main thread, and the menu is rebuilt on project open and close rather than mutated in place.
  • Resumed model downloads recover from an HTTP 416 instead of giving up.
  • Projects store absolute source paths when no relative form exists.
  • The Sentry DSN is wired into release CI, and download failures are captured.

v0.2.0

ShortsClipsFramingCaptionsLoudness

The whole short-form toolkit arrives at once: clips, vertical framing, burned-in captions, and exports conformed to what the platforms actually want. This is the big one.

Clips, and the vertical frame they go out in

Select a range in the transcript, press ⌘⇧K, and it becomes a clip, highlighted in the text with its own rail card and a per-platform duration badge. Whenever a clip exists, Export turns into a split button whose primary action exports that clip: its own MP4 with a re-timed SRT beside it, from one save dialog. Frame presets sit alongside it (Original, Vertical 9:16, Square 1:1) with a crop overlay carrying platform framing guides, a safe box, and a thirds grid, so you can see what survives the reframe before you render. A short clip pre-arms 9:16 unless you have already picked a preset yourself.

Framing that finds the face

Arming a crop preset runs a one-shot, on-device face detection that pre-fills the crop position, centering the speaker in the safe box, with an Auto-frame button to run it again. A position you set by hand is never re-clobbered without that explicit re-run. A Detections toggle under the preview draws what the detector actually sees on the frame you are paused at, confidence score included, so a poor suggestion is explainable rather than mysterious. Every degraded outcome falls back silently to the centered crop.

Captions burned into the picture

Burned-in captions become a project setting with two states, Off and On, and no ambiguous Auto. When they are on, the caption stream is composited into the exported frames, and the preview pump composites the same stream from the same setting, so what you watch is what you ship. Placement is decided once per export, choosing the safe-box position that keeps the words readable without covering the detected face, and never moving mid-video.

Exports conformed to what the platform wants

Every video export sends an encode spec through a single seam, and the core conforms the encode to the platform-recommended upload profile: High Profile, closed GOP, CABAC, BT.709 tagged and converted, HDR rejected up front rather than at the end. Short-form adds the ingest overlay on top. The Deliverable Mode dialog reads source against target row by row, so you see "Source: 3840×2160, will scale to 1920×1080" before you commit rather than after. Frame rate can be clamped into the 23 to 60 band, and export loudness gains a video flavor: Off, −14 LUFS Social under a −1.5 dBTP ceiling, or Custom.

Say what you are making, once

After the first import into a new project, a chooser asks what you are making: Long-form, Short-form, or Podcast. Confirming applies the matching presets in one shot (Short-form arms 9:16, turns burn-in on, and sets a three-minute target) and then gets out of the way. It is never re-imposed, and anything you change afterwards stays changed. Skip it and nothing is applied at all. The chosen mode also shapes which panels are on screen, and the native View menu puts any of them back for good.

Two read-outs that keep you honest

An optional target runtime shows a live under or over read-out against the edited timeline, and inline timecode markers appear at each thirty-second boundary of the post-cut timeline, reshuffling as you strike and restore material. Both answer the same question: how long is the thing you are actually making. Separately, if the measured loudness of your source sits far from the target while normalization is Off, the chooser says so, and says in which direction.

Also in this release

  • Audio-only exports gain a conformance clamp: sample rate snaps into the 44.1 or 48 kHz family, and MP3 bitrate lands in a mono or stereo band resolved from the source’s own probed bitrate. A source without a probed bitrate passes through unclamped rather than guessing at one.
  • tract-onnx, tract-nnef, and time were bumped past Dependabot advisories.

v0.1.13

CaptionsTimelinePerformance

Captions learn where a sentence ends.

Cues break where the sentence breaks

Caption cues now group at punctuation instead of at arbitrary word counts. A cue holds a clause or a sentence, which is the difference between subtitles that read and subtitles that merely appear, and it costs you nothing: the grouping comes from the transcript you already have.

Also in this release

  • The timeline playhead and scrub map through full-axis kept segments.
  • absorb_nonspeech_gaps and IntervalSet::union are linear rather than quadratic.
  • The scrub-preview decode is bounded and cancellable.

v0.1.12

Silence

Silence becomes as easy to cut as an "um".

Silence you can delete

Over-long pauses are detected alongside filler words and struck in exactly the same way: a bulk Remove silences action for the whole recording, or gap chips in the reader to step through them one at a time. Playback and export skip a struck silence the way they skip a struck word, and one click restores it. Dead air was always the easiest thing to cut and the most tedious to find.

Also in this release

  • A failed silence strike is no longer masked as a success, and the timeline clip’s extent is restored when the project is reopened.

v0.1.11

TranscriptionTranscript

A transcript release: real pauses come back, and a struck word can be un-struck.

Parakeet reports true pauses again

Word timestamps coming out of Parakeet had been swallowing genuine pauses, which left the transcript reading as one unbroken stream and gave silence detection nothing to find. The timestamps are honest again, and everything downstream of them reads correctly.

Backspace restores what it struck

Pressing Backspace or Delete on a word that is already struck restores it, rather than doing nothing and leaving you to hunt for the undo.

Also in this release

  • Identify speakers defaults to unchecked.
  • The supporting pane scrolls instead of compressing its cards.

v0.1.10

ImportProjects

Import and project state stop surprising you.

Re-importing behaves

Importing the identical file a second time is now a true no-op rather than something that quietly duplicates state. Importing a different file resets the annotations layer instead of leaving markers pointed at media that is gone, and the project frame rate follows whichever import is actually active.

Also in this release

  • The primary source resolves through the active timeline clip rather than the first row in the sources table.

v0.1.9

Fix

A single scoping fix: transcript reads are bounded to the project’s active source.

v0.1.8

CaptionsChaptersLoudnessSpeakers

Captions, chapters, and loudness normalization arrive together, and playback gets a great deal quieter under the hood.

Captions follow the edit everywhere it goes

A caption export operation with its own File menu entry writes subtitles from the corrected, post-cut transcript. Those captions are also baked into the FCPXML timeline export and into the MP4, so the file you hand off already carries them.

Chapters

Chapter markers live in the Annotations layer, with a transcript UI for pinning them to words. Export produces a YouTube-ready block, puts it on the clipboard, and writes FCPXML markers.

Loudness and speakers

Audio export presets normalize loudness to a target. Diarization improved on two fronts: VAD-turn diarization is wired onto the whisper ladder, and pyannote with an embedder handles re-identification inside diarize_words, so a voice keeps its identity across a whole file.

Playback that stops thrashing

The play path streams audio through a bounded ring buffer, a keyframe index is cached with a container fast path behind it plus warm and watchdog awareness, and import hashing runs in parallel. Scrub-seek decoding anchors at the keyframe nearest the requested time instead of somewhere adrift of it.

Also in this release

  • The supporting side panel is resizable and collapsible.
  • A transcript toolbar (broom and fade) and a unified toast replace the earlier ad hoc surfaces.
  • FCPXML asset start anchors at the media’s probed timecode rather than an assumed one-hour origin.
  • The macOS minimum system version drops to 11.0 to match the documentation.

v0.1.7

ProjectsTranscriptionDesign

Projects become documents, whisper.cpp is gone, and the app puts on its warm-editorial clothes.

A project is a file, and there is a place to keep them

A default library at ~/Documents/Scenaristo holds your projects. The File menu gains New, Open, Close, and Save As with native dialogs, backed by an app-level state store and Recent Projects. Save As and Duplicate Project are implemented with SQLite’s VACUUM INTO, so a copy is a genuinely clean copy. Importing media anchors an untitled project into the library rather than leaving the work homeless, a home surface lists Recents, and a welcome project is seeded on first launch.

One transcription ladder

whisper.cpp and whisper-rs are removed, and the whisper ladder runs through CrispASR alongside Parakeet. The whisper catalog is trimmed to large-v3 and large-v3-turbo, and long Parakeet transcriptions report chunked progress live instead of going quiet.

The warm-editorial refresh

The interface takes on the design the app wears today. Alongside it: caret keyboard navigation in the transcript, so the whole document is reachable without the mouse, and a toggle between a subtle and a marked style for the filler words the app highlights, because how loudly the app should point at your "um"s turns out to be a matter of taste.

Also in this release

  • The project WAL is checkpointed on shutdown and on idle, and the -wal and -shm files are actually removed on a graceful exit.
  • Project lifecycle operations are non-blocking, and Seek, open_frame_channel, and ExportVideo decode off the dispatcher mutex.
  • Playback PCM is resampled when the output device rejects the source rate, and silent play failures surface as a toast.
  • A second media import replaces the prior clip instead of appending to it.
  • The Import Media dialog no longer reopens in a loop after a cancel.
  • Preview and play run to an empirical decode budget, resize VideoToolbox frames on the GPU, and reseek keyframe-aware for large forward jumps.

v0.1.6

PlaybackReliability

Playback gets a new engine, and the app starts telling us when it crashes.

Play that does not get slower as the file goes on

Preview playback moves onto a canvas-direct path fed by a sequential decoder. The path it replaces decoded every frame independently, so the further into a recording you played, the more work each frame cost. That cost is gone: playing at the ninety-minute mark is as cheap as playing at the start.

Crashes and hangs, reported

Crashes and hangs are captured through Sentry, with an IPC hang watchdog for the cases where nothing crashes and nothing moves either.

Also in this release

  • Spanish transcribed as English is fixed, with selectable Canary and Cohere engines, ECAPA automatic language detection, and an overlap-tiling correction.
  • Backspace and Delete in the transcript reader are caret-based.
  • Changelog generation is automated: a draft workflow, a release body, and a pre-push guard.

v0.1.5

Updates

The app tells you when there is a new version, and installs it for you.

In-app updates

A notification appears when a new version is available, and you can install it without leaving the app. Auto-update is disabled under tauri:dev, so development stops raising spurious update prompts.

v0.1.4

macOS

The crash on signed and hardened macOS builds when opening a file dialog is fixed.

The file dialog opens

The crash traced back to a missing NSOpenPanel entitlement. That entitlement is declared now, along with the folder-access usage strings macOS requires before it will let the app ask for anything.

v0.1.3

Updates

The foundation for in-app updates.

Signed updates, wired in

The Tauri updater plugin is wired in, so the app can receive and apply signed updates from the release endpoint. The visible half of this arrives two releases later, in 0.1.5.

v0.1.2

ProjectsmacOS

Schema migrations stop being scary, and the signed app launches.

A backup before every migration

When the app needs to migrate an existing project’s schema, it takes a backup first, so nothing is lost if the migration goes wrong.

Also in this release

  • The signed macOS .app failed to launch because the CrispASR and FFmpeg dylibs were not bundled. They are now.

v0.1.1

Playback

The playhead reports the position you are actually hearing.

Sync you can trust

The playback clock subtracts audio output latency and reports the heard position, so the highlighted word in the transcript matches the word coming out of your speakers.

v0.1.0

First releasemacOS

The first distributable release: a signed and notarized macOS DMG.

Transcription and speakers

CrispASR with Parakeet is the default transcription engine, replacing whisper.cpp. Speaker diarization produces stable identities across a file through CrispASR’s global diarizer, and those speakers persist between sessions and can be renamed. Transcription is non-blocking, with live progress events, and hardware-acceleration detection is shared across the backends.

Playback and preview

Playback runs in real time on an audio clock through cpal, with video as the master clock and frames painted while you scrub. Preview rides a program stream: a loopback transport, a fragmented-MP4 MSE surface inside WKWebView, and cooperative render cancellation.

Export

MP4 export at source resolution honors every cut. FCPXML 1.11 serializes the edit for Final Cut, with an Export Timeline menu item to reach it. On Apple silicon, an opt-in zero-copy VideoToolbox path takes decode straight into encode.

The editing surface

Drag and drop import with a native drop target and a visual overlay, a Script view laid out as a US Letter manuscript with screenplay character cues, word corrections dispatched to core as you type, and a splash screen that shows the hardware-acceleration checklist while the app starts.

Also in this release

  • Seek extraction starts from the real keyframe landing, not the requested anchor.
  • Core resolves the program-stream source from the timeline instead of expecting the UI to pass a raw source id.
  • Scrubbing is latest-wins, through seek-sequence correlation and coalescing in core.
  • The project frame rate is set from the imported media, which fixes export and preview drift.
  • Contiguous deleted-word cuts merge, absorbing the inter-word silence cleanly.
  • Import hash progress and the download indeterminate bar render correctly.
Keep it coming

Download the latest build,
then tell us what broke.

The app updates itself, so you only have to do this once. Bug reports and feature requests reach a human: there is a link inside the app, or write to us directly.

Free today · no account required