Opera8 commited on
Commit
8e58bb9
·
verified ·
1 Parent(s): 7222679

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +105 -77
index.html CHANGED
@@ -97,7 +97,11 @@
97
  font-size: 1.1rem; font-weight: 700; cursor: pointer;
98
  display: flex; justify-content: center; align-items: center; gap: 10px;
99
  box-shadow: 0 5px 15px var(--accent-glow);
100
- transition: transform 0.2s;
 
 
 
 
101
  }
102
  .btn-main:active { transform: scale(0.98); }
103
  .btn-main:disabled { opacity: 0.7; cursor: not-allowed; filter: grayscale(1); }
@@ -205,7 +209,7 @@
205
  <button id="processBtn" class="btn-main" style="margin-top: 15px;"><span>ساخت آهنگ 🎵</span></button>
206
  </div>
207
 
208
- <div id="loader">
209
  <div class="wave-bars"><div class="bar"></div><div class="bar"></div><div class="bar"></div><div class="bar"></div><div class="bar"></div></div>
210
  <p id="loaderText">در حال پردازش...</p>
211
  </div>
@@ -218,7 +222,7 @@
218
  <div id="playerWrapper"></div>
219
  <div class="form-label" style="margin-top: 20px; justify-content: center; color: #718096;">متن آهنگ</div>
220
  <div class="lyrics-container" id="finalLyricsBox"></div>
221
- <button onclick="location.reload()" class="btn-main btn-outline">ساخت آهنگ جدید</button>
222
  </div>
223
 
224
  <div id="historySection">
@@ -232,7 +236,8 @@
232
 
233
  <script>
234
  const ACE_SPACE_URL = "https://ace-step-ace-step-v1-5.hf.space/";
235
-
 
236
  // المان‌ها
237
  const ideaInput = document.getElementById('ideaInput');
238
  const processBtn = document.getElementById('processBtn');
@@ -260,70 +265,114 @@
260
  });
261
  }
262
 
263
- // --- مدیریت سوابق ---
264
- function loadHistory() {
265
- const history = JSON.parse(localStorage.getItem('alphaHistory')) || [];
266
- historyList.innerHTML = '';
267
-
268
- if (history.length === 0) {
269
- historyList.innerHTML = '<div style="text-align:center; color:#999; padding:20px;">هنوز آهنگی نساخته‌اید</div>';
270
- return;
271
- }
272
 
273
- history.forEach((item) => {
274
- const div = document.createElement('div');
275
- div.className = 'history-card';
276
- div.innerHTML = `
277
- <div class="h-info">
278
- <div class="h-icon">🎵</div>
279
- <div class="h-details">
280
- <h4>${item.idea.substring(0, 30)}${item.idea.length > 30 ? '...' : ''}</h4>
281
- <span>${item.date}</span>
282
- </div>
283
- </div>
284
- <div class="h-play">▶ نمایش</div>
285
- `;
286
- div.onclick = () => openHistoryItem(item);
287
- historyList.appendChild(div);
288
- });
289
  }
290
 
291
- function saveToHistory(idea, lyrics, audioUrl) {
292
- let history = JSON.parse(localStorage.getItem('alphaHistory')) || [];
293
- const newItem = {
294
- id: Date.now(), idea: idea, lyrics: lyrics, audioUrl: audioUrl,
295
- date: new Date().toLocaleDateString('fa-IR', { hour: '2-digit', minute: '2-digit' })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
296
  };
297
- history.unshift(newItem);
298
- if (history.length > 10) history.pop();
299
- localStorage.setItem('alphaHistory', JSON.stringify(history));
300
- loadHistory();
301
  }
302
 
303
  function openHistoryItem(item) {
304
- // مخفی کردن صفحه اصلی
305
  step1.style.display = 'none';
306
  historySection.style.display = 'none';
 
 
 
307
 
308
- // پر کردن صفحه نتیجه با اطلاعات سابقه
309
  const headerText = document.getElementById('resultHeaderText');
310
- headerText.innerHTML = `
311
- <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path><polyline points="22 4 12 14.01 9 11.01"></polyline></svg>
312
- آهنگ آرشیو شده
313
- `;
314
  headerText.style.color = 'var(--accent-primary)';
315
 
316
- mainDownloadLink.href = item.audioUrl;
317
  mainDownloadLink.style.display = 'inline-block';
318
- playerWrapper.innerHTML = `<audio controls autoplay src="${item.audioUrl}"></audio>`;
319
  finalLyricsBox.innerHTML = formatLyrics(item.lyrics);
320
 
321
- // نمایش صفحه نتیجه
322
  finalResult.style.display = 'block';
323
  window.scrollTo({ top: 0, behavior: 'smooth' });
324
  }
325
 
326
- loadHistory();
 
327
 
328
  // --- فرآیند اصلی ساخت آهنگ ---
329
  processBtn.addEventListener('click', async () => {
@@ -331,29 +380,18 @@
331
 
332
  processBtn.disabled = true;
333
  step1.style.display = 'none';
334
- historySection.style.display = 'none'; // مخفی کردن سابقه
335
  loader.style.display = 'block';
336
 
337
  try {
338
  loaderText.innerText = "آلفا در حال نوشتن شعر و ملودی...";
339
-
340
- const response = await fetch('/api/refine', {
341
- method: 'POST',
342
- headers: {'Content-Type': 'application/json'},
343
- body: JSON.stringify({ idea: ideaInput.value })
344
- });
345
-
346
  const data = await response.json();
347
  if (data.error) throw new Error(data.error);
348
 
349
- const lyrics = data.lyrics;
350
- const musicPrompt = data.music_prompt;
351
-
352
  loaderText.innerText = "در حال ضبط آهنگ در استودیو آلفا...";
353
 
354
- formatLyricsForDisplay(lyrics);
355
- playerWrapper.innerHTML = '';
356
-
357
  const payload = [
358
  getVal('model_select'), "custom", null, "unknown", musicPrompt, lyrics, 0, "", "", "unknown",
359
  getNum('steps_input'), getNum('cfg_input'), true, getNum('seed_input'), null, -1,
@@ -363,16 +401,10 @@
363
  ];
364
 
365
  const session_hash = Math.random().toString(36).substring(2);
366
- const joinResp = await fetch(`${ACE_SPACE_URL}gradio_api/queue/join`, {
367
- method: 'POST',
368
- headers: { 'Content-Type': 'application/json' },
369
- body: JSON.stringify({ data: payload, fn_index: 77, session_hash })
370
- });
371
-
372
  if (!joinResp.ok) throw new Error('خطا در اتصال به سرور موزیک');
373
 
374
  const eventSource = new EventSource(`${ACE_SPACE_URL}gradio_api/queue/data?session_hash=${session_hash}`);
375
-
376
  eventSource.onmessage = (event) => {
377
  const msg = JSON.parse(event.data);
378
  if (msg.msg === 'process_starts') loaderText.innerText = "هوش مصنوعی در حال خواندن...";
@@ -388,7 +420,7 @@
388
  alert("خطا: " + e.message);
389
  loader.style.display = 'none';
390
  step1.style.display = 'block';
391
- historySection.style.display = 'block'; // نمایش مجدد سابقه در صورت خطا
392
  processBtn.disabled = false;
393
  }
394
  });
@@ -406,9 +438,8 @@
406
  if (processedUrls.size === 1) {
407
  mainDownloadLink.href = fullUrl;
408
  mainDownloadLink.style.display = 'inline-block';
409
- saveToHistory(idea, lyrics, fullUrl);
410
  }
411
-
412
  playerWrapper.innerHTML += `<div class="audio-item"><audio controls src="${fullUrl}"></audio></div>`;
413
  }
414
 
@@ -423,12 +454,10 @@
423
 
424
  if (hasResult) {
425
  const headerText = document.getElementById('resultHeaderText');
426
- headerText.innerHTML = `
427
- <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path><polyline points="22 4 12 14.01 9 11.01"></polyline></svg>
428
- آهنگ جدید آماده شد
429
- `;
430
  headerText.style.color = 'var(--success-color)';
431
  finalResult.style.display = 'block';
 
432
  window.scrollTo({ top: 0, behavior: 'smooth' });
433
  } else {
434
  alert("فایل صوتی یافت نشد!");
@@ -438,7 +467,6 @@
438
  }
439
 
440
  function formatLyrics(text) { return text.replace(/\[(.*?)\]/g, '<span class="lyrics-tag">[$1]</span>'); }
441
- function formatLyricsForDisplay(text) { finalLyricsBox.innerHTML = formatLyrics(text); }
442
 
443
  const canvas = document.getElementById('music-canvas');
444
  const ctx = canvas.getContext('2d');
 
97
  font-size: 1.1rem; font-weight: 700; cursor: pointer;
98
  display: flex; justify-content: center; align-items: center; gap: 10px;
99
  box-shadow: 0 5px 15px var(--accent-glow);
100
+ transition: all 0.2s ease-out;
101
+ }
102
+ .btn-main:hover {
103
+ transform: translateY(-2px);
104
+ box-shadow: 0 8px 25px var(--accent-glow);
105
  }
106
  .btn-main:active { transform: scale(0.98); }
107
  .btn-main:disabled { opacity: 0.7; cursor: not-allowed; filter: grayscale(1); }
 
209
  <button id="processBtn" class="btn-main" style="margin-top: 15px;"><span>ساخت آهنگ 🎵</span></button>
210
  </div>
211
 
212
+ <div id="loader" style="display: none;">
213
  <div class="wave-bars"><div class="bar"></div><div class="bar"></div><div class="bar"></div><div class="bar"></div><div class="bar"></div></div>
214
  <p id="loaderText">در حال پردازش...</p>
215
  </div>
 
222
  <div id="playerWrapper"></div>
223
  <div class="form-label" style="margin-top: 20px; justify-content: center; color: #718096;">متن آهنگ</div>
224
  <div class="lyrics-container" id="finalLyricsBox"></div>
225
+ <button onclick="location.reload()" class="btn-main btn-outline">برگشت و ساخت آهنگ جدید</button>
226
  </div>
227
 
228
  <div id="historySection">
 
236
 
237
  <script>
238
  const ACE_SPACE_URL = "https://ace-step-ace-step-v1-5.hf.space/";
239
+ let db; // متغیر برای نگهداری اتصال به پایگاه داده
240
+
241
  // المان‌ها
242
  const ideaInput = document.getElementById('ideaInput');
243
  const processBtn = document.getElementById('processBtn');
 
265
  });
266
  }
267
 
268
+ // --- مدیریت پایگاه داده IndexedDB ---
269
+ function initDB() {
270
+ const request = indexedDB.open("alphaMusicDB", 1);
 
 
 
 
 
 
271
 
272
+ request.onerror = (event) => console.error("خطای IndexedDB:", event);
273
+ request.onsuccess = (event) => {
274
+ db = event.target.result;
275
+ loadHistory(); // بارگذاری سوابق پس از اتصال موفق
276
+ };
277
+ request.onupgradeneeded = (event) => {
278
+ const db = event.target.result;
279
+ db.createObjectStore("songs", { keyPath: "id" });
280
+ };
 
 
 
 
 
 
 
281
  }
282
 
283
+ async function saveToHistory(idea, lyrics, audioUrl) {
284
+ try {
285
+ // دریافت فایل صوتی به صورت Blob
286
+ const response = await fetch(audioUrl);
287
+ const audioBlob = await response.blob();
288
+
289
+ const newItem = {
290
+ id: Date.now(), idea: idea, lyrics: lyrics, audioBlob: audioBlob,
291
+ date: new Date().toLocaleDateString('fa-IR', { hour: '2-digit', minute: '2-digit' })
292
+ };
293
+
294
+ const transaction = db.transaction(["songs"], "readwrite");
295
+ const store = transaction.objectStore("songs");
296
+ store.add(newItem);
297
+
298
+ // مدیریت محدودیت 10 آیتم
299
+ const countReq = store.count();
300
+ countReq.onsuccess = () => {
301
+ if (countReq.result > 10) {
302
+ const cursorReq = store.openCursor(); // قدیمی‌ترین اولین است
303
+ cursorReq.onsuccess = (e) => {
304
+ const cursor = e.target.result;
305
+ if (cursor) {
306
+ cursor.delete();
307
+ }
308
+ };
309
+ }
310
+ };
311
+
312
+ transaction.oncomplete = () => loadHistory();
313
+
314
+ } catch (error) {
315
+ console.error("خطا در ذخیره آهنگ:", error);
316
+ alert("خطایی در ذخیره آهنگ در مرورگر رخ داد. ممکن است لینک موقتی باشد.");
317
+ }
318
+ }
319
+
320
+ function loadHistory() {
321
+ if (!db) return;
322
+ const transaction = db.transaction(["songs"], "readonly");
323
+ const store = transaction.objectStore("songs");
324
+ const allReq = store.getAll();
325
+
326
+ allReq.onsuccess = () => {
327
+ const history = allReq.result.sort((a, b) => b.id - a.id); // جدیدترین‌ها اول
328
+ historyList.innerHTML = '';
329
+
330
+ if (history.length === 0) {
331
+ historyList.innerHTML = '<div style="text-align:center; color:#999; padding:20px;">هنوز آهنگی نساخته‌اید</div>';
332
+ return;
333
+ }
334
+
335
+ history.forEach((item) => {
336
+ const div = document.createElement('div');
337
+ div.className = 'history-card';
338
+ div.innerHTML = `
339
+ <div class="h-info">
340
+ <div class="h-icon">🎵</div>
341
+ <div class="h-details">
342
+ <h4>${item.idea.substring(0, 30)}${item.idea.length > 30 ? '...' : ''}</h4>
343
+ <span>${item.date}</span>
344
+ </div>
345
+ </div>
346
+ <div class="h-play">▶ نمایش</div>
347
+ `;
348
+ div.onclick = () => openHistoryItem(item);
349
+ historyList.appendChild(div);
350
+ });
351
  };
 
 
 
 
352
  }
353
 
354
  function openHistoryItem(item) {
 
355
  step1.style.display = 'none';
356
  historySection.style.display = 'none';
357
+
358
+ // تبدیل Blob به URL قابل پخش
359
+ const audioURL = URL.createObjectURL(item.audioBlob);
360
 
 
361
  const headerText = document.getElementById('resultHeaderText');
362
+ headerText.innerHTML = `<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path><polyline points="22 4 12 14.01 9 11.01"></polyline></svg> آهنگ آرشیو شده`;
 
 
 
363
  headerText.style.color = 'var(--accent-primary)';
364
 
365
+ mainDownloadLink.href = audioURL;
366
  mainDownloadLink.style.display = 'inline-block';
367
+ playerWrapper.innerHTML = `<audio controls autoplay src="${audioURL}"></audio>`;
368
  finalLyricsBox.innerHTML = formatLyrics(item.lyrics);
369
 
 
370
  finalResult.style.display = 'block';
371
  window.scrollTo({ top: 0, behavior: 'smooth' });
372
  }
373
 
374
+ // شروع به کار پایگاه داده
375
+ initDB();
376
 
377
  // --- فرآیند اصلی ساخت آهنگ ---
378
  processBtn.addEventListener('click', async () => {
 
380
 
381
  processBtn.disabled = true;
382
  step1.style.display = 'none';
383
+ historySection.style.display = 'none';
384
  loader.style.display = 'block';
385
 
386
  try {
387
  loaderText.innerText = "آلفا در حال نوشتن شعر و ملودی...";
388
+ const response = await fetch('/api/refine', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ idea: ideaInput.value }) });
 
 
 
 
 
 
389
  const data = await response.json();
390
  if (data.error) throw new Error(data.error);
391
 
392
+ const { lyrics, musicPrompt } = data;
 
 
393
  loaderText.innerText = "در حال ضبط آهنگ در استودیو آلفا...";
394
 
 
 
 
395
  const payload = [
396
  getVal('model_select'), "custom", null, "unknown", musicPrompt, lyrics, 0, "", "", "unknown",
397
  getNum('steps_input'), getNum('cfg_input'), true, getNum('seed_input'), null, -1,
 
401
  ];
402
 
403
  const session_hash = Math.random().toString(36).substring(2);
404
+ const joinResp = await fetch(`${ACE_SPACE_URL}gradio_api/queue/join`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ data: payload, fn_index: 77, session_hash }) });
 
 
 
 
 
405
  if (!joinResp.ok) throw new Error('خطا در اتصال به سرور موزیک');
406
 
407
  const eventSource = new EventSource(`${ACE_SPACE_URL}gradio_api/queue/data?session_hash=${session_hash}`);
 
408
  eventSource.onmessage = (event) => {
409
  const msg = JSON.parse(event.data);
410
  if (msg.msg === 'process_starts') loaderText.innerText = "هوش مصنوعی در حال خواندن...";
 
420
  alert("خطا: " + e.message);
421
  loader.style.display = 'none';
422
  step1.style.display = 'block';
423
+ historySection.style.display = 'block';
424
  processBtn.disabled = false;
425
  }
426
  });
 
438
  if (processedUrls.size === 1) {
439
  mainDownloadLink.href = fullUrl;
440
  mainDownloadLink.style.display = 'inline-block';
441
+ saveToHistory(idea, lyrics, fullUrl); // ذخیره سازی در IndexedDB
442
  }
 
443
  playerWrapper.innerHTML += `<div class="audio-item"><audio controls src="${fullUrl}"></audio></div>`;
444
  }
445
 
 
454
 
455
  if (hasResult) {
456
  const headerText = document.getElementById('resultHeaderText');
457
+ headerText.innerHTML = `<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path><polyline points="22 4 12 14.01 9 11.01"></polyline></svg>آهنگ جدید آماده شد`;
 
 
 
458
  headerText.style.color = 'var(--success-color)';
459
  finalResult.style.display = 'block';
460
+ finalLyricsBox.innerHTML = formatLyrics(lyrics);
461
  window.scrollTo({ top: 0, behavior: 'smooth' });
462
  } else {
463
  alert("فایل صوتی یافت نشد!");
 
467
  }
468
 
469
  function formatLyrics(text) { return text.replace(/\[(.*?)\]/g, '<span class="lyrics-tag">[$1]</span>'); }
 
470
 
471
  const canvas = document.getElementById('music-canvas');
472
  const ctx = canvas.getContext('2d');