Hamed744 commited on
Commit
3270dcb
·
verified ·
1 Parent(s): e5ae16c

Update index.html

Browse files
Files changed (1) hide show
  1. 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 Body Styles */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  body {
11
- font-family: 'Vazirmatn', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
12
- background-color: #f0f2f5;
13
- color: #333;
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-color: white;
 
 
 
25
  padding: 40px;
26
- border-radius: 12px;
27
- box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
28
  text-align: center;
29
  max-width: 450px;
30
  width: 90%;
31
- transition: opacity 0.5s ease-out, transform 0.5s ease-out;
 
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: #2c3e50;
42
  margin-bottom: 15px;
43
  font-size: 26px;
44
  }
45
 
46
  #delta-gate-container p {
47
- color: #7f8c8d;
48
  margin-bottom: 30px;
49
  font-size: 16px;
 
50
  }
51
 
52
  #delta-code-input {
53
  width: 100%;
54
  padding: 15px;
55
- border: 1px solid #bdc3c7;
56
- border-radius: 8px;
 
57
  font-size: 16px;
58
  text-align: center;
 
59
  box-sizing: border-box;
60
- direction: ltr; /* For code input */
61
- margin-bottom: 20px;
 
 
 
 
 
62
  }
63
 
64
  #delta-code-input:focus {
65
  outline: none;
66
- border-color: #3498db;
67
- box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.2);
68
  }
69
 
70
  #verify-button {
71
  width: 100%;
72
  padding: 15px;
73
- background: linear-gradient(135deg, #3498db, #2980b9);
74
  color: white;
75
  border: none;
76
- border-radius: 8px;
77
  cursor: pointer;
78
  font-size: 18px;
79
  font-weight: bold;
80
- transition: background 0.3s ease;
 
 
 
 
 
 
 
81
  }
82
 
83
  #verify-button:disabled {
84
- background: #bdc3c7;
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: #e74c3c;
94
- margin-top: 15px;
95
  font-weight: bold;
96
  min-height: 20px;
97
  }
98
 
99
-
100
  /* --- Main Content (Vevo API) Styles --- */
101
  #main-content-container {
102
- display: none; /* Hidden by default */
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', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
111
  margin: 20px auto;
112
  background-color: #f7fafc;
113
  color: #2d3748;
114
  direction: rtl;
115
- padding: 20px;
116
- border-radius: 8px;
117
  max-width: 600px;
118
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
 
119
  }
120
  #huggingface-vevo-api-container .container {
121
  padding: 20px;
122
  background-color: white;
123
- border-radius: 8px;
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
- width: 100%;
156
- padding: 12px;
157
- background-color: #4299e1;
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-color: #a0aec0;
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: #4299e1;
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>برای دسترسی به ابزار ساخت صدا، لطفاً کد دسترسی (کد دلتا) خود را وارد کنید.</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
- mainContentContainer.style.opacity = '1';
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.textContent = 'در حال بررسی...';
264
 
265
  try {
266
- // NOTE: 'send_code.php' must be in the same directory as this HTML file on your server
267
- const response = await fetch('send_code.php', {
268
  method: 'POST',
269
- headers: {
270
- 'Content-Type': 'application/x-www-form-urlencoded',
271
- },
272
  body: `delta_code=${encodeURIComponent(code)}`
273
  });
274
 
275
- const result = await response.json();
276
-
277
- if (result.status === 'success') {
278
- // 3. If successful, save state and show main content
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.textContent = 'تأیید و ورود';
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) { // Ensure container exists before adding listeners
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
- function generateSessionHash() {
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
- return result[0];
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, "size": sourceFile.size, "mime_type": sourceFile.type, "meta": { "_type": "gradio.FileData" } },
353
- { "path": timbrePath, "url": `${API_URL}file=${timbrePath}`, "orig_name": timbreFile.name, "size": timbreFile.size, "mime_type": timbreFile.type, "meta": { "_type": "gradio.FileData" } }
354
  ],
355
- "event_data": null,
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 = function(event) {
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 = function() {
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;