Opera8 commited on
Commit
f1bf7b2
·
verified ·
1 Parent(s): 6a1339e

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +120 -7
index.html CHANGED
@@ -284,13 +284,13 @@
284
  <div class="settings-group"><label>سید (Seed) تصادفی=-1:</label><input type="number" id="seed_input" value="-1"></div>
285
 
286
  <div class="settings-group"><label>مقیاس هدایت (CFG):</label><input type="number" id="cfg_input" value="7.0" step="0.5"></div>
287
- <!-- اضافه شدن انتخاب زمان در کنار CFG -->
288
  <div class="settings-group"><label>مدت زمان آهنگ:</label><select id="duration_select"><option value="unknown" selected>خودکار (استاندارد)</option><option value="short">کوتاه (حدود ۱ دقیقه)</option><option value="medium">متوسط (حدود ۲ دقیقه)</option><option value="long">طولانی (حدود ۳ دقیقه)</option></select></div>
289
  </div>
290
 
291
  <div class="settings-group" style="border-top: 1px solid #e2e8f0; padding-top: 15px; margin-bottom: 10px;">
292
  <label>آپلود آهنگ نمونه (Audio Conditioning):</label>
293
  <input type="file" id="audio_reference" accept="audio/*" style="padding: 10px; width: 100%; background: #fff;">
 
294
  </div>
295
 
296
  <div class="checkbox-wrapper">
@@ -602,6 +602,105 @@
602
 
603
  initDB();
604
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
605
  // --- تابع آپلود فایل صوتی به Gradio ---
606
  async function uploadAudioFile(file) {
607
  const formData = new FormData();
@@ -639,12 +738,28 @@
639
  loader.style.display = 'block';
640
 
641
  try {
642
- // 1. آپلود فایل نمونه (اگر کاربر انتخاب کرده باشد)
643
  const audioInput = document.getElementById('audio_reference');
644
  let uploadedAudioObj = null;
 
645
  if (audioInput.files.length > 0) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
646
  loaderText.innerText = "در حال آپلود فایل نمونه...";
647
- uploadedAudioObj = await uploadAudioFile(audioInput.files[0]);
648
  }
649
 
650
  // 2. درخواست متن و پرامپت
@@ -670,7 +785,6 @@
670
  historySection.style.display = 'block';
671
  processBtn.disabled = false;
672
 
673
- // نمایش مودال ارتقا با متن مناسب
674
  upgradeModalTitle.innerText = "محدودیت ساخت روزانه";
675
  upgradeModalText.innerText = "شما به سقف ۵ آهنگ رایگان در روز رسیده‌اید. برای ساخت آهنگ‌های بیشتر و نامحدود، لطفا حساب خود را ارتقا دهید.";
676
  upgradeModal.classList.add('open');
@@ -685,12 +799,12 @@
685
 
686
  const finalLyrics = isInstrumental ? "" : lyrics;
687
 
688
- // ایندکس 3: مدت زمان آهنگ (قبلا "unknown" بود، الان getVal('duration_select'))
689
  const payload = [
690
  getVal('model_select'),
691
  "custom",
692
  uploadedAudioObj,
693
- getVal('duration_select'), // تغییر: استفاده از مقدار انتخابی زمان
694
  musicPrompt,
695
  finalLyrics,
696
  0, "", "", "unknown",
@@ -736,7 +850,6 @@
736
  hasResult = true;
737
 
738
  if (processedUrls.size === 1) {
739
- // تنظیم دکمه دانلود اصلی
740
  mainDownloadBtn.style.display = 'inline-flex';
741
  mainDownloadBtn.onclick = (e) => handleSecureDownload(fullUrl, e);
742
 
 
284
  <div class="settings-group"><label>سید (Seed) تصادفی=-1:</label><input type="number" id="seed_input" value="-1"></div>
285
 
286
  <div class="settings-group"><label>مقیاس هدایت (CFG):</label><input type="number" id="cfg_input" value="7.0" step="0.5"></div>
 
287
  <div class="settings-group"><label>مدت زمان آهنگ:</label><select id="duration_select"><option value="unknown" selected>خودکار (استاندارد)</option><option value="short">کوتاه (حدود ۱ دقیقه)</option><option value="medium">متوسط (حدود ۲ دقیقه)</option><option value="long">طولانی (حدود ۳ دقیقه)</option></select></div>
288
  </div>
289
 
290
  <div class="settings-group" style="border-top: 1px solid #e2e8f0; padding-top: 15px; margin-bottom: 10px;">
291
  <label>آپلود آهنگ نمونه (Audio Conditioning):</label>
292
  <input type="file" id="audio_reference" accept="audio/*" style="padding: 10px; width: 100%; background: #fff;">
293
+ <div style="font-size: 0.8rem; color: #666; margin-top: 5px;">(تمامی فرمت‌های صوتی پشتیبانی می‌شوند، خودکار به WAV تبدیل می‌شود)</div>
294
  </div>
295
 
296
  <div class="checkbox-wrapper">
 
602
 
603
  initDB();
604
 
605
+ // --- توابع تبدیل فرمت صوتی (Client-Side WAV Converter) ---
606
+ function writeString(view, offset, string) {
607
+ for (let i = 0; i < string.length; i++) {
608
+ view.setUint8(offset + i, string.charCodeAt(i));
609
+ }
610
+ }
611
+
612
+ function floatTo16BitPCM(output, offset, input) {
613
+ for (let i = 0; i < input.length; i++, offset += 2) {
614
+ let s = Math.max(-1, Math.min(1, input[i]));
615
+ output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
616
+ }
617
+ }
618
+
619
+ function interleave(inputL, inputR) {
620
+ const length = inputL.length + inputR.length;
621
+ const result = new Float32Array(length);
622
+ let index = 0;
623
+ let inputIndex = 0;
624
+ while (index < length) {
625
+ result[index++] = inputL[inputIndex];
626
+ result[index++] = inputR[inputIndex];
627
+ inputIndex++;
628
+ }
629
+ return result;
630
+ }
631
+
632
+ function bufferToWave(abuffer, len) {
633
+ let numOfChan = abuffer.numberOfChannels;
634
+ let length = len * numOfChan * 2 + 44;
635
+ let buffer = new ArrayBuffer(length);
636
+ let view = new DataView(buffer);
637
+ let channels = [], i, sample;
638
+ let offset = 0;
639
+ let pos = 0;
640
+
641
+ // write WAVE header
642
+ writeString(view, 0, 'RIFF');
643
+ view.setUint32(4, 36 + len * numOfChan * 2, true);
644
+ writeString(view, 8, 'WAVE');
645
+ writeString(view, 12, 'fmt ');
646
+ view.setUint32(16, 16, true);
647
+ view.setUint16(20, 1, true);
648
+ view.setUint16(22, numOfChan, true);
649
+ view.setUint32(24, abuffer.sampleRate, true);
650
+ view.setUint32(28, abuffer.sampleRate * 2 * numOfChan, true);
651
+ view.setUint16(32, numOfChan * 2, true);
652
+ view.setUint16(34, 16, true);
653
+ writeString(view, 36, 'data');
654
+ view.setUint32(40, len * numOfChan * 2, true);
655
+
656
+ // write interleaved data
657
+ for(i = 0; i < abuffer.numberOfChannels; i++)
658
+ channels.push(abuffer.getChannelData(i));
659
+
660
+ offset = 44;
661
+ // Interleave logic handled simply here for 1 or 2 channels
662
+ if (numOfChan === 2) {
663
+ while(pos < len) {
664
+ for(i = 0; i < numOfChan; i++) {
665
+ sample = Math.max(-1, Math.min(1, channels[i][pos]));
666
+ sample = (sample < 0 ? sample * 0x8000 : sample * 0x7FFF) | 0;
667
+ view.setInt16(offset, sample, true);
668
+ offset += 2;
669
+ }
670
+ pos++;
671
+ }
672
+ } else {
673
+ while(pos < len) {
674
+ sample = Math.max(-1, Math.min(1, channels[0][pos]));
675
+ sample = (sample < 0 ? sample * 0x8000 : sample * 0x7FFF) | 0;
676
+ view.setInt16(offset, sample, true);
677
+ offset += 2;
678
+ pos++;
679
+ }
680
+ }
681
+ return new Blob([buffer], { type: "audio/wav" });
682
+ }
683
+
684
+ async function convertAudioToWav(file) {
685
+ return new Promise((resolve, reject) => {
686
+ const reader = new FileReader();
687
+ reader.onload = function(e) {
688
+ const audioContext = new (window.AudioContext || window.webkitAudioContext)();
689
+ audioContext.decodeAudioData(e.target.result, function(buffer) {
690
+ const wavBlob = bufferToWave(buffer, buffer.length);
691
+ // ساخت فایل جدید با فرمت wav
692
+ const wavFile = new File([wavBlob], file.name.replace(/\.[^/.]+$/, "") + ".wav", { type: "audio/wav" });
693
+ resolve(wavFile);
694
+ }, function(e){
695
+ console.error("Audio decode failed", e);
696
+ reject("فرمت فایل صوتی پشتیبانی نمی‌شود.");
697
+ });
698
+ };
699
+ reader.onerror = reject;
700
+ reader.readAsArrayBuffer(file);
701
+ });
702
+ }
703
+
704
  // --- تابع آپلود فایل صوتی به Gradio ---
705
  async function uploadAudioFile(file) {
706
  const formData = new FormData();
 
738
  loader.style.display = 'block';
739
 
740
  try {
741
+ // 1. آپلود و تبدیل فایل نمونه
742
  const audioInput = document.getElementById('audio_reference');
743
  let uploadedAudioObj = null;
744
+
745
  if (audioInput.files.length > 0) {
746
+ let fileToUpload = audioInput.files[0];
747
+
748
+ // بررسی و تبدیل به WAV
749
+ if (fileToUpload.type !== 'audio/wav' && !fileToUpload.name.toLowerCase().endsWith('.wav')) {
750
+ loaderText.innerText = "در حال تبدیل فرمت فایل صوتی به WAV...";
751
+ try {
752
+ fileToUpload = await convertAudioToWav(fileToUpload);
753
+ console.log("Converted to WAV:", fileToUpload.name, fileToUpload.size);
754
+ } catch (err) {
755
+ console.error(err);
756
+ alert("خطا در تبدیل فایل صوتی. لطفاً فایل WAV معتبر آپلود کنید.");
757
+ throw new Error("Audio conversion failed");
758
+ }
759
+ }
760
+
761
  loaderText.innerText = "در حال آپلود فایل نمونه...";
762
+ uploadedAudioObj = await uploadAudioFile(fileToUpload);
763
  }
764
 
765
  // 2. درخواست متن و پرامپت
 
785
  historySection.style.display = 'block';
786
  processBtn.disabled = false;
787
 
 
788
  upgradeModalTitle.innerText = "محدودیت ساخت روزانه";
789
  upgradeModalText.innerText = "شما به سقف ۵ آهنگ رایگان در روز رسیده‌اید. برای ساخت آهنگ‌های بیشتر و نامحدود، لطفا حساب خود را ارتقا دهید.";
790
  upgradeModal.classList.add('open');
 
799
 
800
  const finalLyrics = isInstrumental ? "" : lyrics;
801
 
802
+ // ایندکس 3: مدت زمان آهنگ
803
  const payload = [
804
  getVal('model_select'),
805
  "custom",
806
  uploadedAudioObj,
807
+ getVal('duration_select'),
808
  musicPrompt,
809
  finalLyrics,
810
  0, "", "", "unknown",
 
850
  hasResult = true;
851
 
852
  if (processedUrls.size === 1) {
 
853
  mainDownloadBtn.style.display = 'inline-flex';
854
  mainDownloadBtn.onclick = (e) => handleSecureDownload(fullUrl, e);
855