Build Wisp: on-device transcription studio (web + native, one codebase)
CI / test (push) Has been cancelled
CI / deploy-web (push) Has been cancelled
CI / build-apk (push) Has been cancelled

Private, offline speech-to-text that runs Whisper on the user's own device —
free, no account, no per-minute fees. Replaces Otter.ai / Rev.

- Pure, tested engine: chunking, overlap timestamp-stitching, exports
  (SRT/VTT/TXT/MD/JSON), WAV codec, resampler, job queue, model catalog (142 tests).
- Platform-abstracted TranscriptionEngine: transformers.js on web (loaded from
  CDN at runtime to dodge Metro's onnxruntime-web bundling limits), whisper.rn
  on native. Shared pipeline orchestrates decode -> chunk -> transcribe -> stitch.
- Cross-platform StorageRepo (Dexie web / expo-sqlite native), Zod-validated.
- UI: library + search, import, live-progress transcription, synced click-to-seek
  editor, multi-format export; model picker + privacy in settings.
- Web ships as a single-page PWA with COOP/COEP isolation for threaded WASM;
  Docker (nginx) image + Traefik compose for wisp.briggen.dev.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-13 17:54:21 +02:00
parent 97996c9846
commit 9f42ee2460
72 changed files with 7293 additions and 421 deletions
+35
View File
@@ -0,0 +1,35 @@
# Self-contained compose project for wisp.briggen.dev.
# Deploy: get the repo onto the server at /root/wisp, then:
# cd /root/wisp && docker compose -f deploy/wisp.compose.yml --project-directory . up -d --build
# Joins the EXISTING external `proxy` network — the shared Traefik stack is untouched.
# Wildcard *.briggen.dev DNS + Traefik's letsencrypt resolver issue TLS automatically.
name: wisp
services:
wisp:
# Build the static web app (Bun + Expo export) into an nginx image that
# serves it with the cross-origin isolation headers threaded WASM needs.
build:
context: .
dockerfile: docker/web.Dockerfile
container_name: wisp
restart: unless-stopped
security_opt:
- no-new-privileges:true
# Static nginx; tiny footprint. Caps keep the blast radius off the shared host.
mem_limit: 256m
memswap_limit: 256m
pids_limit: 200
cpus: 1.0
labels:
- "traefik.enable=true"
- "traefik.http.routers.wisp.rule=Host(`wisp.briggen.dev`)"
- "traefik.http.routers.wisp.entrypoints=websecure"
- "traefik.http.routers.wisp.tls.certresolver=letsencrypt"
- "traefik.http.services.wisp.loadbalancer.server.port=8080"
networks:
- proxy
networks:
proxy:
external: true