Commit Graph
179 Commits
Author SHA1 Message Date
James Pine 60c0fe3b92 isolate shutdown unload calls so one failure doesn't block the other 2026-03-16 03:50:28 -07:00
James Pine c99828cf76 fix startup db session leak on error (rollback + close in finally) 2026-03-16 03:49:21 -07:00
James Pine 5c4b979480 suppress E402 for app.py (AMD env vars must precede torch import) 2026-03-16 03:47:56 -07:00
James Pine 2d1b0ae820 remove unused _get_cuda_dll_excludes function 2026-03-16 03:46:58 -07:00
James Pine 69486c2a77 handle null duration in story_items migration 2026-03-16 03:44:33 -07:00
James Pine e9f63d6c57 reject model migration to subdirectory of source cache 2026-03-16 03:43:37 -07:00
James Pine 0dabb121c9 improve startup logging: version, platform, data dir, db stats
Replace verbose startup messages with a clean summary:
- App version, Python version, OS/arch
- Database path (fix None display), data directory
- Profile and generation counts
- Backend, GPU, model cache path
- Clean up stale loading_model status on startup
- Remove noisy progress manager log line
2026-03-16 03:42:39 -07:00
James Pine 473bb3e9fb fix take-label race in regeneration, add accessible focus to select
- Use DB COUNT query instead of list length for take-N label to avoid
  TOCTOU race between list_versions and create_version
- Add focus:bg-muted to SelectTrigger for keyboard focus visibility
2026-03-16 03:22:05 -07:00
James Pine 0d0b62ea93 address CodeRabbit review: fix 4 critical + 12 major issues
Critical:
- Remove dead backend.utils.validation PyInstaller hidden import
- Fix story_items table rebuild to preserve track/trim/version columns
- Guard cache migration against same source/destination path
- Fix regeneration audio overwrite (use random uuid suffix per take)

Major:
- Engine selector: validate language on Qwen switch, clear stale modelSize
- Sync language validation regex between profile create and generate (22 langs)
- Guard CUDA download against duplicate concurrent requests
- Only set model_size for engines that support multiple sizes
- Fix 404 swallowed by generic except in history export
- Validate audio_path before FileResponse in export-audio
- Transcription: stream uploads in 1MB chunks, use robust cache check,
  call complete_download() on Whisper download success
- Set clean version as default when effects chain validation fails
- Return explicit error when Windows port occupied by non-voicebox process
2026-03-16 03:12:01 -07:00
James Pine 3187344f01 add model loading status, effects preset dropdown, clean up UI
Backend:
- Generation service reports 'loading_model' status only when model
  is not yet in memory, then 'generating' once inference starts
- Migrate hf_offline_patch.py from print() to logging module
- Update ADDING_TTS_ENGINES.md for post-refactor file paths

Frontend:
- HistoryTable shows 'Loading model...' vs 'Generating...' based on step
- FloatingGenerateBox: replace instruct toggle + inline effects editor
  with an effects preset dropdown (third dropdown after language and engine)
- Instruct UI removed for now (form field preserved for future models)
- Remove focus ring from Select component globally
2026-03-16 02:58:41 -07:00
James Pine 7b0fbfb567 rewrite backend README, remove completed refactor plan, update style guide
Replace the outdated backend README (473 lines of stale API docs and
pre-refactor file tree) with a concise architecture document covering
module structure, request flow, backend selection, API domain overview,
and development commands.

Delete REFACTOR_PLAN.md -- all phases are complete.

Update STYLE_GUIDE.md to remove refactor plan references and replace
the verbose target layout with the current actual structure.
2026-03-16 02:18:34 -07:00
James Pine b3012ed10c move CRUD and service modules into services/, platform_detect into utils/
Move 9 business-logic modules from the backend root into services/:
channels, effects, history, profiles, stories, versions, export_import,
transcribe, tts. Move platform_detect.py into utils/.

Backend root now contains only infrastructure (app, main, config, server,
models, build_binary) and docs. All 94 routes verified.
2026-03-16 02:15:20 -07:00
James Pine 88536d27f7 extract routes from main.py into domain routers (Phase 4)
Split the 2,578-line main.py (90 routes) into 12 domain-specific router
modules under routes/. main.py is now a 45-line entry point.

New structure:
- app.py: FastAPI instance, CORS, startup/shutdown, safe_content_disposition
- routes/: health, profiles, channels, generations, history, transcription,
  stories, effects, audio, models, tasks, cuda
- services/cuda.py: moved from cuda_download.py

Also includes Phase 5 database/ package (from parallel agent):
- database/__init__.py re-exports all symbols for backward compat
- database/models.py, session.py, migrations.py, seed.py

All 90 routes verified registered and app imports cleanly.
2026-03-16 02:03:15 -07:00
James Pine 89d6e364d4 move pyproject 2026-03-16 01:48:26 -07:00
James Pine b7781951df comment cleanup 2026-03-16 01:46:19 -07:00
James Pine fe19a9ca47 add style guide, ruff config, generation service extraction, remove Makefile
- Add backend/STYLE_GUIDE.md covering formatting, imports, types, docstrings,
  comments, error handling, async, logging, and naming conventions
- Add pyproject.toml with ruff linter/formatter config (ERA, FIX, isort, pyupgrade)
- Extract generation service (Phase 3): unified run_generation() replaces three
  duplicated closures, serial queue moved to services/task_queue.py
- Delete Makefile in favor of justfile; update all references
- Add Python lint/format/test commands to justfile (check-python, fix-python, test)
- Install ruff, pytest, pytest-asyncio as dev tools in setup-python
- Update REFACTOR_PLAN.md with Phase 3 and Phase 7 completion
2026-03-16 01:35:59 -07:00
Jamie Pine 439fedcbf2 update refactor plan with phase 1+2 progress 2026-03-16 01:10:59 -07:00
Jamie Pine 0813a3d9d6 refactor: remove dead code, deduplicate backends
Phase 1 - delete dead code:
- studio.py, migrate_add_instruct.py, utils/validation.py
- duplicate _profile_to_response in main.py, duplicate asyncio import
- pointless _get_profiles_dir/_get_generations_dir wrappers
- duplicate LANGUAGE_CODE_TO_NAME and WHISPER_HF_REPOS constants

Phase 2 - extract backends/base.py with shared utilities:
- is_model_cached() replaces 7 copy-pasted HF cache checks
- get_torch_device() replaces 5 device detection methods
- combine_voice_prompts() replaces 5 identical implementations
- model_load_progress() ctx manager replaces progress boilerplate in all backends
- patch_chatterbox_f32() replaces identical monkey-patches in both chatterbox backends

net -1078 lines across the backend
2026-03-16 01:10:02 -07:00
Jamie Pine 9514c6596c migrations 2026-03-16 00:54:13 -07:00
Jamie Pine 4e84415da7 refactor start 2026-03-16 00:52:23 -07:00
James Pine 34e17bd469 Fix LuxTTS + Chatterbox in prod: bundle espeak/perth data, fix multiprocessing
- collect-all piper_phonemize to bundle espeak-ng-data for LuxTTS phonemization
- Set ESPEAK_DATA_PATH in frozen builds so the C library finds bundled data
- collect-all perth to bundle pretrained watermark model for Chatterbox
- Add multiprocessing.freeze_support() to fix resource_tracker subprocess crash
2026-03-15 16:02:09 -07:00
James Pine aada13a5c9 Collect all inflect files for PyInstaller (fixes typeguard inspect.getsource) 2026-03-15 14:32:10 -07:00
James Pine de8558d197 Fix prod build: download progress, robust stderr, full tracebacks
- Force tqdm disable=False in TrackedTqdm so byte progress works in prod
  (huggingface_hub disables tqdm based on logger level, which prevents
  self.n from updating — our progress tracking needs the counter even
  though we don't render to terminal)
- Harden devnull redirect to test writability, not just None check
- Add full traceback logging to all backend error handlers
- Add chatterbox/luxtts/zipvoice hidden imports and metadata to spec
2026-03-15 14:23:11 -07:00
Jamie Pine 9d79ea367a Only use --noconsole on Windows, macOS/Linux need stdout for Tauri logs 2026-03-15 12:07:35 -07:00
Jamie Pine 04316f7adc Copy metadata for requests/transformers/huggingface-hub to fix PyInstaller metadata lookup 2026-03-15 11:35:05 -07:00
Jamie Pine 4e4361d350 Fix noconsole crash: redirect None stdout/stderr to devnull on Windows 2026-03-15 11:27:35 -07:00
Jamie Pine e9a249587c Collect all linacodec files for PyInstaller (fixes inspect.getsource in Vocos) 2026-03-15 11:06:13 -07:00
Jamie Pine 3dbf1c200e Revert "Bump version: 0.2.3 → 0.2.4"
This reverts commit 40fcb8d917.
2026-03-15 10:20:31 -07:00
Jamie Pine 40fcb8d917 Bump version: 0.2.3 → 0.2.4 2026-03-15 10:18:51 -07:00
Jamie Pine ad64d1c3d9 Collect all zipvoice files for PyInstaller (fixes source code error) 2026-03-15 10:18:40 -07:00
Jamie Pine 3d53c06c5b Bump version: 0.2.2 → 0.2.3 2026-03-15 10:08:56 -07:00
Jamie Pine e7f749f082 Add luxtts/zipvoice hidden imports to PyInstaller build 2026-03-15 09:13:59 -07:00
Jamie Pine d42e926e5c Bump version: 0.2.1 → 0.2.2 2026-03-15 09:02:10 -07:00
Jamie Pine 32768ea874 Add chatterbox hidden imports to PyInstaller build 2026-03-15 09:00:13 -07:00
Jamie Pine 655910457f Auto-update CUDA binary on app update: check version on startup, download if stale 2026-03-15 08:46:17 -07:00
James Pine a5269d23db Fix keep-server-running on macOS: ignore SIGHUP, watchdog grace period, build script fixes 2026-03-15 08:22:35 -07:00
Jamie Pine fc450e5024 Hide console window for server binary on Windows 2026-03-15 07:57:58 -07:00
Jamie Pine a99c2b572d Show download progress bar for CUDA backend download 2026-03-15 07:50:23 -07:00
Jamie Pine 96289e95f1 Bump version: 0.2.0 → 0.2.1 2026-03-15 06:36:38 -07:00
Jamie Pine 410413dc57 Watchdog respects keep-server-running setting via /watchdog/disable endpoint 2026-03-15 06:05:17 -07:00
Jamie Pine e239be5bbb Review fixes: CUDA restore in finally, os._exit on Windows, taskkill /T for process tree, build-server-cuda error handling, db-init path 2026-03-15 05:43:26 -07:00
Jamie Pine f1ba73a386 Address review: validate parent-pid, ensure binaries dir exists, fix Xcode typo 2026-03-15 04:09:49 -07:00
Jamie Pine f1963740b4 Fix server binary build, watchdog logging, pedalboard import, window close loop 2026-03-15 04:04:56 -07:00
Jamie Pine 4d6c976ad9 Windows support: CUDA detection, justfile cross-platform, clean server shutdown 2026-03-15 00:02:13 -07:00
Jamie Pine 310a4acb02 Add source version selection when applying effects, voices tab overhaul with inline inspector 2026-03-14 11:07:32 -07:00
Jamie Pine 899b90202b Add version control to track editor, restyle story list
- Story items can be pinned to a specific generation version via
  toolbar dropdown (shows when clip is selected and has >1 version)
- version_id column on story_items with migration, validated against
  the generation's versions before saving
- Split/duplicate preserve the source clip's pinned version
- Export and playback resolve version-specific audio paths
- Extracted _build_item_detail helper in stories.py (DRY cleanup)
- Story list restyled from rounded cards to flat rows with rounded
  hover/active states, gradient header fade, and dynamic bottom
  padding that accounts for track editor + generate box
2026-03-14 09:56:27 -07:00
Jamie Pine e8d54d52d3 Add favorites, effects badge on profiles, UI polish
- Add is_favorited column with toggle endpoint and star button on history
- Show sparkles icon on profile cards that have effects configured
- Gold ring on selected profile cards
- Smaller, gray action buttons with brighter hover
- Clamp player time to duration to prevent runaway playback
- Align profile card icon to top for wrapped names
- Flush bottom corners on history card when versions expanded
- Simplify .gitignore data/ rule
2026-03-14 09:10:56 -07:00
Jamie Pine 00c5b75ffb Regenerate as new version, UI polish, and bugfixes
- Add /generate/{id}/regenerate endpoint that creates a new take version
- Wire regenerate into history dropdown with SSE progress + autoplay
- Add normalize_audio to regenerate path
- Remove duplicate Regenerate menu item
- Show disabled ellipsis menu during generation instead of hiding it
- Fix sf.write format kwarg broken by asyncio.to_thread migration
- Rename clean version label to 'original', effects to 'version-N'
- Show effects chain names in version list instead of 'N fx'
- Include all versions in export package
- Clean up version panel padding
2026-03-14 08:34:58 -07:00
Jamie Pine 3d922ec846 Fix review findings: toggle logic, preset saving, version lookup, async audio ops
- Fix inverted effects toggle in FloatingGenerateBox
- Add Save button + API method for editing custom effect presets
- Return early on effects save failure in ProfileForm
- Fix no-op ternary in effectsStore
- Handle duplicate preset names with proper 400 response
- Use effects_chain is None instead of label for clean version lookup
- Move blocking audio ops to asyncio.to_thread in async endpoints
- Log warnings instead of silently swallowing parse errors
2026-03-14 07:47:06 -07:00
James Pine 638820c839 Add post-processing audio effects system
Adds a full effects pipeline powered by Spotify's pedalboard library,
enabling users to apply professional DSP effects (flanger, reverb, delay,
compressor, pitch shift, filters, gain) to generated audio.

Key features:
- Effects chain editor with drag-and-drop reordering (dnd-kit)
- Generation versions: clean copy always saved, processed versions created on top
- Built-in presets (Robotic, Radio, Echo Chamber, Deep Voice) + custom user presets
- Per-profile default effects chain (auto-applied to new generations)
- Per-generation effects override from the generation form
- Apply effects to existing generations from history (creates new version)
- Ephemeral preview endpoint for auditioning effects without persisting
- Dedicated Effects sidebar tab with preset management and live preview
- Version switcher in history cards with expandable panel
- Backward-compatible: existing generations backfilled as clean versions
2026-03-14 07:11:56 -07:00