# MOSS-TTS-Local-Transformer-v1.5 This folder contains the public remote-code implementation and realtime streaming examples for `OpenMOSS-Team/MOSS-TTS-Local-Transformer-v1.5`. MOSS-TTS-Local-Transformer-v1.5 uses the `MossTTSLocal` architecture with time-synchronous RVQ frame generation and `OpenMOSS-Team/MOSS-Audio-Tokenizer-v2` as the audio tokenizer for 48 kHz stereo audio encoding and decoding.

--- ## Model | Item | Value | |---|---| | **Checkpoint** | `OpenMOSS-Team/MOSS-TTS-Local-Transformer-v1.5` | | **Architecture** | `MossTTSLocal` | | **Audio tokenizer** | `OpenMOSS-Team/MOSS-Audio-Tokenizer-v2` | | **Audio format** | 48 kHz stereo | | **Backbone Model** | Initialized from **Qwen3-4B** | | **Depth Transformer** | 1 Transformer blocks (Hidden: 2560, FFN: 9728) | | **Frame Rate** | 12.5 Hz (1s ≈ 12.5 tokens/blocks) | | **Codebooks** | 12 RVQ layers (10-bit each) | | **Generation Mode** | Purely Autoregressive (AR) | ## Batch Inference ```python from pathlib import Path from tqdm import tqdm import importlib.util import torch import torchaudio from transformers import AutoModel, AutoProcessor # Disable the broken cuDNN SDPA backend on some CUDA/PyTorch combinations. torch.backends.cuda.enable_cudnn_sdp(False) # Keep these enabled as fallbacks. torch.backends.cuda.enable_flash_sdp(True) torch.backends.cuda.enable_mem_efficient_sdp(True) torch.backends.cuda.enable_math_sdp(True) pretrained_model_name_or_path = "OpenMOSS-Team/MOSS-TTS-Local-Transformer-v1.5" device = "cuda" if torch.cuda.is_available() else "cpu" dtype = torch.bfloat16 if device == "cuda" else torch.float32 def resolve_attn_implementation() -> str: # Prefer FlashAttention 2 when package + device conditions are met. if ( device == "cuda" and importlib.util.find_spec("flash_attn") is not None and dtype in {torch.float16, torch.bfloat16} ): major, _ = torch.cuda.get_device_capability() if major >= 8: return "flash_attention_2" # CUDA fallback: use PyTorch SDPA kernels. if device == "cuda": return "sdpa" # CPU fallback. return "eager" attn_implementation = resolve_attn_implementation() print(f"[INFO] Using attn_implementation={attn_implementation}") processor = AutoProcessor.from_pretrained( pretrained_model_name_or_path, trust_remote_code=True, ) processor.audio_tokenizer = processor.audio_tokenizer.to(device) text_zh = "亲爱的你,愿你的每一天都值得被记住,也值得被珍惜。" text_en = "We stand on the threshold of the AI era, where intelligence becomes an extension of human creativity." text_fr = "Bonjour, je voudrais essayer une voix francaise naturelle et stable." text_pause = "我今天学习了一首中国的古诗,它的名字是[pause 3.2s]静夜思!" # Use remote demo audio to avoid requiring local assets. ref_audio_zh = "https://speech-demo.oss-cn-shanghai.aliyuncs.com/moss_tts_demo/tts_readme_demo/reference_zh.wav" ref_audio_en = "https://speech-demo.oss-cn-shanghai.aliyuncs.com/moss_tts_demo/tts_readme_demo/reference_en.m4a" conversations = [ # Direct TTS. Language tags are recommended in v1.5 when the language is known. [processor.build_user_message(text=text_zh, language="Chinese")], [processor.build_user_message(text=text_en, language="English")], [processor.build_user_message(text=text_fr, language="French")], # Explicit pause control. Use [pause X.Ys], such as [pause 3.2s]. [processor.build_user_message(text=text_pause, language="Chinese")], # Voice cloning with a reference audio. [processor.build_user_message(text=text_zh, reference=[ref_audio_zh], language="Chinese")], [processor.build_user_message(text=text_en, reference=[ref_audio_en], language="English")], # Duration control. At 12.5 frames per second, 125 frames is about 10 seconds. [processor.build_user_message(text=text_en, tokens=125, language="English")], ] model = AutoModel.from_pretrained( pretrained_model_name_or_path, trust_remote_code=True, attn_implementation=attn_implementation, torch_dtype=dtype, ).to(device) model.eval() batch_size = 1 save_dir = Path("inference_root_moss_tts_local_v1_5") save_dir.mkdir(exist_ok=True, parents=True) sample_idx = 0 with torch.no_grad(): for start in tqdm(range(0, len(conversations), batch_size)): batch_conversations = conversations[start : start + batch_size] batch = processor(batch_conversations, mode="generation") input_ids = batch["input_ids"].to(device) attention_mask = batch["attention_mask"].to(device) outputs = model.generate( input_ids=input_ids, attention_mask=attention_mask, max_new_tokens=4096, do_sample=True, audio_temperature=1.7, audio_top_p=0.8, audio_top_k=25, audio_repetition_penalty=1.0, ) for message in processor.decode(outputs): if message is None: continue audio = message.audio_codes_list[0] out_path = save_dir / f"sample{sample_idx}.wav" sample_idx += 1 # MOSS-TTS Local v1.5 codec returns stereo audio as [channels, samples]. # Save the two-channel tensor directly. torchaudio.save(str(out_path), audio, processor.model_config.sampling_rate) ``` ## Realtime Streaming Decode Launch the realtime browser app. It uses FastAPI plus Web Audio playback so decoded PCM chunks can be played while generation is still running: ```bash MODEL_DIR=OpenMOSS-Team/MOSS-TTS-Local-Transformer-v1.5 \ CODEC_DIR=OpenMOSS-Team/MOSS-Audio-Tokenizer-v2 \ TTS_DEVICE=cuda:0 \ CODEC_DEVICE=cuda:1 \ CODEC_WEIGHT_DTYPE=fp32 \ bash moss_tts_local_v1.5/run_streaming_app.sh ``` The app defaults to `flash_attention_2`. If FlashAttention 2 is not available in the current environment, runtime loading falls back to `sdpa` on CUDA. The codec encoder/decoder weights default to `fp32`; pass `--codec-weight-dtype bf16` or set `CODEC_WEIGHT_DTYPE=bf16` to reduce memory. For Continuation and Continuation + Clone modes, provide the reference audio transcript in the separate Reference Audio Transcript field. The streaming demo defaults are: | Parameter | Default | |---|---:| | Audio Temperature | 1.7 | | Audio Top P | 0.8 | | Audio Top K | 25 | | Audio Repetition Penalty | 1.0 | | Codec Chunk Frames | 0 (auto, UI range 0-32) | | Initial Playback Delay | 0.08 s | Generated audio, token dumps, and metadata are written under `outputs/moss_tts_local_v1_5_streaming/` by default.