Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1481,6 +1481,21 @@ audiocpp_add_model(soprano_tts
engine::community_models::soprano_tts::make_soprano_tts_loader
)

audiocpp_add_model(mira_tts
SOURCES
src/community_models/mira_tts/assets.cpp
src/community_models/mira_tts/decoder.cpp
src/community_models/mira_tts/generator.cpp
src/community_models/mira_tts/processor.cpp
src/community_models/mira_tts/prompt.cpp
src/community_models/mira_tts/session.cpp
src/community_models/mira_tts/speaker_encoder.cpp
INCLUDES
engine/community_models/mira_tts/session.h
LOADERS
engine::community_models::mira_tts::make_mira_tts_loader
)


audiocpp_add_model(midashenglm_gen
SOURCES
Expand Down Expand Up @@ -1910,6 +1925,7 @@ if (ENGINE_BUILD_WARMBENCH)
add_engine_warmbench(irodori_tts_warm_bench tests/irodori_tts/irodori_tts_warm_bench.cpp)
add_engine_warmbench(marblenet_vad_warm_bench tests/marblenet_vad/marblenet_vad_warm_bench.cpp)
add_engine_warmbench(miocodec_warm_bench tests/miocodec/miocodec_warm_bench.cpp)
add_engine_warmbench(mira_tts_warm_bench tests/mira_tts/mira_tts_warm_bench.cpp)
add_engine_warmbench(muscriptor_warm_bench tests/muscriptor/muscriptor_warm_bench.cpp)
add_engine_warmbench(moss_tts_nano_warm_bench tests/moss_tts_nano/moss_tts_nano_warm_bench.cpp)
add_engine_warmbench(moss_tts_local_warm_bench tests/moss_tts_local/moss_tts_local_warm_bench.cpp)
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ Community model ports live under `community_models` to make the ownership bounda
| **kroko_asr** | ASR | de, en, es, fr, it, he, nl, pt, sv, tr | Safetensors, GGUF Q8 | Mirek [@mirek190](https://github.com/mirek190) | [Kroko Community ASR](docs/community_models/kroko_asr.md) native offline/streaming Zipformer2/RNN-T transcription with word timestamps |
| **minimax_h3** | Video, Music, TTS/Dialogue | auto | GGUF Q4/INT8 | [@0xShug0](https://github.com/0xShug0) | [MiniMax-H3](docs/community_models/minimax_h3.md) text-to-audio/video generation with Q4_K and optional INT8 ConvRot DiT |
| **minimax_music3** | Music | auto | GGUF Q4/Q8 | [@0xShug0](https://github.com/0xShug0), [@JoeMattie](https://github.com/JoeMattie) | [MiniMax Music 3](docs/community_models/minimax_music3.md) text-to-music generation with lyrics conditioning |
| **mira_tts** | TTS, Clone | en | Local conversion | Mirek [@mirek190](https://github.com/mirek190) | [MiraTTS](docs/community_models/mira_tts.md) experimental native Qwen2 + ECAPA/Perceiver zero-shot voice cloning with progressive segment streaming (CC-BY-NC-SA-4.0 weights) |
| **mms_forced_aligner** | Align | nl (nld), en (eng); pre-romanized Latin | Safetensors, GGUF 16/Q8 | Community | [MMS-300M-1130 Forced Aligner](docs/community_models/mms_forced_aligner.md) word-timestamp alignment from a wav2vec2 CTC checkpoint (safetensors or local GGUF) |
| **moss_tts_local** | TTS, Clone, Ctrl | auto, optional language hint | GGUF | [@justinjohn0306](https://github.com/justinjohn0306) | MOSS-TTS-Local Transformer v1.5 support |
| **moss_voicegen** | Voice Design | en, zh | GGUF | Joost [@jrohde](https://github.com/jrohde) | [MOSS-VoiceGenerator](docs/community_models/moss_voicegen.md) speech in a voice designed from a written instruction |
Expand Down
78 changes: 78 additions & 0 deletions docs/community_models/mira_tts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# MiraTTS

MiraTTS is an experimental community port of
[ysharma3501/MiraTTS](https://github.com/ysharma3501/MiraTTS), a zero-shot
voice-cloning text-to-speech model. The native path includes the Qwen2 speech
token generator, ECAPA-TDNN plus Perceiver reference encoder, finite-scalar
speaker tokenizer, conditional acoustic processor, and DAC waveform decoder.

## Model and license

The upstream checkpoint is
[YatharthS/MiraTTS](https://huggingface.co/YatharthS/MiraTTS). Its model card
declares `CC-BY-NC-SA-4.0`; this is a non-commercial, attribution, share-alike
license. Review that license before downloading or redistributing converted
weights. audio.cpp does not redistribute the checkpoint.

No ready-to-run GGUF package is published yet, so MiraTTS intentionally has no
entry in the built-in download catalog. Convert a locally obtained upstream
checkpoint with:

```bash
python tools/community_models/convert_mira_tts.py /path/to/MiraTTS /path/to/mira-native
audiocpp_gguf \
--input language_model=/path/to/mira-native/language_model.safetensors \
--input speaker_encoder=/path/to/mira-native/speaker_encoder.safetensors \
--input processor=/path/to/mira-native/processor.safetensors \
--input decoder=/path/to/mira-native/decoder.safetensors \
--input upsampler=/path/to/mira-native/upsampler.safetensors \
--output /path/to/mira-native/mira-tts.gguf --type bf16 \
--family mira_tts --root /path/to/mira-native
```

Use BF16 for the first parity-oriented conversion. Converting the natively
BF16 Qwen backbone to F16 can overflow and produce non-finite logits.

The converter also imports the official FastBiCodec and FlashSR component
checkpoints referenced by the upstream repository. Use `--help` to see its
component path overrides.

## Run

MiraTTS requires reference audio. The CLI voice-cloning request accepts the
converted model directory, target text, and a short clean reference WAV through
the normal audio.cpp TTS/clone arguments. Sampling defaults reproduce upstream:
temperature `0.8`, top-k `50`, top-p `0.95`, min-p `0.05`, and repetition
penalty `1.2`.

The upstream pipeline decodes at 16 kHz and applies its learned FlashSR
upsampler. The native runtime executes both stages and returns 48 kHz audio.

MiraTTS also exposes a streaming session. It splits long input at natural text
boundaries, reuses one encoded speaker identity for the whole request, and emits
each completed 48 kHz segment immediately. `text_chunk_size` controls the
maximum segment size (160 codepoints by default), while `text_chunk_mode`
selects the framework chunker. This is segment-level progressive synthesis;
the acoustic processor, DAC, and FlashSR still decode each segment as a unit.

The session caches one encoded reference voice by default, so repeated requests
with the same audio do not rerun the speaker encoder. Increase the bounded cache
with `--session-option reference_cache_slots=<n>`, or set it to `0` to disable
reference reuse.

## Validation status

- Official checkpoint conversion: validated.
- Native CUDA build: validated.
- Native CUDA smoke synthesis through all converted model components: validated.
- Segment-level streaming synthesis: validated through the native streaming
session and `/v1/audio/speech/live` route.
- Deterministic upstream comparison with identical speech/context tokens:
validated (48 kHz waveform correlation 0.99996, SNR 41.1 dB).
- End-to-end generation comparison: validated through matching tokenization,
identical 32-token speaker codes, and the first six greedy LM tokens. Later
autoregressive tokens can diverge between LMDeploy, Transformers, and the
native backend because of backend floating-point differences.

Until end-to-end measurements are published, the family remains experimental
and is not advertised as an installable WebUI package.
1 change: 1 addition & 0 deletions docs/community_models/models.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Practical expectations:
| **mms_forced_aligner** | Align | nl (nld), en (eng); pre-romanized Latin | Community | [MMS-300M-1130 Forced Aligner](mms_forced_aligner.md) word-timestamp alignment from a wav2vec2 CTC checkpoint (safetensors or local GGUF) |
| **minimax_h3** | Video, Music, TTS/Dialogue | auto | [@0xShug0](https://github.com/0xShug0) | [MiniMax-H3](minimax_h3.md) text-to-audio/video generation with Q4_K and optional INT8 ConvRot DiT |
| **minimax_music3** | Music | auto | [@0xShug0](https://github.com/0xShug0) | [MiniMax Music 3](minimax_music3.md) text-to-music generation with lyrics conditioning |
| **mira_tts** | TTS, voice cloning | en | Mirek [@mirek190](https://github.com/mirek190) | [MiraTTS](mira_tts.md) experimental native Qwen2 + ECAPA/Perceiver zero-shot cloning; local conversion only (CC-BY-NC-SA-4.0 weights) |
| **moss_tts_local** | TTS, voice cloning | auto, optional language hint | [@justinjohn0306](https://github.com/justinjohn0306) | [MOSS-TTS-Local Transformer v1.5](../models/moss_tts.md) support in the core model tree |
| **outetts** | TTS, voice cloning | en, ar, zh, nl, fr, de, it, ja, ko, lt, ru, es, pt, be, bn, ka, hu, lv, fa, pl, sw, ta, uk | Mirek [@mirek190](https://github.com/mirek190) | [Llama-OuteTTS-1.0-1B](outetts.md) TTS and voice cloning support |
| **voxcpm1** | TTS, voice cloning | zh, en, ja, ko | Community | [VoxCPM1](voxcpm1.md) tokenizer-free 0.5B TTS with 16 kHz output, streaming, and continuation-mode voice cloning |
Expand Down
5 changes: 5 additions & 0 deletions docs/maintainers/model_specs.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,11 @@ packages come from the same repo, put the shared source in
`package_defaults.download` and keep package-level `download` only for
overrides.

Experimental ports may use an empty `packages` array while conversion and
runtime validation are still local-only. In that case `ui.recommended_package`
is omitted, so model managers do not advertise a download that cannot yet be
loaded. Community and supported families must publish at least one package.

```json
{
"package_defaults": {
Expand Down
56 changes: 56 additions & 0 deletions include/engine/community_models/mira_tts/assets.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#pragma once

#include "engine/framework/assets/resource_bundle.h"
#include "engine/framework/assets/tensor_source.h"

#include <cstdint>
#include <filesystem>
#include <memory>

namespace engine::community_models::mira_tts {

struct MiraTTSConfig {
int64_t hidden_size = 896;
int64_t intermediate_size = 4864;
int64_t layers = 24;
int64_t attention_heads = 14;
int64_t kv_heads = 2;
int64_t head_dim = 64;
int64_t vocab_size = 166000;
int64_t max_position_embeddings = 32768;
float rms_norm_eps = 1.0e-6F;
float rope_theta = 1.0e6F;
int32_t bos_token_id = 151643;
int32_t eos_token_id = 151645;
int32_t speech_token_start = 155761;
int32_t speech_token_end = 163952;
int32_t prompt_speech_start = 165151;
int32_t sample_rate = 16000;
int32_t output_sample_rate = 48000;
};

struct MiraTTSAssets {
assets::ResourceBundle resources;
MiraTTSConfig config;
std::shared_ptr<const assets::TensorSource> language_model_weights;
std::shared_ptr<const assets::TensorSource> speaker_encoder_weights;
std::shared_ptr<const assets::TensorSource> processor_weights;
std::shared_ptr<const assets::TensorSource> decoder_weights;
std::shared_ptr<const assets::TensorSource> upsampler_weights;
};

struct MiraGenerationOptions {
int64_t max_new_tokens = 1024;
int64_t top_k = 50;
float top_p = 0.95F;
float min_p = 0.05F;
float temperature = 0.8F;
float repetition_penalty = 1.2F;
uint64_t seed = 0;
bool has_seed = false;
};

std::shared_ptr<const MiraTTSAssets> load_mira_tts_assets(
const std::filesystem::path & model_path);

} // namespace engine::community_models::mira_tts
33 changes: 33 additions & 0 deletions include/engine/community_models/mira_tts/decoder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#pragma once

#include "engine/community_models/mira_tts/assets.h"
#include "engine/framework/core/execution_context.h"
#include "engine/framework/runtime/session.h"

#include <cstddef>
#include <cstdint>
#include <memory>
#include <vector>

namespace engine::community_models::mira_tts {

class MiraDecoder final {
public:
MiraDecoder(
const MiraTTSAssets & assets,
core::ExecutionContext & execution,
size_t weight_context_bytes,
size_t graph_context_bytes,
assets::TensorStorageType storage_type);
~MiraDecoder();

runtime::AudioBuffer decode(
const std::vector<float> & latents,
int64_t frames);

private:
struct Impl;
std::unique_ptr<Impl> impl_;
};

} // namespace engine::community_models::mira_tts
34 changes: 34 additions & 0 deletions include/engine/community_models/mira_tts/generator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#pragma once

#include "engine/community_models/mira_tts/assets.h"
#include "engine/framework/core/execution_context.h"

#include <cstddef>
#include <cstdint>
#include <memory>
#include <vector>

namespace engine::community_models::mira_tts {

class MiraGenerator final {
public:
MiraGenerator(
const MiraTTSAssets & assets,
core::ExecutionContext & execution,
size_t prefill_graph_arena_bytes,
size_t decode_graph_arena_bytes,
size_t weight_context_bytes,
assets::TensorStorageType weight_storage_type);
~MiraGenerator();

std::vector<int32_t> generate(
const std::vector<int32_t> & prompt_ids,
const MiraGenerationOptions & options);
void release_runtime_graphs();

private:
struct Impl;
std::unique_ptr<Impl> impl_;
};

} // namespace engine::community_models::mira_tts
33 changes: 33 additions & 0 deletions include/engine/community_models/mira_tts/processor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#pragma once

#include "engine/community_models/mira_tts/assets.h"
#include "engine/framework/core/execution_context.h"

#include <cstddef>
#include <cstdint>
#include <memory>
#include <vector>

namespace engine::community_models::mira_tts {

class MiraAcousticProcessor final {
public:
MiraAcousticProcessor(
const MiraTTSAssets & assets,
core::ExecutionContext & execution,
size_t weight_context_bytes,
size_t graph_context_bytes,
assets::TensorStorageType linear_storage_type,
assets::TensorStorageType conv_storage_type);
~MiraAcousticProcessor();

std::vector<float> process(
const std::vector<int32_t> & speech_codes,
const std::vector<int32_t> & context_codes);

private:
struct Impl;
std::unique_ptr<Impl> impl_;
};

} // namespace engine::community_models::mira_tts
26 changes: 26 additions & 0 deletions include/engine/community_models/mira_tts/prompt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once

#include "engine/community_models/mira_tts/assets.h"

#include <cstdint>
#include <memory>
#include <string>
#include <vector>

namespace engine::community_models::mira_tts {

class MiraPromptBuilder final {
public:
explicit MiraPromptBuilder(std::shared_ptr<const MiraTTSAssets> assets);
~MiraPromptBuilder();

std::vector<int32_t> build(
const std::string & text,
const std::vector<int32_t> & context_codes) const;

private:
struct Impl;
std::unique_ptr<Impl> impl_;
};

} // namespace engine::community_models::mira_tts
Loading
Loading