Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
Added
- Transcode job resilience (F2): separate
environmentalAttemptscounter onjobs(transient/environmental failures no longer burn the realMAX_TRANSCODE_ATTEMPTSretry budget, capped atMAX_ENVIRONMENTAL_ATTEMPTS). SharedredispatchJobhelper (apps/api-edge/src/services/job-redispatch.ts) re-queues a job with no live orchestrator (waitTokenIdnull) directly;reclaim-stale-dispatch-jobsand/fail(transient-aware) use it. Manual rescue of orphaned jobs is now automated. - Admin job requeue:
POST /v1/admin/jobs/:jobId/requeue(superadmin) kills stale non-terminal dispatches, re-queues viaredispatchJob, resets the job toqueued, and auditsJOB_REQUEUED. - Worker hardware probe + CPU fallback (F3):
apps/transcoder/internal/hwprobethrowaway-encode probes for VA-API/NVENC atauto; on a ladder error with hwaccel enabled the worker re-encodes in software (.cpuladder, swapped into place). Fixes the prior 64x64 test source (below VA-API's 128px minimum) that would falsely reject working hardware. - Secret bindings single source of truth (F1):
apps/api-edge/src/secret-bindings.ts+ a test cross-checking every[[secrets_store_secrets]]binding inwrangler.tomlagainst it (the exact gap that 500'd the TUS path); base64 validation onJWT_SECRET/SHARED_AUTH_SECRET. - Least-privilege worker DB role:
worker_listener(CONNECT-only) provisioned on prod + staging Neon forLISTEN job_queuewakeups;scripts/provision-worker-listener.sh <env> [--rotate]andscripts/start-worker.sh [env]wrap provisioning + launch. Documented indocs/worker-setup.md.
Changed
- R2 CORS reconciled: prod bucket now matches
infra/r2/strum-vod-cors.json(correct dev portslocalhost:42901/42911+vod/player.usestrum.app), aligning with staging. docs/worker-setup.md: documents theworker_listenerrole, the LISTEN/NOTIFY wakeup path, and the provisioning/start scripts.
[0.1.0] - 2026-02-13
Added
- Initial release of Strum VOD
- REST API with Fastify for asset management (create, upload, import, process, hard-delete)
- Node worker: BullMQ↔Redis-Streams bridge + AI pipeline (transcription, subtitles, chapters, highlights)
- NEW: AI subtitle translation — context-aware sliding window (±2) translation to multiple languages (ISO-639-1) using LLM with glossary, speaker, and video context support. Outputs per-lang
.vtt/.srt+ index JSON. Standalonetranslate-subtitlesjob type for on-demand re-translation. Player renders multiple<track>elements for language selection. - Go transcoder (
apps/transcoder) — single-pass FFmpeg HLS ladder, 7 renditions 360p–4320p (H.264/HEVC, CPU or VA-API), shared EXT-X-MEDIA audio track, thumbnail sprites, downloadable MP4s - Async Modal transcription provider (scale-to-zero GPU) with HMAC-signed webhook callback, retry, and 5-min reaper
- React dashboard with upload, import, asset management, video playback, collections (folders)
- Embeddable HLS player with quality selector, thumbnail seek preview, comments & reactions
- Installable PWAs (dashboard + player) with Workbox service workers
- All-in-one Docker image with embedded PostgreSQL and Redis
- Docker Compose setup for local development (Postgres, Redis, MinIO)
- S3-compatible storage support (AWS S3, Cloudflare R2, Backblaze B2, MinIO)
- Pre-signed URL, resumable TUS, and direct (shared-volume) uploads
- URL import from public video URLs
- Shared Drizzle ORM schemas via
@strum-vod/dbpackage (PostgreSQL) - Organizations, members, roles, and API keys (multi-tenant)
- JWT sessions + email OTP magic-code login (Resend / SMTP / console)
- Analytics: views, watch time, retention, engagement, heatmap, live viewer count (SSE)
- Outgoing webhooks (
asset.ready,asset.error,asset.deleted,ai.completed,ai.failed) with delivery log & retry - Optional Stripe billing with tiered plan limits and usage metering
- Scheduled PostgreSQL backups (
pg_dump→ R2) - Superadmin dashboards (orgs, asset errors, webhook failures, BullMQ queues) with audit log