Skip to content

feat: .voicebox bundle — portable voice profile export with full metadata - #938

Open
andreolf wants to merge 1 commit into
jamiepine:mainfrom
andreolf:feat/voicebox-bundle-format
Open

feat: .voicebox bundle — portable voice profile export with full metadata#938
andreolf wants to merge 1 commit into
jamiepine:mainfrom
andreolf:feat/voicebox-bundle-format

Conversation

@andreolf

@andreolf andreolf commented Jul 21, 2026

Copy link
Copy Markdown

Problem

Voicebox's export has always been crippled compared to cloud TTS tools: the downloaded archive only contained name, description, and language. Every other piece of configuration — voice_type, preset_engine, preset_voice_id, design_prompt, default_engine, personality, and the effects_chain — was silently discarded on export and lost on import. Practically speaking this made voice-profile portability useless: cloned voices could not be moved to a new machine, shared with teammates, or restored from a backup without manually re-entering all settings.

Solution

Introduces the .voicebox bundle format (a ZIP archive under the hood, renamed to signal intent). The manifest is bumped to version 1.1 and now serialises the full profile metadata.

Changes

backend/services/export_import.py

  • export_profile_to_zip() writes manifest v1.1, adding voice_type, preset_engine, preset_voice_id, design_prompt, default_engine, personality, and effects_chain (deserialized from JSON before embedding).
  • import_profile_from_zip() reads every new field and passes them into VoiceProfileCreate; after the profile is created, effects_chain is written back directly (it is not exposed by VoiceProfileCreate) with a db commit + refresh.
  • Version "1.0" bundles still import cleanly — missing fields default to None.

backend/routes/profiles.py

  • Export filename changed from profile-<name>.voicebox.zipprofile-<name>.voicebox.
  • Content-Type changed from application/zipapplication/octet-stream so browsers don't handle the file as a generic ZIP.

app/src/lib/hooks/useProfiles.ts

  • useExportProfile saves with the .voicebox extension and uses the 'Voicebox Profile / voicebox' file filter in the native save dialog.

app/src/components/MainEditor/MainEditor.tsx

  • File input accept attribute updated to .voicebox,.voicebox.zip (backward compat with bundles exported by older versions).
  • Validation guard updated to accept both extensions.

Backward compatibility

Bundle version Export Import
1.0 (old .voicebox.zip) ✅ imports, extra fields default to None
1.1 (new .voicebox) ✅ full metadata ✅ full round-trip

Test plan

  • Export a cloned profile (with samples, personality prompt, effects chain set) → file downloads as profile-<name>.voicebox
  • Import the .voicebox file on a fresh install → all fields restored: name, description, language, voice_type, personality, effects_chain
  • Export a preset profile (kokoro / qwen_custom_voice) → preset_engine and preset_voice_id round-trip correctly
  • Import an old .voicebox.zip bundle → still works, no crash, missing fields default gracefully
  • Export a profile with no effects chain → effects_chain: null in manifest, no error on import

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Voice profiles can now be exported and imported using .voicebox files.
    • Profile exports retain additional settings, including voice type, engine selections, personality, design prompts, and effects chains.
    • Updated export metadata reflects the new .voicebox format.
  • Bug Fixes

    • Import file selection now recognizes both .voicebox and .voicebox.zip files.
    • Imported profiles more accurately restore their saved configuration.

Upgrades the export/import format from a minimal ZIP (name, description,
language only) to a richer .voicebox bundle (a ZIP under the hood) that
carries ALL profile metadata so cloned voices can be moved between
machines or shared with other users without losing any configuration.

Backend — backend/services/export_import.py:
- Bump manifest to version "1.1"
- Export now includes voice_type, preset_engine, preset_voice_id,
  design_prompt, default_engine, personality, and effects_chain
- Import reads all new fields; version "1.0" bundles still import
  cleanly (missing fields default to None for backward compat)
- After profile creation the effects_chain is written back directly
  because VoiceProfileCreate does not expose that field

Route — backend/routes/profiles.py:
- Change download filename from .voicebox.zip to .voicebox
- Change Content-Type to application/octet-stream so browsers don't
  try to treat the file as a generic ZIP

Frontend:
- useExportProfile: saves as .voicebox, filter label "Voicebox Profile"
  with extension 'voicebox'
- MainEditor file input: accept=".voicebox,.voicebox.zip" and the
  validation guard accepts both extensions for backward compat with
  bundles exported by older versions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ef60802a-7215-44f7-946b-ce1d7a0cc0bd

📥 Commits

Reviewing files that changed from the base of the PR and between 52f8d8d and 08dc8e1.

📒 Files selected for processing (4)
  • app/src/components/MainEditor/MainEditor.tsx
  • app/src/lib/hooks/useProfiles.ts
  • backend/routes/profiles.py
  • backend/services/export_import.py

📝 Walkthrough

Walkthrough

Voice profile exports now use .voicebox filenames, advertise an octet-stream response, and include additional profile data in manifest version 1.1. Imports restore the expanded fields and effects chains. The editor accepts both .voicebox and .voicebox.zip files.

Changes

Voice profile archive flow

Layer / File(s) Summary
Archive schema and profile restoration
backend/services/export_import.py
Manifest version 1.1 includes additional profile fields, which are restored during import along with effects_chain.
Voicebox export naming and response metadata
backend/routes/profiles.py, app/src/lib/hooks/useProfiles.ts
Backend downloads and client saves use .voicebox filenames and corresponding response or file metadata.
Voicebox file selection and validation
app/src/components/MainEditor/MainEditor.tsx
The editor accepts both .voicebox and .voicebox.zip files for selection and validation.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant MainEditor
  participant ProfilesRoute
  participant ExportImportService
  participant Database
  MainEditor->>ProfilesRoute: request profile export
  ProfilesRoute->>ExportImportService: generate voice profile archive
  ExportImportService->>Database: read profile fields and effects_chain
  Database-->>ExportImportService: profile data
  ExportImportService-->>ProfilesRoute: manifest version 1.1 archive
  ProfilesRoute-->>MainEditor: .voicebox download response
Loading

Suggested reviewers: jamiepine

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the new .voicebox portable export bundle and its full metadata support.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@jamiepine

Copy link
Copy Markdown
Owner

Hell yeah I love this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants