* feat(media): add SenseAudio TTS provider
Add SenseAudio (https://docs.senseaudio.cn) as a new TTS provider
alongside ElevenLabs / MiniMax / FishAudio / Volcengine. Surfaced as
the `senseaudio-tts` catalogue id, mapped on the wire to
`senseaudio-tts-1.5-260319` — SenseAudio's flagship model with
emotion / 多音字 / 公式朗读 / clone / text-generated voice support.
Scope here is HTTP non-streaming (POST /v1/t2a_v2 with stream=false)
only; SSE and WebSocket transports are intentionally out of scope.
- Mirror provider + model entries in apps/daemon and apps/web
registries (catalogue drift check stays green).
- ENV_KEYS gets `OD_SENSEAUDIO_API_KEY` / `SENSEAUDIO_API_KEY` so the
alias scheme matches every other integrated provider.
- `renderSenseAudioTTS` in media.ts mirrors renderMinimaxTTS: Bearer
auth, voice_setting / audio_setting body, hex-decoded audio under
`data.audio`, base_resp envelope split from HTTP-level failures.
- NewProjectPanel's audio supportedProviders allowlist now includes
`senseaudio` so the picker actually surfaces the new entry.
- Audio shape (mp3 / 32kHz / 128kbps / stereo) and default voice
(`female_0033_b`) hard-coded for parity with the other TTS paths;
MediaContext is unchanged.
- New apps/daemon/tests/media-senseaudio.test.ts (8 specs) covers
defaults, custom voice, default base URL fall-back, env-key path,
missing-key error, base_resp failures, missing audio, and HTTP
non-2xx — patterned on media-elevenlabs.test.ts.
* docs(media): drop Chinese from SenseAudio provider comment
Translate the model-capabilities line in the SenseAudio block comment
(media.ts) into English. Keeping the source comments in a single
language matches the rest of the daemon and avoids reviewer churn over
mixed-locale prose.
* fix(web): unblock openai and volcengine speech models in audio picker
Per review on #1633, supportedModels()'s audio allowlist in
NewProjectPanel was still filtering out gpt-4o-mini-tts (openai) and
doubao-tts (volcengine) even though both are marked `integrated: true`
in the shared media-models catalogue. Add the two ids so the picker
matches the registry and the PR body's "alongside doubao-tts" claim
holds true.
* style(media): normalize speech hints to bare provider names
Strip the trailing descriptions on the speech catalogue hints so every
entry shows just the provider name (matching FishAudio / ElevenLabs /
SenseAudio): `gpt-4o-mini-tts` → "OpenAI", `minimax-tts` → "MiniMax",
`doubao-tts` → "Volcengine". Also move `gpt-4o-mini-tts` to the end of
the list so the OpenAI entry sits after the upstream-focused providers,
matching the recent picker grouping discussion on #1633.
Mirrored in both apps/daemon/src/media-models.ts and apps/web/src/media/
models.ts; catalogue drift check + daemon (1848) + web (1150) suites all
green.