lenML/ChatTTS-Forge
301
1import logging2 3from fastapi import HTTPException, Query, Request4from fastapi.responses import StreamingResponse5from pydantic import BaseModel6 7from modules.api.Api import APIManager8from modules.api.impl.handler.TTSHandler import TTSHandler9from modules.api.impl.model.audio_model import AdjustConfig, AudioFormat10from modules.api.impl.model.chattts_model import ChatTTSConfig, InferConfig11from modules.api.impl.model.enhancer_model import EnhancerConfig12from modules.speaker import speaker_mgr13 14logger = logging.getLogger(__name__)15 16 17class XTTS_V2_Settings:18 def __init__(self):19 self.stream_chunk_size = 10020 self.temperature = 0.321 self.speed = 122 23 # TODO: 这两个参数现在用不着...但是其实gpt是可以用的可以考虑增加24 self.length_penalty = 0.525 self.repetition_penalty = 1.026 27 self.top_p = 0.728 self.top_k = 2029 self.enable_text_splitting = True30 31 # 下面是额外配置 xtts_v2 中不包含的,但是本系统需要的32 self.batch_size = 433 self.eos = "[uv_break]"34 self.infer_seed = 4235 self.use_decoder = True36 self.prompt1 = ""37 self.prompt2 = ""38 self.prefix = ""39 self.spliter_threshold = 10040 self.style = ""41 42 43class TTSSettingsRequest(BaseModel):44 # 这个 stream_chunk 现在当作 spliter_threshold 用45 stream_chunk_size: int46 temperature: float47 speed: float48 length_penalty: float49 repetition_penalty: float50 top_p: float51 top_k: int52 enable_text_splitting: bool53 54 batch_size: int = None55 eos: str = None56 infer_seed: int = None57 use_decoder: bool = None58 prompt1: str = None59 prompt2: str = None60 prefix: str = None61 spliter_threshold: int = None62 style: str = None63 64 65class SynthesisRequest(BaseModel):66 text: str67 speaker_wav: str68 language: str69 70 71def setup(app: APIManager):72 XTTSV2 = XTTS_V2_Settings()73 74 @app.get("/v1/xtts_v2/speakers")75 async def speakers():76 spks = speaker_mgr.list_speakers()77 return [78 {79 "name": spk.name,80 "voice_id": spk.id,81 # TODO: 也许可以放一个 "/v1/tts" 接口地址在这里82 "preview_url": "",83 }84 for spk in spks85 ]86 87 @app.post("/v1/xtts_v2/tts_to_audio", response_class=StreamingResponse)88 async def tts_to_audio(request: SynthesisRequest):89 text = request.text90 # speaker_wav 就是 speaker id 。。。91 voice_id = request.speaker_wav92 language = request.language93 94 spk = speaker_mgr.get_speaker_by_id(voice_id) or speaker_mgr.get_speaker(95 voice_id96 )97 if spk is None:98 raise HTTPException(status_code=400, detail="Invalid speaker id")99 100 tts_config = ChatTTSConfig(101 style=XTTSV2.style,102 temperature=XTTSV2.temperature,103 top_k=XTTSV2.top_k,104 top_p=XTTSV2.top_p,105 prefix=XTTSV2.prefix,106 prompt1=XTTSV2.prompt1,107 prompt2=XTTSV2.prompt2,108 )109 infer_config = InferConfig(110 batch_size=XTTSV2.batch_size,111 spliter_threshold=XTTSV2.spliter_threshold,112 eos=XTTSV2.eos,113 seed=XTTSV2.infer_seed,114 )115 adjust_config = AdjustConfig(116 speed_rate=XTTSV2.speed,117 )118 # TODO: support enhancer119 enhancer_config = EnhancerConfig(120 # enabled=params.enhance or params.denoise or False,121 # lambd=0.9 if params.denoise else 0.1,122 )123 124 handler = TTSHandler(125 text_content=text,126 spk=spk,127 tts_config=tts_config,128 infer_config=infer_config,129 adjust_config=adjust_config,130 enhancer_config=enhancer_config,131 )132 133 buffer = handler.enqueue_to_buffer(AudioFormat.mp3)134 135 return StreamingResponse(buffer, media_type="audio/mpeg")136 137 @app.get("/v1/xtts_v2/tts_stream")138 async def tts_stream(139 request: Request,140 text: str = Query(),141 speaker_wav: str = Query(),142 language: str = Query(),143 ):144 # speaker_wav 就是 speaker id 。。。145 voice_id = speaker_wav146 147 spk = speaker_mgr.get_speaker_by_id(voice_id) or speaker_mgr.get_speaker(148 voice_id149 )150 if spk is None:151 raise HTTPException(status_code=400, detail="Invalid speaker id")152 153 tts_config = ChatTTSConfig(154 style=XTTSV2.style,155 temperature=XTTSV2.temperature,156 top_k=XTTSV2.top_k,157 top_p=XTTSV2.top_p,158 prefix=XTTSV2.prefix,159 prompt1=XTTSV2.prompt1,160 prompt2=XTTSV2.prompt2,161 )162 infer_config = InferConfig(163 batch_size=XTTSV2.batch_size,164 spliter_threshold=XTTSV2.spliter_threshold,165 eos=XTTSV2.eos,166 seed=XTTSV2.infer_seed,167 )168 adjust_config = AdjustConfig(169 speed_rate=XTTSV2.speed,170 )171 # TODO: support enhancer172 enhancer_config = EnhancerConfig(173 # enabled=params.enhance or params.denoise or False,174 # lambd=0.9 if params.denoise else 0.1,175 )176 177 handler = TTSHandler(178 text_content=text,179 spk=spk,180 tts_config=tts_config,181 infer_config=infer_config,182 adjust_config=adjust_config,183 enhancer_config=enhancer_config,184 )185 186 async def generator():187 for chunk in handler.enqueue_to_stream(AudioFormat.mp3):188 disconnected = await request.is_disconnected()189 if disconnected:190 break191 192 yield chunk193 194 return StreamingResponse(generator(), media_type="audio/mpeg")195 196 @app.post("/v1/xtts_v2/set_tts_settings")197 async def set_tts_settings(request: TTSSettingsRequest):198 try:199 if request.stream_chunk_size < 50:200 raise HTTPException(201 status_code=400, detail="stream_chunk_size must be greater than 0"202 )203 if request.temperature < 0:204 raise HTTPException(205 status_code=400, detail="temperature must be greater than 0"206 )207 if request.speed < 0:208 raise HTTPException(209 status_code=400, detail="speed must be greater than 0"210 )211 if request.length_penalty < 0:212 raise HTTPException(213 status_code=400, detail="length_penalty must be greater than 0"214 )215 if request.repetition_penalty < 0:216 raise HTTPException(217 status_code=400, detail="repetition_penalty must be greater than 0"218 )219 if request.top_p < 0:220 raise HTTPException(221 status_code=400, detail="top_p must be greater than 0"222 )223 if request.top_k < 0:224 raise HTTPException(225 status_code=400, detail="top_k must be greater than 0"226 )227 228 XTTSV2.stream_chunk_size = request.stream_chunk_size229 XTTSV2.spliter_threshold = request.stream_chunk_size230 231 XTTSV2.temperature = request.temperature232 XTTSV2.speed = request.speed233 XTTSV2.length_penalty = request.length_penalty234 XTTSV2.repetition_penalty = request.repetition_penalty235 XTTSV2.top_p = request.top_p236 XTTSV2.top_k = request.top_k237 XTTSV2.enable_text_splitting = request.enable_text_splitting238 239 # TODO: checker240 if request.batch_size:241 XTTSV2.batch_size = request.batch_size242 if request.eos:243 XTTSV2.eos = request.eos244 if request.infer_seed:245 XTTSV2.infer_seed = request.infer_seed246 if request.use_decoder:247 XTTSV2.use_decoder = request.use_decoder248 if request.prompt1:249 XTTSV2.prompt1 = request.prompt1250 if request.prompt2:251 XTTSV2.prompt2 = request.prompt2252 if request.prefix:253 XTTSV2.prefix = request.prefix254 if request.spliter_threshold:255 XTTSV2.spliter_threshold = request.spliter_threshold256 if request.style:257 XTTSV2.style = request.style258 259 return {"message": "Settings successfully applied"}260 except Exception as e:261 if isinstance(e, HTTPException):262 raise e263 logger.error(e)264 raise HTTPException(status_code=500, detail=str(e))265 