github richardr1126/openreader v5.0.0

3 hours ago

OpenReader v5 is a ground-up rebuild of how playback, document processing, storage and self-hosting work. Audio is now generated ahead of you by a background compute worker and streamed as one continuous, seekable timeline. The worker owns every heavy workload, one policy engine rate-limits all of them, and a new admin, account and email layer makes OpenReader practical to run for other people.

This is a major release with breaking changes. Read the ⚠️ Upgrading from v4.4.0 section below before you deploy.

✨ What's New

🚀 New

Progressive background playback (PR #133, PR #135, PR #137, PR #138, PR #139, PR #140)

  • Press play and audio starts as soon as the first segment is ready. The compute worker keeps generating ahead in the background, outside the browser request, so playback no longer depends on the tab driving each request.
  • The whole document is one continuous, seekable timeline, and audio streams directly from the worker as a signed MP3.
  • Generated audio is cached and reused when you seek, reload, or move between pages and chapters. Nothing is regenerated that already exists.
  • Pausing, seeking or resetting the cache cancels stale generation right away, so provider calls stop for audio you'll never hear.
  • A duration-based play-ahead buffer keeps a ready window in front of you. Forward generation grew from 8 to 48 segments, to stay ahead even with production provider latency.
  • Admins can choose how far generation continues after the reader stops listening: the current PDF page or EPUB chapter (default), or the rest of the document (Settings → Admin → Instance).
  • Stalled streams recover automatically with bounded retries and keep the audio already cached. Safari and iOS autoplay now unlock correctly.

Brand-new player (PR #133, PR #140)

  • A scrub bar along the top edge covers the whole document. Already-generated audio is shown in your accent color, and dragging shows a time preview.
  • current / total time readout for the document.
  • Live buffer badge ("12s ahead", "Loading ahead · 4s ready") shows how much audio is ready.
  • The play button doubles as a cancel button while audio loads.
  • Dedicated phone layout: two rows, larger touch targets and a compact PDF page-navigation row.

Unified compute rate limiting (PR #141, PR #142, PR #146), docs

  • One versioned policy covers every expensive workload: PDF layout parsing, playback sessions, playback planning, audiobook export, document previews, DOCX conversion, account export and TTS synthesis. Each action has its own enable switch.
  • Four layers of control:
    • admission windows (burst and sustained limits per user or IP)
    • active leases and queues
    • worker resource pools (CPU, speech-alignment model, FFmpeg, LibreOffice, archive)
    • per-provider concurrency plus rolling request and character limits
  • Limits are coordinated across worker replicas, and a provider 429 Retry-After triggers a shared cooldown instead of a retry storm.
  • TTS characters are charged only for segments that are actually synthesized, not for cached audio. Audio you've already generated stays playable after you reach a limit.
  • New visual policy editor in Settings → Admin → Compute. Users can see their own TTS usage in Settings → Account.
  • Self-host defaults stay out of the way: admission limits and generated-character limits are off, and provider concurrency is 3.

User administration (PR #145), docs

  • New Admin → Users directory with search, account-kind and status filters, and document count, stored bytes and compute activity for each user.
  • Change a user's role or status, or delete them. Select many users to approve, suspend, restore or delete in bulk.
  • The last administrator is protected: every demote, suspend and delete path, including self-deletion, is checked atomically.
  • User deletion is durable. If the server restarts mid-delete, cleanup resumes automatically on the next startup.

Signup policy with approval queue (PR #145)

  • The on/off signup toggle is now a three-way policy: Open, Approve (new accounts wait in a pending state until an admin approves them) or Closed.

First-boot bootstrap admin (PR #145), docs

  • Set BOOTSTRAP_ADMIN_EMAIL and BOOTSTRAP_ADMIN_PASSWORD (or BOOTSTRAP_ADMIN_PASSWORD_FILE; minimum 16 characters) to create the first administrator of a new instance.
  • Admin rights activate after that account changes its initial password in Settings → Account.

Account self-service (PR #145)

  • New Account Security panel: edit your display name, email and password inline.
  • Email changes are verified, with resend support. Changing your password signs out your other sessions.

Account email with Resend (PR #143), docs

  • Opt-in email verification, forgot-password and reset-password flows, with new /verify-email, /forgot-password and /reset-password pages.
  • New Admin → Email panel stores the Resend API key encrypted and can send a test email.
  • The worker delivers email durably using responsive, theme-aware templates. You can pre-configure it through the accountEmail runtime seed key.

⚡ Improved

Compute worker owns all heavy work (PR #133), docs

  • PDF layout parsing, PDF and EPUB preview rendering, DOCX conversion (headless LibreOffice), audiobook and account exports, retention, and cleanup all run on the worker now. The web app stays responsive while it works.
  • The worker is locked down: it has no database access and never receives POSTGRES_URL or AUTH_SECRET.
    • TTS provider API keys are handed out per job by an authenticated app credential broker. They never pass through NATS, SSE, stored artifacts or logs.
    • Each trust boundary uses its own secret.
  • Worker HTTP requests that are aborted now release their in-flight slots (PR #136).

Audiobook export rebuilt (PR #133, PR #144)

  • M4B and MP3 audiobooks are now assembled by the worker from the same cache playback uses, so audio you've already listened to isn't generated again.
  • A segment that fails to generate becomes a short pause instead of failing the whole export. The export reports how many segments were skipped, generated and planned, and an export that would be entirely silent is rejected.
  • Export progress survives page reloads and reconnects.
  • This replaces v4's per-chapter generate, regenerate and delete workflow with a single progress-tracked export.

Account export rebuilt (PR #133, PR #144)

  • Account data export is now a worker job with live progress and a dedicated download. It covers the v5 schema and still reads legacy archives.

One reader startup for every format (PR #133)

  • PDF, EPUB and HTML documents now share one startup pipeline, with live server-sent progress and a consistent loading screen. This replaces the PDF-only layout-scan animation.

More accurate word highlighting (PR #133, PR #135, PR #140)

  • Highlighting uses only exact Whisper word timings. The proportional estimates that drifted out of sync are gone.
  • English documents use the faster Whisper Tiny English model, and other languages use multilingual Whisper Base.
  • Model download progress is bounded and clearly labeled.

Settings is now a full page (PR #143)

  • The settings modal is now a Finder-style page at /app/settings, with General and Admin sections that have their own URLs.
  • General: Appearance and Account, including account security, your TTS provider and the changelog.
  • Admin: Users, Providers, Email, Instance, Compute, Maintenance.
  • Maintenance tasks for expiring export artifacts and pruning compute-limit records can be run on demand.

Uploads (PR #143)

  • The file picker, drag-and-drop, created documents, URL import and server-library import all share one upload pipeline.
  • Real transfer and DOCX-conversion progress, per-file cancel, and retry for failed files only.
  • Files upload into the folder you're viewing, and browser memory use is bounded for large batches.
  • New Add Documents entry point and upload status in the sidebar.

Finder

  • Simpler header and status areas. Previews and scroll position are kept when you switch folders (PR #143).
  • In presigned deployments, document previews load straight from object storage with long-lived cached URLs, making large libraries faster and cheaper to browse (PR #146).

Storage transport (PR #133), docs

  • New explicit S3_INTERNAL_ENDPOINT and S3_PUBLIC_ENDPOINT, plus S3_BROWSER_TRANSPORT (auto, proxy or presigned). They replace loopback-address guessing and the old fallback routes.
  • The embedded SeaweedFS default now serves browser traffic through a same-origin proxy, so port 8333 no longer has to be exposed.
  • New S3_AUTO_CREATE_BUCKET, and WEED_MINI_BIND_HOST / WEED_MINI_ADVERTISE_HOST / WEED_MINI_PORT for the embedded store.

Self-hosting (PR #143), docs

  • Docker Compose is now the recommended setup, with slim, full and local-build stacks in examples/docker/.
  • A complete runtime seed example ships at examples/openreader-seed.json.
  • API_MODEL_NAME sets the default model for the seeded TTS provider.

Lower hosting cost and more resilient config (PR #146)

  • The worker refreshes its limit policy every 5 minutes instead of every 60 seconds.
  • Runtime config is cached briefly (RUNTIME_CONFIG_CACHE_TTL_MS, default 15s) and falls back to the last known-good values if the database has a transient error. A database blip can no longer, for example, reopen signups.

Privacy and security

  • Refreshed privacy page and data disclosures. You're asked to accept the privacy terms again when the policy changes.
  • Analytics require explicit consent, and ONNX and Next.js telemetry are disabled (PR #133).

Packages and testing (PR #133)

  • TTS provider code now lives in a reusable @openreader/tts package, and runtime configuration in @openreader/runtime-config.
  • The end-to-end suite was rebuilt as real browser walkthroughs on Chromium and WebKit, alongside a much larger unit test suite.

🐛 Fixed

  • Fixed document downloads in presigned-storage deployments (PR #134)
  • Fixed live playback state being overwritten by stale sessions, and provider work now stops promptly when you pause or seek (PR #137)
  • Fixed playback progress updates that could be missed right after a session started. Cached audio is found per segment instead of by probing the whole book (PR #138)
  • Fixed seek and playback lifecycle races that could leave the player stuck (PR #139)
  • Fixed playback readiness leaking between sessions (PR #140)
  • Fixed a WebKit flake when saving PDF view preferences, and reduced redundant timeline refreshes (PR #142)
  • Fixed audiobook export progress after reconnects, queued exports carried over from v4, and account export on the v5 schema (PR #144)
  • Fixed glitchy transitions between the changelog and onboarding modals (PR #144)
  • Fixed signup-policy migration for instances that had signups disabled, so they stay closed after upgrading (PR #145)
  • Fixed clearer email verification messaging, the email settings loading state, the anonymous device limit label, and email settings saves
  • Fixed compute-limit callbacks from the credential broker being rejected

⚠️ Upgrading from v4.4.0

v5 is a hard cut. Back up your database and object-storage volumes before upgrading. Never run docker compose down -v: it deletes the data you are upgrading.

What happens automatically

On startup, the Docker entrypoint applies schema migrations 0013 through 0020 and then permanently deletes the retired v4 object prefixes tts_segments_v1/, tts_segments_v2/ and audiobooks_v1/. Check the logs for the migration and decommission completion messages.

v4 generated audio and audiobooks are not carried over.

  • The migrations drop the old TTS segment cache and audiobook tables, and reset TTS usage counters.
  • Audio regenerates on demand into the new v5 playback cache.
  • Export anything you want to keep before upgrading.

Documents, folders, users, settings, preferences and reading progress are preserved. Existing administrators remain administrators.

Docker Compose

Pull the new image and recreate your stack with the same project name, volumes, AUTH_SECRET and storage settings. See Upgrade from v4.4 to v5.

The Compose examples moved from docker/examples/ to examples/docker/. Update your -f paths if you use the repository files.

Required new configuration

  • TTS_PLAYBACK_TOKEN_SECRET is required for playback in every deployment, including the embedded worker. Set a stable random value.
  • COMPUTE_CREDENTIAL_BROKER_TOKEN is generated automatically when the worker is embedded. With an external worker, set it on both the app and the worker, and set COMPUTE_CREDENTIAL_BROKER_URL on the worker.
  • Browsers must be able to reach the compute worker (port 8081). Audio streams directly from the worker.
    • The Compose examples already publish it. With plain docker run, add -p 8081:8081, COMPUTE_WORKER_HOST=0.0.0.0 and COMPUTE_WORKER_PUBLIC_URL=http://<host>:8081 for LAN or remote access.
    • Port 8333 no longer needs to be exposed.
  • External worker: deploy the v5 app and v5 worker together. Do not give the worker POSTGRES_URL or AUTH_SECRET. See Compute worker.

External S3 storage

  • With external (non-embedded) S3, S3_BROWSER_TRANSPORT=auto refuses to start unless you set either:
    • S3_PUBLIC_ENDPOINT (a dedicated HTTPS hostname, not a path mount), or
    • S3_BROWSER_TRANSPORT=proxy.
  • Proxy mode is not supported on Vercel.
  • S3_ENDPOINT still works but is deprecated and logs a warning. Switch to S3_INTERNAL_ENDPOINT and S3_PUBLIC_ENDPOINT.

Vercel and other app-only deployments

These deployments have no entrypoint to run migrations.

  1. Take the v4 deployment offline and back up.
  2. Run pnpm migrate against production.
  3. Run pnpm migrate-decommission with the production S3 configuration.
  4. Deploy v5 together with its compute worker.

See Migrations.

Removed and renamed settings

v4 v5
ADMIN_EMAILS No longer grants admin. Existing admins are kept; new instances use BOOTSTRAP_ADMIN_EMAIL and BOOTSTRAP_ADMIN_PASSWORD
RUN_FS_MIGRATIONS RUN_V4_DECOMMISSION (the filesystem-to-S3 migration was removed)
IMPORT_LIBRARY_DIR IMPORT_LIBRARY_DIRS
COMPUTE_JOB_CONCURRENCY Removed. Concurrency is set in the compute limit policy
ENABLE_TEST_NAMESPACE Removed
enableUserSignups (setting and seed) signupPolicy: open, approval or closed (migrated automatically)
disableTtsRateLimit, ttsDailyLimit*, computeParse* (seed) computeLimitPolicies

The full list is in Environment variables.

Removed API routes

If you call OpenReader's API directly:

  • /api/audiobook*: use the worker-backed audiobook export.
  • /api/tts/segments/ensure, /api/tts/segments/manifest and /api/tts/segments/audio/fallback: use the playback session API.
  • /api/documents/blob/*/fallback and /api/documents/blob/get/presign: removed.
  • /api/rate-limit/status: removed.
  • /api/documents/library*: moved to /api/local-library*.

Full Changelog: v4.4.0...v5.0.0

Don't miss a new openreader release

NewReleases is sending notifications on new releases.