github murtaza-nasir/speakr v0.10.3-alpha

2 hours ago

Speakr v0.10.3-alpha

This release is shaped by community reports and contributions: two new upload conveniences, two community-contributed features, a batch of correctness fixes across chat, processing, and the browser cache, and localization catch-up. Every instance upgrades with a plain image pull; database columns migrate automatically and no configuration change is required.


New features

  • Meeting date from filename (#342). Voice recorders and phone apps commonly encode the recording date in the filename (20260716_meeting.mp3, 260716_1102.m4a). A new preference, off by default, parses that date at upload time and uses it as the recording's meeting date, taking precedence over file timestamps and embedded metadata. Preset patterns cover YYYYMMDD, YYYYMMDD_HHMM, YYYY-MM-DD, YYMMDD_HHMM, and YYMMDD, an Auto mode tries the common formats, and a custom regular expression with named groups handles unusual schemes. Files without a matching date keep the current behaviour without failing the upload, the parsed date stays editable, and the setting also applies to the automated processing folder. Dates parsed from filenames are wall-clock values, so browser uploads carry the uploader's timezone and date-only matches are anchored so the calendar date renders the same in every viewer's timezone.

  • Configurable auto-export filenames (#348). Exports no longer have to be named recording_<id>.md. A filename template in account settings (shown when auto-export is enabled) supports {{id}}, {{title}}, {{filename}}, and meeting-date variables ({{date}}, {{datetime}}, {{time}}, {{year}}, {{month}}, {{day}}), so {{date}} {{title}} yields 2026-07-16 Team Standup.md. Each recording remembers the name it was exported under: re-exports overwrite the same file and deletion renames it with the [deleted]_ prefix regardless of later template changes. Rendered names are sanitized for filesystem safety with unicode titles preserved, and collisions disambiguate with the recording id. Changing the template affects new exports; a Rename existing exports button migrates every existing file to the new scheme in one pass. The default remains recording_<id>, so nothing changes until a template is set.

  • Mobile external microphone selection (#345, community contribution by @cybersader). On Android and iOS, when a likely external microphone (USB receiver, wireless or headset microphone, webcam, audio interface) is present after permission is granted, Speakr expands the input picker with an "Another microphone is available" notice before recording starts. Detection is deliberately conservative and label-based, so devices without a recognisable external label never trigger the prompt, and the prompt never appears when a recording is resuming after an interruption. Device selections persist across sessions, and the Mic + System mode now honors the selected primary input. Note for users who route system audio through a virtual device set as their default input: the mic leg of Mic + System now uses your selected device rather than always the OS default.

  • ASR Voice Recorder webhook (community contribution by @cybersader). A new endpoint, POST /api/v1/integrations/asr-voice-recorder/upload, accepts the multipart webhook format of the ASR Voice Recorder Android app, which can only place its secret in a form field. The secret is a normal Speakr API token, validated against the same token table with the same semantics; the form field is not an authentication source for any other route. Deliveries are idempotent within a replay window, per-IP rate limited with a cost model based on the declared upload size, and documented in the API reference. This work also tightened two pre-existing size-limit gaps in the regular upload path and fixed a staging filename collision.

  • Full Whisper language list (#359). The transcription language dropdowns on upload and reprocess offered twelve hardcoded languages; they now offer the full Whisper set of roughly one hundred, with names localized to the interface language automatically. Auto-detect remains the default.

  • Bulk reprocess localization. The bulk reprocess modal, its toasts, and the remaining hardcoded tooltips in the detail views are now localized across all seven interface languages, with count-aware phrasing. Thanks to @ikelvingo for flagging the gap and contributing the initial en/zh version.

Fixes

  • Truncated chat responses are now flagged (#349). When a streaming chat or Inquire response hits the configured output token limit, the provider's truncation signal was discarded and the partial answer displayed as if complete. The terminal stream event now carries the finish reason, and the interface keeps the partial answer with a visible, localized note explaining that the token limit was reached, with a hint to continue or raise CHAT_MAX_TOKENS. This is easiest to trigger with reasoning models, whose hidden reasoning tokens share the output budget.

  • Database lock during Inquire reindexing (#355). Editing speakers with summary regeneration enabled could fail with "database is locked": the chunk reindex held SQLite's write lock across the embeddings API call, which can take half a minute against a cold local model, starving the summarize-job enqueue. Embeddings are now generated before the chunk swap, so the write transaction lasts milliseconds. The rollback safety is preserved: a failed or partial embedding response leaves the recording's existing chunks untouched.

  • Stale interface after upgrading (#357). Upgrading the Docker image could leave the browser serving the previous release's scripts and translation files against new pages, producing blank panels and "Translation not found" errors until site data was cleared manually. Three layers now prevent this: each release registers a service worker with its own cache namespace, static assets are revalidated on load instead of trusted indefinitely, and translation files are always fetched fresh. Upgrades from releases before this one may need a one-time manual clear; after that the cache self-heals on every future upgrade.

  • Audio files with non-UTF-8 metadata (#350). ffmpeg copies container metadata such as ID3 tags into its output as raw bytes, so a file tagged in a non-UTF-8 encoding (for example GBK) crashed processing with a decoding error, including inside the Linux container. All ffmpeg and ffprobe output is now decoded defensively, trying UTF-8, then the system encoding, then replacement characters, across the conversion, chunking, probing, and stitching paths. Reported by @ikelvingo.

  • Embedding provider compatibility (#352). Embedding requests now ask for float vectors explicitly, since the OpenAI SDK's base64 default is not supported by all OpenAI-compatible providers. When a model rejects the configured EMBEDDING_DIMENSIONS parameter (for example BAAI/bge-m3), the request is retried without it and the rejection remembered, instead of failing the whole embedding pipeline. Models that support dimensions continue to receive the setting. Reported by @ikelvingo.

  • Non-ASCII transcript download filenames (#360, community contribution by @Ceasy). Downloading a transcript for a recording with a non-Latin title (Cyrillic, Chinese, accented characters) saved the file as underscores. The download now keeps the unicode title, advertising it through the standard RFC 5987 header parameter with an ASCII fallback, and the four duplicated filename parsers in the frontend are consolidated into one shared helper that reads it correctly. Reported, diagnosed, and fixed by @Ceasy with tests on both sides.

  • API voice suggestions repaired. The API v1 endpoint for a recording's speakers called the voice-matching function with reversed arguments and mishandled its return value, so its suggestions were always empty. It now returns per-speaker voice-match suggestions like the web interface.

  • Migration ordering. The one-time email normalization migration ran before column migrations, so an upgrade that adds user columns skipped it for one restart with a warning. It now runs after all column migrations.

Database

Five new columns are added automatically on first start: parse_filename_dates, filename_date_pattern, filename_date_regex, and export_filename_template on the user table, and export_filename on the recording table. All are nullable or default to off, and all migrations are SQLite and PostgreSQL compatible.

Credits

Thanks to @cybersader for the mobile microphone selection and ASR Voice Recorder webhook contributions, to @ikelvingo for the ffmpeg encoding, embedding compatibility, and localization reports and initial patches, to @Ceasy for the non-ASCII download filename fix, and to everyone who filed the detailed issues that shaped this release.

Don't miss a new speakr release

NewReleases is sending notifications on new releases.