- 타임스트레치 우선순위를 ffmpeg atempo(기본) → rubberband → librosa 로 변경 - MeloEngine: 문장 단위로 분리 후 문장 사이 무음(sentence_gap), 단어(어절) 사이 무음(word_gap)을 타임스트레치와 독립적으로 삽입. speed 는 글자(음소) 속도만 조절 - API(TTSRequest)에 word_gap/sentence_gap 필드 추가, 전 엔진 시그니처 확장 - 프론트엔드에 '글자 속도/단어 간격/문장 간격' 슬라이더 추가, supports 플래그로 미지원 엔진(supertonic/oute/cosy)에서는 간격 슬라이더 자동 비활성화
94 lines
3.7 KiB
HTML
94 lines
3.7 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="ko">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>한국어 TTS 스튜디오</title>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@400;500;700&display=swap" rel="stylesheet" />
|
|
<link rel="stylesheet" href="/static/style.css" />
|
|
</head>
|
|
<body>
|
|
<div class="app">
|
|
<header class="hero">
|
|
<div class="badge">무료 · 무제한 · GPU 가속</div>
|
|
<h1>한국어 TTS 스튜디오</h1>
|
|
<p class="subtitle">텍스트를 자연스러운 음성으로. 로그인 없이 마음껏 사용하세요.</p>
|
|
<div class="device-chip" id="deviceChip">엔진 확인 중…</div>
|
|
</header>
|
|
|
|
<main class="card">
|
|
<label class="field-label" for="text">읽을 내용</label>
|
|
<textarea id="text" rows="5" placeholder="예) 안녕하세요, 오늘도 좋은 하루 보내세요!">안녕하세요, 오늘 하루도 힘내세요! 이 목소리는 GPU로 생성되었습니다.</textarea>
|
|
<div class="text-meta"><span id="charCount">0</span>자</div>
|
|
|
|
<div class="control control-full">
|
|
<label class="field-label" for="engine">TTS 엔진</label>
|
|
<select id="engine"></select>
|
|
<div class="engine-info" id="engineInfo"></div>
|
|
</div>
|
|
|
|
<div class="controls">
|
|
<div class="control">
|
|
<label class="field-label" for="language">언어</label>
|
|
<select id="language"></select>
|
|
</div>
|
|
<div class="control">
|
|
<label class="field-label" for="speaker">목소리 모델</label>
|
|
<select id="speaker"></select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="sliders">
|
|
<div class="slider-row">
|
|
<div class="slider-head">
|
|
<span>글자 속도</span>
|
|
<span class="slider-val" id="speedVal">1.40x</span>
|
|
</div>
|
|
<input type="range" id="speed" min="0.5" max="2.0" step="0.05" value="1.4" />
|
|
<div class="slider-scale"><span>느리게</span><span>빠르게</span></div>
|
|
</div>
|
|
<div class="slider-row">
|
|
<div class="slider-head">
|
|
<span>단어 간격</span>
|
|
<span class="slider-val" id="wordGapVal">0 ms</span>
|
|
</div>
|
|
<input type="range" id="wordGap" min="0" max="1.0" step="0.02" value="0" />
|
|
<div class="slider-scale"><span>붙여서</span><span>띄어서</span></div>
|
|
</div>
|
|
<div class="slider-row">
|
|
<div class="slider-head">
|
|
<span>문장 간격</span>
|
|
<span class="slider-val" id="sentGapVal">0.30 s</span>
|
|
</div>
|
|
<input type="range" id="sentGap" min="0" max="1.5" step="0.05" value="0.3" />
|
|
<div class="slider-scale"><span>짧게</span><span>길게</span></div>
|
|
</div>
|
|
<div class="slider-row">
|
|
<div class="slider-head">
|
|
<span>피치</span>
|
|
<span class="slider-val" id="pitchVal">0 반음</span>
|
|
</div>
|
|
<input type="range" id="pitch" min="-12" max="12" step="1" value="0" />
|
|
<div class="slider-scale"><span>낮게</span><span>높게</span></div>
|
|
</div>
|
|
</div>
|
|
|
|
<button id="generate" class="btn-primary">
|
|
<span class="btn-text">음성 생성</span>
|
|
<span class="spinner" hidden></span>
|
|
</button>
|
|
|
|
<div class="result" id="result" hidden>
|
|
<audio id="audio" controls></audio>
|
|
<a id="download" class="btn-secondary" download="tts.wav">다운로드</a>
|
|
</div>
|
|
<div class="error" id="error" hidden></div>
|
|
</main>
|
|
|
|
<footer class="foot">MeloTTS 기반 · 한국어/영어 지원</footer>
|
|
</div>
|
|
<script src="/static/app.js"></script>
|
|
</body>
|
|
</html>
|