diff --git a/backend/go/crispasr/CMakeLists.txt b/backend/go/crispasr/CMakeLists.txt index c77a8ecad..5a8b5711b 100644 --- a/backend/go/crispasr/CMakeLists.txt +++ b/backend/go/crispasr/CMakeLists.txt @@ -17,7 +17,7 @@ target_link_libraries(gocrispasr PRIVATE crispasr-lib parakeet canary canary_ctc cohere granite_speech granite_nle voxtral voxtral4b qwen3_asr qwen3_tts orpheus chatterbox indextts - kokoro voxcpm2_tts m2m100 t5_translate wav2vec2-ggml vibevoice + kokoro voxcpm2_tts m2m100 t5_translate wav2vec2-ggml vibevoice f5-tts silero-lid pyannote-seg funasr paraformer sensevoice crisp_audio ggml) diff --git a/backend/go/crispasr/gocrispasr_test.go b/backend/go/crispasr/gocrispasr_test.go index 63ea47907..4c4563c47 100644 --- a/backend/go/crispasr/gocrispasr_test.go +++ b/backend/go/crispasr/gocrispasr_test.go @@ -189,5 +189,32 @@ var _ = Describe("CrispASR", func() { Expect(info.Size()).To(BeNumerically(">", 1024), "expected a non-trivial WAV, got %d bytes", info.Size()) }) + + It("synthesizes with F5-TTS voice cloning (reference WAV + transcript)", func() { + // F5-TTS has no baked speaker: it clones from a reference WAV and + // its transcript, supplied via the voice/voice_text options. The + // spec skips unless all three fixtures are provided. + model := os.Getenv("CRISPASR_F5_MODEL_PATH") + refWav := os.Getenv("CRISPASR_F5_REF_WAV") + refText := os.Getenv("CRISPASR_F5_REF_TEXT") + if model == "" || refWav == "" || refText == "" { + Skip("set CRISPASR_F5_MODEL_PATH, CRISPASR_F5_REF_WAV and CRISPASR_F5_REF_TEXT to run this spec") + } + ensureLibLoaded() + + w := &CrispASR{} + Expect(w.Load(&pb.ModelOptions{ + ModelFile: model, + Options: []string{"voice:" + refWav, "voice_text:" + refText}, + })).To(Succeed()) + + dst := filepath.Join(GinkgoT().TempDir(), "f5.wav") + Expect(w.TTS(&pb.TTSRequest{Text: "Hello from LocalAI running F5 text to speech.", Dst: dst})).To(Succeed()) + + info, err := os.Stat(dst) + Expect(err).ToNot(HaveOccurred(), "synthesized WAV should exist at %q", dst) + Expect(info.Size()).To(BeNumerically(">", 1024), + "expected a non-trivial WAV, got %d bytes", info.Size()) + }) }) }) diff --git a/gallery/index.yaml b/gallery/index.yaml index 1b15efdff..164a4f92d 100644 --- a/gallery/index.yaml +++ b/gallery/index.yaml @@ -36811,6 +36811,34 @@ - filename: snac-24khz.gguf uri: huggingface://cstr/snac-24khz-GGUF/snac-24khz.gguf sha256: b4b044631df62ececa86ab080516b3e619cd8f93caabd5f6758c7eae14981bd8 +- name: f5-tts-crispasr + url: github:mudler/LocalAI/gallery/virtual.yaml@master + urls: + - https://huggingface.co/SWivid/F5-TTS + - https://huggingface.co/cstr/f5-tts-GGUF + description: | + F5-TTS v1 Base (SWivid, MIT) text-to-speech synthesized through the CrispASR backend. A 22-layer DiT flow-matching model with a built-in Vocos vocoder in a single self-contained GGUF (no separate codec). Auto-detected by CrispASR and runs end-to-end on CPU, producing 24 kHz mono audio. + + F5-TTS is a voice-cloning model with no built-in speaker: you must supply a reference clip and its transcript. Add `voice:` and `voice_text:` to the model's `options` (paths resolve against the model directory) before synthesizing; without a reference the model cannot generate audio. + + Default GGUF size ~945 MB (f16). Quantization below f16 is not recommended for flow-matching models. Synthesis runs a 32-step ODE solver and is compute-heavy on CPU (expect long generation times without a GPU-enabled CrispASR build). + tags: + - crispasr + - tts + - text-to-speech + - gguf + - voice-cloning + overrides: + backend: crispasr + known_usecases: + - tts + name: f5-tts-crispasr + parameters: + model: f5-tts-v1-base-f16.gguf + files: + - filename: f5-tts-v1-base-f16.gguf + uri: huggingface://cstr/f5-tts-GGUF/f5-tts-v1-base-f16.gguf + sha256: fdd6ba8baa9e1224072cd0bea795f7962daf00e89b5d8c736fb06b3155c8d1f1 - name: piper-it_IT-riccardo-x_low-crispasr url: github:mudler/LocalAI/gallery/virtual.yaml@master urls: