limkang commited on
Commit
793040e
Β·
verified Β·
1 Parent(s): e366bad

Upload index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +161 -0
templates/index.html ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="ko">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>MeloTTS + OpenVoice V2</title>
7
+ <style>
8
+ body {
9
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
10
+ background-color: #f4f4f9;
11
+ display: flex;
12
+ justify-content: center;
13
+ align-items: center;
14
+ min-height: 100vh;
15
+ margin: 0;
16
+ padding: 20px;
17
+ box-sizing: border-box;
18
+ }
19
+ .container {
20
+ background: white;
21
+ padding: 30px;
22
+ border-radius: 12px;
23
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
24
+ width: 100%;
25
+ max-width: 600px;
26
+ }
27
+ h1 {
28
+ text-align: center;
29
+ color: #333;
30
+ margin-bottom: 25px;
31
+ }
32
+ form div {
33
+ margin-bottom: 20px;
34
+ }
35
+ label {
36
+ display: block;
37
+ margin-bottom: 8px;
38
+ font-weight: 600;
39
+ color: #555;
40
+ }
41
+ textarea, input[type="file"] {
42
+ width: 100%;
43
+ padding: 12px;
44
+ border: 1px solid #ddd;
45
+ border-radius: 8px;
46
+ box-sizing: border-box;
47
+ font-size: 16px;
48
+ }
49
+ textarea {
50
+ resize: vertical;
51
+ min-height: 100px;
52
+ }
53
+ button {
54
+ width: 100%;
55
+ padding: 15px;
56
+ background-color: #007bff;
57
+ color: white;
58
+ border: none;
59
+ border-radius: 8px;
60
+ font-size: 18px;
61
+ font-weight: 600;
62
+ cursor: pointer;
63
+ transition: background-color 0.3s ease;
64
+ }
65
+ button:disabled {
66
+ background-color: #a0cfff;
67
+ cursor: not-allowed;
68
+ }
69
+ button:hover:not(:disabled) {
70
+ background-color: #0056b3;
71
+ }
72
+ #result-container {
73
+ margin-top: 30px;
74
+ text-align: center;
75
+ }
76
+ #status-message {
77
+ color: #666;
78
+ font-style: italic;
79
+ }
80
+ #audio-player {
81
+ width: 100%;
82
+ margin-top: 15px;
83
+ display: none; /* μ²˜μŒμ—λŠ” μˆ¨κΉ€ */
84
+ }
85
+ </style>
86
+ </head>
87
+ <body>
88
+
89
+ <div class="container">
90
+ <h1>μŒμ„± 볡제 ν…ŒμŠ€νŠΈ (MeloTTS + OpenVoice)</h1>
91
+ <form id="tts-form">
92
+ <div>
93
+ <label for="text-input">μŒμ„±μœΌλ‘œ λ³€ν™˜ν•  ν…μŠ€νŠΈ:</label>
94
+ <textarea id="text-input" name="text" required placeholder="동화 λ‚΄μš©μ„ 여기에 μž…λ ₯ν•˜μ„Έμš”..."></textarea>
95
+ </div>
96
+ <div>
97
+ <label for="audio-input">μ°Έμ‘° λͺ©μ†Œλ¦¬ 파일 (WAV, MP3):</label>
98
+ <input type="file" id="audio-input" name="reference_audio" accept="audio/*" required>
99
+ </div>
100
+ <button type="submit" id="submit-button">μŒμ„± μƒμ„±ν•˜κΈ°</button>
101
+ </form>
102
+
103
+ <div id="result-container">
104
+ <p id="status-message"></p>
105
+ <audio controls id="audio-player"></audio>
106
+ </div>
107
+ </div>
108
+
109
+ <script>
110
+ const ttsForm = document.getElementById('tts-form');
111
+ const submitButton = document.getElementById('submit-button');
112
+ const statusMessage = document.getElementById('status-message');
113
+ const audioPlayer = document.getElementById('audio-player');
114
+
115
+ ttsForm.addEventListener('submit', async (event) => {
116
+ event.preventDefault(); // 폼 κΈ°λ³Έ 제좜 λ™μž‘ λ°©μ§€
117
+
118
+ // 1. UIλ₯Ό 'λ‘œλ”© 쀑' μƒνƒœλ‘œ λ³€κ²½
119
+ submitButton.disabled = true;
120
+ statusMessage.textContent = 'μŒμ„± 생성 쀑... πŸš€ μž μ‹œλ§Œ κΈ°λ‹€λ €μ£Όμ„Έμš”. (μ„œλ²„κ°€ 처음 켜질 λ•ŒλŠ” λͺ‡ 뢄이 걸릴 수 μžˆμŠ΅λ‹ˆλ‹€)';
121
+ audioPlayer.style.display = 'none';
122
+ audioPlayer.src = '';
123
+
124
+ // 2. 폼 데이터λ₯Ό FormData 객체둜 생성
125
+ const formData = new FormData(ttsForm);
126
+
127
+ try {
128
+ // 3. fetchλ₯Ό μ‚¬μš©ν•΄ μ„œλ²„μ— POST μš”μ²­ 전솑
129
+ const response = await fetch('/generate-cloned-speech/', {
130
+ method: 'POST',
131
+ body: formData,
132
+ });
133
+
134
+ // 4. 응닡 처리
135
+ if (response.ok) {
136
+ // 성곡 μ‹œ: μ˜€λ””μ˜€ 데이터λ₯Ό Blob으둜 λ³€ν™˜
137
+ const audioBlob = await response.blob();
138
+ const audioUrl = URL.createObjectURL(audioBlob);
139
+
140
+ // μ˜€λ””μ˜€ ν”Œλ ˆμ΄μ–΄μ— κ²°κ³Ό ν‘œμ‹œ
141
+ audioPlayer.src = audioUrl;
142
+ audioPlayer.style.display = 'block';
143
+ statusMessage.textContent = 'μŒμ„± 생성이 μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€! πŸŽ‰';
144
+ } else {
145
+ // μ‹€νŒ¨ μ‹œ: μ„œλ²„μ—μ„œ 온 μ—λŸ¬ λ©”μ‹œμ§€ ν‘œμ‹œ
146
+ const errorData = await response.json();
147
+ statusMessage.textContent = `였λ₯˜ λ°œμƒ: ${errorData.detail || 'μ•Œ 수 μ—†λŠ” 였λ₯˜'}`;
148
+ }
149
+ } catch (error) {
150
+ // λ„€νŠΈμ›Œν¬ 였λ₯˜ λ“± μ˜ˆμ™Έ 처리
151
+ console.error('Fetch Error:', error);
152
+ statusMessage.textContent = 'λ„€νŠΈμ›Œν¬ 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€. λ‹€μ‹œ μ‹œλ„ν•΄μ£Όμ„Έμš”.';
153
+ } finally {
154
+ // 5. 성곡/μ‹€νŒ¨μ™€ 관계없이 λ²„νŠΌ λ‹€μ‹œ ν™œμ„±ν™”
155
+ submitButton.disabled = false;
156
+ }
157
+ });
158
+ </script>
159
+
160
+ </body>
161
+ </html>