feat: 글자속도·단어간격·문장간격 독립 조절 + atempo 기본 타임스트레치

- 타임스트레치 우선순위를 ffmpeg atempo(기본) → rubberband → librosa 로 변경
- MeloEngine: 문장 단위로 분리 후 문장 사이 무음(sentence_gap), 단어(어절) 사이
  무음(word_gap)을 타임스트레치와 독립적으로 삽입. speed 는 글자(음소) 속도만 조절
- API(TTSRequest)에 word_gap/sentence_gap 필드 추가, 전 엔진 시그니처 확장
- 프론트엔드에 '글자 속도/단어 간격/문장 간격' 슬라이더 추가, supports 플래그로
  미지원 엔진(supertonic/oute/cosy)에서는 간격 슬라이더 자동 비활성화
This commit is contained in:
claude
2026-08-25 23:54:48 +09:00
parent e16f88e534
commit c0665893a7
8 changed files with 181 additions and 50 deletions

View File

@@ -39,8 +39,10 @@ class TTSRequest(BaseModel):
engine: str | None = Field(None, description="엔진 ID (melo / coqui-kss 등)")
language: str = Field("KR", description="언어 코드")
speaker: str | None = Field(None, description="화자/모델 ID")
speed: float = Field(1.4, ge=0.5, le=2.0, description="말하기 속도")
speed: float = Field(1.4, ge=0.5, le=2.0, description="글자(음소) 발화 속도")
pitch: float = Field(0.0, ge=-12.0, le=12.0, description="피치(반음)")
word_gap: float = Field(0.0, ge=0.0, le=1.0, description="단어 사이 무음(초)")
sentence_gap: float = Field(0.3, ge=0.0, le=2.0, description="문장 사이 무음(초)")
@app.on_event("startup")
@@ -80,6 +82,8 @@ def tts(req: TTSRequest) -> Response:
speaker=req.speaker,
speed=req.speed,
pitch=req.pitch,
word_gap=req.word_gap,
sentence_gap=req.sentence_gap,
)
except ValueError as exc:
raise HTTPException(status_code=400, detail=str(exc))