Skip to content

Add configurable mascot voices with ElevenLabs voice IDs #1762

@senamakel

Description

@senamakel

Summary

Let users customize the mascot's voice by selecting or pasting an ElevenLabs voice_id, including support for female voices.

OpenHuman already threads a mascot voice ID through the ElevenLabs TTS path, but it is currently effectively a build-time or config-time default. Users should be able to choose a voice that better matches the mascot or their preference without changing code or rebuilding the app.

Problem

The mascot voice is part of the product experience. Right now, the available voice is too static for users who want a different tone, including female-sounding voices, and there is no user-facing way to swap voices per install.

That creates a poor fit for different audiences and makes experimentation awkward. It also forces voice choices into env vars or hidden config instead of a visible preference that can be tested, persisted, and supported.

Solution (optional)

Add a voice preference UI for the mascot that lets the user:

  • pick from a curated set of ElevenLabs voices
  • paste a custom voice_id
  • preview the selected voice before saving
  • persist the choice across restarts
  • reset to the default mascot voice

Suggested scope:

  • app settings UI for voice selection
  • config persistence for the selected voice_id
  • validation for malformed or empty voice IDs
  • TTS path continues to use the chosen voice without changing other reply behavior
  • optional preview / test playback action so users can hear the selected voice before applying it

Security / product constraints:

  • Do not expose API keys or other sensitive ElevenLabs credentials in the UI.
  • Only store the voice ID, not the secret key.
  • Keep the fallback behavior if the selected voice is unavailable.
  • Keep the mascot default voice as the reset option.

Acceptance criteria

  • Voice can be changed in the UI — Users can select a different mascot voice without editing env vars.
  • Female voices supported — The picker includes at least one female voice option or allows pasting a known female voice_id.
  • Choice persists — The selected voice survives app restart.
  • Invalid IDs are handled — Bad or empty voice IDs are rejected or fall back safely.
  • Preview works — Users can play a short sample before committing a voice choice.
  • Fallback remains safe — If the chosen voice fails, the app falls back cleanly to default speech behavior.
  • Regression coverage added — Unit and/or E2E tests cover selection, persistence, and fallback behavior.
  • Diff coverage ≥ 80% — the implementing PR meets the changed-lines coverage gate (Vitest + cargo-llvm-cov, enforced by .github/workflows/coverage.yml).

Related

  • Mascot TTS path already uses MASCOT_VOICE_ID in app/src/utils/config.ts
  • Mascot speech synthesis path in app/src/features/human/voice/ttsClient.ts

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status
    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions