模型端点配置化 - #4
Open
Nuyoahzhou wants to merge 1 commit into
Open
Conversation
|
|
10 tasks
Star-Lotus
pushed a commit
that referenced
this pull request
May 28, 2026
…erride for custom voices
Custom cloned voices have voice_ids that aren't in TTS_VOICE_REGISTRY, so
the existing _resolve_model_for_voice() fallback would dispatch wrong model
and produce wrong output. Wire explicit overrides through both backend
endpoints and TTSProcessor.
src/audio/tts.py:
- TTSProcessor.synthesize() gains model_override + family_override params
- _synthesize_cosyvoice() honors model_override
- _synthesize_qwen3() honors model_override
- Backward compatible: when overrides are None, falls back to registry lookup
src/apps/comic_gen/api.py:
- /voice/preview now looks up pipeline.find_custom_voice(voice_id) to
resolve target_model + family for custom voices, passes through as
overrides to synthesize()
- New POST /voice/clone {series_id, audio_url, label, target_model}
- Delegates to pipeline.create_voice_clone
- target_model defaults cosyvoice-v3.5-plus (supports instructions →
enables PR-3j emotion control on clones too)
- 404 if series not found, 500 on dashscope error
- New GET /series/{id}/custom_voices
- Returns full list (clones + designs) for the Voice picker's
我的复刻 / 我的设计 tabs to render
- New DELETE /series/{id}/custom_voices/{voice_id}
- Removes from list (does NOT call dashscope delete — 24h retention)
Smoke-tested: unknown voice_id falls through to self.model as expected
(registry lookup graceful). model_override path wires correctly through
both family branches.
Next: #3 frontend api.ts wrappers + #4 VoiceCloneModal sub-modal +
VoicePickerModal Tab 2 integration.
Star-Lotus
pushed a commit
that referenced
this pull request
May 28, 2026
Voice cloning now fully functional from Cast picker UI.
frontend/src/lib/api.ts:
- New CustomVoice type (mirrors backend models.py CustomVoice)
- cloneVoice({series_id, audio_url, label, target_model?}) → CustomVoice
- listCustomVoices(seriesId) → CustomVoice[]
- deleteCustomVoice(seriesId, voiceId) → {removed}
New frontend/src/components/modules/cast/VoiceCloneModal.tsx (~250 LOC):
- Per Q16.2 推荐 B: dedicated sub-modal opened from VoicePickerModal
'+ 上传新音频' button. Keeps picker focused on selection; creation
has its own UX (drop zone + label + submit)
- Phases: pick → uploading → cloning → done (with status banners) /
error (with retry path via cancel + reopen)
- Frontend pre-validation: MP3/WAV/M4A, ≤10MB; backend hard-rejects
otherwise (dashscope side enforces audio quality)
- Drop zone: drag-and-drop + click-to-pick; auto-suggests label from
filename (minus extension, ≤30 chars)
- Two-step flow: POST /upload → URL → POST /voice/clone {url, label}
- Block-close during in-flight phases to prevent orphaned uploads
VoicePickerModal extensions:
- New seriesId? prop (when null/missing, Tab 2/3 show "需要先关联到系列"
placeholder — orphan project handling per spec)
- Loads custom_voices on open via api.listCustomVoices(seriesId)
in parallel with /voices fetch (Promise.all)
- handlePreviewById extracted from handlePreview; works for both
VoiceMeta (system) and CustomVoice (clones) — unified preview path
- New CustomVoiceList sub-component: "+ 上传新音频" button at top +
grid of cards (label + origin tag + target_model + ▶ + 🗑) +
empty state when no clones yet
- Tab 2 (我的复刻) now renders CustomVoiceList when seriesId; else
NeedsSeriesPlaceholder
- Apply lookup unified: checks voices ∪ customVoices for selectedId,
resolves name from VoiceMeta.name or CustomVoice.label fallback
- handleCloneCreated: refreshes list + auto-selects new clone +
switches to clone tab so user sees their new voice
- handleDeleteCustom: confirms before delete, refreshes, unselects
if was selected
Cast.tsx: pass currentProject.series_id to VoicePickerModal.
i18n:
- voiceClone namespace (15 keys × 2 langs): title/dropHint/requirements/
labelLabel/labelPlaceholder/submit/cancel/done/uploading/cloning/
doneCloned/errorBadType/errorTooLarge
- voicePicker: cloneEmptyTitle (changed from "coming soon" to "no
cloned voices"), cloneEmptyBody, cloneCreateBtn, cloneNeedsSeries,
originClone, originDesign, confirmDelete
End-to-end working flow:
1. User hovers character card → clicks voice chip → picker opens
2. Switches to 我的复刻 tab → sees existing clones + "+ 上传新音频"
3. Click + → VoiceCloneModal opens → drop audio + label → submit
4. Wait ~10-30s (uploading + cloning banners) → success → close
5. Picker refreshes → new clone selected + visible → preview ▶ to verify
6. Click 应用 → character.voice_id bound to the new clone
PR-3h COMPLETE. Next: PR-3i (voice design with character.description
one-click → voice_prompt) reuses same sub-modal pattern.
Star-Lotus
pushed a commit
that referenced
this pull request
May 28, 2026
- VoiceDesignModal: write voice_prompt → preview → tweak → accept loop
- ✨ 由角色描述生成 button calls /voice/design/translate when character.description present
- VoicePickerModal Tab 3 now mirrors Tab 2: list + delete + auto-select on create
- i18n keys: voiceDesign.* + voicePicker.{designCreateBtn,designNeedsSeries}
Zwens
pushed a commit
to Zwens/prismreel
that referenced
this pull request
Jul 28, 2026
…ort what pass 2 did Three findings, all in RenderEngine.finalize, all invisible because finalize itself had zero tests. tests/test_render_finalize.py now calls it. 1) No audio stream (finding alibaba#2). The generation pipeline's DEFAULT is Silent Mode, so the concat output routinely has no audio stream, but build_audio_filter always referenced [0:a]. ffmpeg aborted with "matches no streams" and pass 2 returned None — losing BGM, loudnorm AND burned subtitles at once, i.e. exactly the film this phase set out to replace, while merge_videos still reported success. Adds media_probe.has_audio_stream (False on probe failure — the safe response to "unknown" is the same as to "no audio"), a dialogue_label parameter on build_audio_filter, and a synthetic anullsrc input in finalize. The synthetic input goes last so BGM keeps index 1 and audio_mixer's documented input convention is unchanged. 2) Apostrophe / comma / bracket in the path (finding alibaba#4). The review proposed escaping "'" as \'. Measured against ffmpeg 8.1.1 that does not work, and neither does '\'' nor \': a literal apostrophe is not expressible in an ffmpeg filter argument at all — libass receives the path with the quote deleted. So the .ass path no longer enters the filter string as an absolute path: pass 2 runs with cwd set to the .ass directory and passes only a sanitised basename. The directory is the user's install location and we do not get to choose its spelling. escape_filter_path still gains the missing ' , [ ] escapes — it is a public helper and should be correct — but it is no longer load-bearing for the directory part. Measured: , and [ ] already survived inside the surrounding quotes; only ' actually broke, and it broke totally. 3) Silent subtitle drops (finding alibaba#3). finalize returned Optional[str], so four independent paths could discard the subtitle track with only a log line: disabled, a zero-duration segment, no dialogue, or any ffmpeg failure. It now returns FinalizeResult(path, subtitles_burned, bgm_applied, loudnorm_applied, skip_reason, ass_path) and merge_videos persists it to the new Script.last_render_report. A return value rather than an instance attribute, because RenderEngine is constructed and discarded inline and an attribute would invite stale state. Additionally, a subtitle burn failure now retries pass 2 once without the burn, so a subtitle problem no longer takes BGM and loudness normalisation down with it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
将代码中的硬编码的api model_name 等抽到env 中 以便后续方便的部署安装。以及使用海外端点。