• הורדת נקודות

    פורום מפתחים API
    1
    0 הצבעות
    1 פוסטים
    1 צפיות
    אין תגובות
  • הסרת פרסומות מספר משויך

    שאלות ועזרה הדדית
    7
    1 הצבעות
    7 פוסטים
    73 צפיות
    I
    @אוריה-דניאלי-0 כתב: @שלוחה-404 זה מה שאמרתי, אבל זה נשמע מההודעה של @יעקב-יצחק שזה קרה לו, אז העלתי השערה למה זה קורה ועל פיתרון. חבל להעלות השערות ובכך לבלבל את הציבור ולגרום לחפש פתרונות באפיקים לא נכונים. הסרת פרסומות זה על המערכת, ולא משנה אם הגיעו אליה דרך מספר ראשי או מספר משני שמפנה לשלוחה פנימית.
  • למכירה 10K יחידות במחיר מוזל

    שאלות ועזרה הדדית
    1
    0 הצבעות
    1 פוסטים
    17 צפיות
    אין תגובות
  • 0 הצבעות
    14 פוסטים
    54 צפיות
    ר
    בדקתי גם אצלי זה קורה בשרת YMX, כנראה זה באג של השרת, השאלה היא מה אפשר לעשות לסדר את זה??
  • 12 הצבעות
    117 פוסטים
    3k צפיות
    א
    הספקתי לסדר ממש קצת מהבעיות באתר שלי, בעקבות שיש כאלה שבבין הזמנים יצטרכו את זה העליתי לכאן את הקובץ. אחד מהדברים שסודרו זה העיצוב שלא עובד בכל הדרכים... תפתחו פנקס רשימות ואז תשמרו את זה על שם index.html ותפתחו אותו... בהצלחה!!!! <!DOCTYPE html> <html lang="he" dir="rtl"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>VoiceMaster AI Studio ✨</title> <script src="https://cdn.tailwindcss.com"></script> <style> @import url('https://fonts.googleapis.com/css2?family=Assistant:wght@300;400;600;700;800&display=swap'); body { font-family: 'Assistant', sans-serif; background: #f1f5f9; transition: background-color 0.3s ease, color 0.3s ease; } .dark-mode { background: #020617; color: #f8fafc; } .card { background: white; border: 1px solid #e2e8f0; transition: all 0.3s ease; } .dark-mode .card { background: #1e293b; border-color: #334155; } .loading-spinner { border: 2px solid rgba(255,255,255,0.3); border-top: 2px solid currentColor; border-radius: 50%; width: 16px; height: 16px; animation: spin 0.8s linear infinite; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .ai-glow { box-shadow: 0 0 25px rgba(99, 102, 241, 0.15); } .feature-badge { background: linear-gradient(90deg, #4f46e5, #9333ea); color: white; padding: 2px 8px; border-radius: 99px; font-size: 10px; font-weight: bold; } /* התאמת רכיבי שמע למכשירים ניידים */ audio { max-width: 100%; height: 36px; } </style> </head> <body class="min-h-screen py-4 sm:py-8 px-3 sm:px-6 md:px-8 transition-colors duration-500" id="bodyTag"> <div class="max-w-7xl mx-auto"> <header class="flex flex-wrap justify-between items-center gap-4 mb-6 sm:mb-8 pb-4 border-b border-slate-200 dark:border-slate-800"> <div class="flex items-center gap-3 sm:gap-4"> <div class="bg-indigo-600 p-2.5 sm:p-3 rounded-2xl text-white shadow-xl flex-shrink-0"> <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 sm:h-8 sm:w-8" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11a7 7 0 01-7 7m0 0a7 7 0 01-7-7m7 7v4m0 0H8m4 0h4m-4-8a3 3 0 01-3-3V5a3 3 0 116 0v6a3 3 0 01-3 3z" /> </svg> </div> <div> <h1 class="text-2xl sm:text-3xl font-black text-slate-800 dark:text-white tracking-tight leading-none uppercase">Voice<span class="text-indigo-600">Master</span></h1> <p class="text-[10px] sm:text-xs font-bold text-slate-400 uppercase tracking-widest mt-1">AI Smart Narration Hub</p> </div> </div> <div class="flex items-center gap-2"> <div class="relative"> <button id="apiKeyBtn" class="p-2.5 sm:p-3 rounded-xl card shadow-sm hover:scale-105 transition-all flex items-center gap-2 text-xs font-bold text-slate-600 dark:text-slate-300"> <svg class="w-4 h-4 sm:w-5 sm:h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z"/></svg> <span id="apiKeyStatus" class="hidden sm:inline">הגדר מפתח</span> </button> <div id="apiKeyPopover" class="hidden absolute left-0 sm:left-auto right-0 sm:right-0 mt-2 w-72 sm:w-80 p-4 card rounded-2xl shadow-2xl z-50"> <h4 class="font-bold text-sm mb-2 dark:text-white">Gemini API Key</h4> <input id="apiKeyInput" type="password" class="w-full p-2.5 text-xs bg-slate-50 dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 outline-none focus:ring-2 focus:ring-indigo-500 mb-2 dark:text-white" placeholder="AIzaSy..."> <div class="flex gap-2"> <button id="saveApiKey" class="flex-1 py-2 bg-indigo-600 text-white text-[11px] font-bold rounded-lg hover:bg-indigo-700 active:scale-95 transition-all">שמור מפתח</button> <button id="clearApiKey" class="flex-1 py-2 bg-red-50 text-red-600 text-[11px] font-bold rounded-lg hover:bg-red-100 active:scale-95 transition-all">מחק</button> </div> </div> </div> <button id="toggleDark" class="p-2.5 sm:p-3 rounded-xl card shadow-sm hover:scale-105 active:scale-95 transition-all"> <svg class="h-5 w-5 sm:h-6 sm:w-6 text-slate-600 dark:text-indigo-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"/> </svg> </button> </div> </header> <div class="grid grid-cols-1 lg:grid-cols-12 gap-6 lg:gap-8"> <div class="lg:col-span-5 space-y-6"> <div class="card p-4 sm:p-6 rounded-2xl sm:rounded-[2rem] shadow-lg ai-glow border-indigo-100 dark:border-indigo-900/30"> <div class="flex items-center justify-between mb-3 sm:mb-4"> <h3 class="font-bold text-sm sm:text-base text-indigo-900 dark:text-indigo-300">יצירת תוכן חכמה</h3> </div> <div class="flex gap-2 mb-3 sm:mb-4"> <input id="promptInput" type="text" class="flex-grow p-3 bg-slate-50 dark:bg-slate-800 rounded-xl text-xs sm:text-sm border-none outline-none focus:ring-2 focus:ring-indigo-500 dark:text-white" placeholder="תאר מה לכתוב (למשל: פרסומת לשירות חדש)..."> <button id="magicWriteBtn" class="p-3 bg-indigo-600 text-white rounded-xl hover:bg-indigo-700 active:scale-95 transition-all flex items-center justify-center min-w-[48px] sm:min-w-[50px]"> <span id="magicIcon">✨</span> <div id="magicLoader" class="loading-spinner hidden"></div> </button> </div> <div class="grid grid-cols-2 sm:grid-cols-3 gap-2"> <button onclick="smartEdit('הפוך את הטקסט ליותר רגוע ונעים')" class="text-[11px] font-bold py-2 px-1 bg-slate-100 dark:bg-slate-800 rounded-lg hover:bg-indigo-50 dark:hover:bg-indigo-950/40 dark:text-slate-200 active:scale-95 transition-all truncate">✨ ריכוך</button> <button onclick="smartEdit('הפוך את הטקסט ליותר שיווקי ואנרגטי')" class="text-[11px] font-bold py-2 px-1 bg-slate-100 dark:bg-slate-800 rounded-lg hover:bg-indigo-50 dark:hover:bg-indigo-950/40 dark:text-slate-200 active:scale-95 transition-all truncate">✨ שיווקי</button> <button onclick="smartEdit('קצר את הטקסט ב-30% מבלי לאבד משמעות')" class="text-[11px] font-bold py-2 px-1 bg-slate-100 dark:bg-slate-800 rounded-lg hover:bg-indigo-50 dark:hover:bg-indigo-950/40 dark:text-slate-200 active:scale-95 transition-all truncate">✨ קיצור</button> <button onclick="translateText()" class="text-[11px] font-bold py-2 px-1 bg-indigo-50 dark:bg-indigo-900/40 text-indigo-700 dark:text-indigo-300 rounded-lg hover:bg-indigo-100 active:scale-95 transition-all truncate">✨ תרגם לאנגלית</button> <button onclick="generatePodcastScript()" class="text-[11px] font-bold py-2 px-1 bg-indigo-50 dark:bg-indigo-900/40 text-indigo-700 dark:text-indigo-300 rounded-lg hover:bg-indigo-100 active:scale-95 transition-all truncate">✨ תסריט פודקאסט</button> <button onclick="summarizeText()" class="text-[11px] font-bold py-2 px-1 bg-indigo-50 dark:bg-indigo-900/40 text-indigo-700 dark:text-indigo-300 rounded-lg hover:bg-indigo-100 active:scale-95 transition-all truncate">✨ סיכום נקודות</button> </div> </div> <div class="card p-4 sm:p-7 rounded-2xl sm:rounded-[2.5rem] shadow-xl border-none"> <div class="flex flex-wrap justify-between items-center gap-2 mb-2"> <label class="text-xs sm:text-sm font-bold text-slate-500 dark:text-slate-400">טקסט לקריינות</label> <button id="analyzeToneBtn" class="text-[10px] sm:text-[11px] font-bold text-indigo-600 bg-indigo-50 dark:bg-indigo-900/30 px-2.5 py-1 rounded-full hover:bg-indigo-100 active:scale-95 transition-all flex items-center gap-1"> <span>✨ התאם סגנון אוטומטית</span> <div id="toneLoader" class="loading-spinner hidden !w-3 !h-3"></div> </button> </div> <textarea id="textInput" rows="5" class="w-full p-3 sm:p-4 bg-slate-50 dark:bg-slate-800/50 rounded-xl sm:rounded-2xl outline-none border-2 border-transparent focus:border-indigo-500 transition-all text-base sm:text-lg dark:text-white resize-y" placeholder="הטקסט יופיע כאן..."></textarea> <div class="flex gap-2 mt-3 mb-5"> <button id="vocalizeBtn" class="flex-1 py-2.5 sm:py-3 bg-slate-50 dark:bg-slate-800 text-slate-600 dark:text-slate-300 rounded-xl text-xs font-bold hover:bg-indigo-50 dark:hover:bg-indigo-900/20 active:scale-95 transition-all flex items-center justify-center gap-2 border border-slate-100 dark:border-slate-700"> <span>✨ ניקוד אוטומטי</span> <div id="vocalizeLoader" class="loading-spinner hidden"></div> </button> </div> <div class="grid grid-cols-1 sm:grid-cols-2 gap-3 sm:gap-4 mb-6"> <div> <label class="text-[10px] font-bold text-slate-400 uppercase mr-1 block mb-1">קול</label> <select id="voiceSelect" class="w-full p-3 bg-slate-100 dark:bg-slate-800 dark:text-white rounded-xl text-xs sm:text-sm font-bold border-none outline-none cursor-pointer"> <optgroup label="גברים (Male)"> <option value="Zephyr">Zephyr (קליל)</option> <option value="Fenrir">Fenrir (עמוק)</option> <option value="Puck">Puck (שובב)</option> <option value="Charon">Charon (סמכותי)</option> <option value="Orus">Orus (קלאסי)</option> <option value="Enceladus">Enceladus (צעיר)</option> <option value="Iapetus">Iapetus (חם)</option> <option value="Algieba">Algieba (נמרץ)</option> <option value="Rasalgethi">Rasalgethi (בוגר)</option> <option value="Achernar">Achernar (יציב)</option> <option value="Alnilam">Alnilam (בהיר)</option> <option value="Schedar">Schedar (נעים)</option> <option value="Achird">Achird (שידור)</option> <option value="Zubenelgenubi">Zubenelgenubi (עמוק מאוד)</option> <option value="Sadachbia">Sadachbia (רך)</option> <option value="Sadaltager">Sadaltager (טבעי)</option> <option value="Sulafat">Sulafat (עוצמתי)</option> </optgroup> <optgroup label="נשים (Female)"> <option value="Kore" selected>Kore (מקצועי)</option> <option value="Leda">Leda (עדין)</option> <option value="Aoede">Aoede (רך)</option> <option value="Callirrhoe">Callirrhoe (רהוט)</option> <option value="Autonoe">Autonoe (אנרגטי)</option> <option value="Umbriel">Umbriel (מסתורי)</option> <option value="Despina">Despina (מהיר)</option> <option value="Erinome">Erinome (ידידותי)</option> <option value="Algenib">Algenib (חדשותי)</option> <option value="Laomedeia">Laomedeia (מרגיע)</option> <option value="Gacrux">Gacrux (אלגנטי)</option> <option value="Pulcherrima">Pulcherrima (עשיר)</option> <option value="Vindemiatrix">Vindemiatrix (סבלני)</option> </optgroup> </select> </div> <div> <label class="text-[10px] font-bold text-slate-400 uppercase mr-1 block mb-1">סגנון והגשה</label> <select id="styleSelect" class="w-full p-3 bg-slate-100 dark:bg-slate-800 dark:text-white rounded-xl text-xs sm:text-sm font-bold border-none outline-none cursor-pointer"> <option value="natural">טבעי (Natural)</option> <option value="cheerful">שמח (Cheerful)</option> <option value="serious">רציני (Serious)</option> <option value="whisper">לחישה (Whisper)</option> <option value="excited">נרגש (Excited)</option> <option value="calm">רגוע (Calm)</option> <option value="authoritative">סמכותי (Authoritative)</option> <option value="friendly">ידידותי (Friendly)</option> <option value="professional">מקצועי (Professional)</option> <option value="storytelling">מספר סיפורים (Storytelling)</option> <option value="shouting">צעקה (Shouting)</option> <option value="terrified">מבועת (Terrified)</option> <option value="sad">עצוב (Sad)</option> <option value="angry">כועס (Angry)</option> <option value="hopeful">מלא תקווה (Hopeful)</option> </select> </div> </div> <button id="generateBtn" class="w-full bg-indigo-600 hover:bg-indigo-700 active:scale-[0.98] text-white font-bold py-3.5 sm:py-4 rounded-xl sm:rounded-2xl shadow-lg transition-all flex items-center justify-center gap-3"> <span id="btnText" class="text-sm sm:text-base">הפק קריינות עכשיו</span> <div id="btnLoader" class="loading-spinner hidden !border-t-white"></div> </button> </div> </div> <div class="lg:col-span-7"> <div class="flex justify-between items-center mb-4"> <h2 class="text-lg sm:text-xl font-bold dark:text-white">הקלטות אחרונות</h2> <button id="clearTracks" class="text-xs text-slate-400 hover:text-red-500 font-bold transition-colors">נקה הכל</button> </div> <div id="tracksContainer" class="space-y-3 sm:space-y-4"> <div id="noTracks" class="text-center py-16 sm:py-24 border-2 border-dashed border-slate-300 dark:border-slate-800 rounded-2xl sm:rounded-[2.5rem] text-slate-400 font-bold text-sm sm:text-base"> היסטוריית הקריינות שלך תישמר כאן </div> </div> </div> </div> </div> <div id="toast" class="fixed bottom-4 sm:bottom-8 left-4 sm:left-8 right-4 sm:right-auto px-4 sm:px-6 py-3 rounded-xl shadow-2xl opacity-0 transition-all pointer-events-none z-50 transform translate-y-4 flex items-center justify-center sm:justify-start gap-2 max-w-md"> <span id="toastIcon"></span> <span id="toastMessage" class="text-xs sm:text-sm font-semibold"></span> </div> <script> // Global State & Config let currentApiKey = localStorage.getItem('gemini_api_key') || ""; const modelText = "gemini-3.5-flash"; const modelAudio = "gemini-2.5-flash-preview-tts"; const els = { textInput: document.getElementById('textInput'), promptInput: document.getElementById('promptInput'), generateBtn: document.getElementById('generateBtn'), magicWriteBtn: document.getElementById('magicWriteBtn'), analyzeToneBtn: document.getElementById('analyzeToneBtn'), voiceSelect: document.getElementById('voiceSelect'), styleSelect: document.getElementById('styleSelect'), tracksContainer: document.getElementById('tracksContainer'), noTracks: document.getElementById('noTracks'), body: document.getElementById('bodyTag'), toast: document.getElementById('toast'), toastMessage: document.getElementById('toastMessage'), // API Key elements apiKeyBtn: document.getElementById('apiKeyBtn'), apiKeyPopover: document.getElementById('apiKeyPopover'), apiKeyInput: document.getElementById('apiKeyInput'), saveApiKey: document.getElementById('saveApiKey'), clearApiKey: document.getElementById('clearApiKey'), apiKeyStatus: document.getElementById('apiKeyStatus') }; // Initialize UI function updateApiStatus() { if (currentApiKey) { els.apiKeyStatus.innerText = "מפתח מוגדר ✅"; els.apiKeyStatus.classList.add('text-green-600'); els.apiKeyInput.value = currentApiKey; } else { els.apiKeyStatus.innerText = "הגדר מפתח ⚠️"; els.apiKeyStatus.classList.remove('text-green-600'); els.apiKeyInput.value = ""; } } updateApiStatus(); // API Key Popover Toggle els.apiKeyBtn.onclick = (e) => { e.stopPropagation(); els.apiKeyPopover.classList.toggle('hidden'); }; els.saveApiKey.onclick = () => { const key = els.apiKeyInput.value.trim(); if (key) { currentApiKey = key; localStorage.setItem('gemini_api_key', key); updateApiStatus(); els.apiKeyPopover.classList.add('hidden'); showToast("מפתח ה-API נשמר בהצלחה", "success"); } }; els.clearApiKey.onclick = () => { currentApiKey = ""; localStorage.removeItem('gemini_api_key'); updateApiStatus(); showToast("מפתח ה-API נמחק"); }; document.addEventListener('click', () => els.apiKeyPopover.classList.add('hidden')); els.apiKeyPopover.onclick = (e) => e.stopPropagation(); // Utility: API Caller with retry logic async function apiCall(model, payload, retries = 5) { if (!currentApiKey) { showToast("אנא הגדר מפתח API בתפריט למעלה"); els.apiKeyPopover.classList.remove('hidden'); throw new Error("Missing API Key"); } const url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:${model.includes('tts') ? 'generateContent' : 'generateContent'}?key=${currentApiKey}`; for (let i = 0; i < retries; i++) { try { const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); const data = await response.json(); if (response.ok) return data; if (response.status === 429) { await new Promise(r => setTimeout(r, Math.pow(2, i) * 1000)); } else if (response.status === 403 || response.status === 401) { showToast("מפתח ה-API אינו תקין"); throw new Error("Invalid API Key"); } else { throw new Error(data.error?.message || "Communication Error"); } } catch (e) { if (i === retries - 1) throw e; } } } function showToast(msg, type = 'error') { els.toastMessage.innerText = msg; els.toast.className = `fixed bottom-4 sm:bottom-8 left-4 sm:left-8 right-4 sm:right-auto px-4 sm:px-6 py-3 rounded-xl shadow-2xl transition-all z-50 transform translate-y-0 opacity-100 ${type === 'error' ? 'bg-red-600' : 'bg-indigo-600'} text-white max-w-md flex items-center justify-center sm:justify-start gap-2`; setTimeout(() => { els.toast.classList.add('opacity-0', 'translate-y-4'); }, 4000); } // --- LLM Features --- // ✨ Magic Write els.magicWriteBtn.onclick = async () => { const prompt = els.promptInput.value.trim(); if (!prompt) return showToast("תאר מה לכתוב בתיבה"); toggleLoader('magic', true); try { const data = await apiCall(modelText, { contents: [{ parts: [{ text: `כתוב סקריפט קצר ומקצועי לקריינות בעברית עבור הנושא הבא: "${prompt}". החזר רק את הטקסט של הסקריפט ללא הסברים או כותרות.` }] }] }); const result = data.candidates?.[0]?.content?.parts?.[0]?.text; if (result) els.textInput.value = result.trim(); } catch (e) { if(e.message !== "Missing API Key") showToast(e.message); } toggleLoader('magic', false); }; // ✨ Smart Edit async function smartEdit(instruction) { const text = els.textInput.value.trim(); if (!text) return showToast("הכנס קודם טקסט לתיבה"); showToast("מעבד טקסט...", "success"); try { const data = await apiCall(modelText, { contents: [{ parts: [{ text: `${instruction} על הטקסט הבא: "${text}". החזר רק את הטקסט המעובד.` }] }] }); const result = data.candidates?.[0]?.content?.parts?.[0]?.text; if (result) els.textInput.value = result.trim(); } catch (e) { if(e.message !== "Missing API Key") showToast(e.message); } } // ✨ Translate async function translateText() { const text = els.textInput.value.trim(); if (!text) return showToast("אין טקסט לתרגום"); showToast("מתרגם לאנגלית...", "success"); try { const data = await apiCall(modelText, { contents: [{ parts: [{ text: `Translate the following text to fluent English suitable for narration: "${text}". Return only the translation.` }] }] }); const result = data.candidates?.[0]?.content?.parts?.[0]?.text; if (result) els.textInput.value = result.trim(); } catch (e) { if(e.message !== "Missing API Key") showToast(e.message); } } // ✨ Podcast Script async function generatePodcastScript() { const topic = els.promptInput.value.trim() || "Technology"; showToast("יוצר תסריט פודקאסט...", "success"); try { const data = await apiCall(modelText, { contents: [{ parts: [{ text: `Create a short podcast script dialogue between two people about: "${topic}". Return only the dialogue in Hebrew.` }] }] }); const result = data.candidates?.[0]?.content?.parts?.[0]?.text; if (result) els.textInput.value = result.trim(); } catch (e) { if(e.message !== "Missing API Key") showToast(e.message); } } // ✨ Summarize async function summarizeText() { const text = els.textInput.value.trim(); if (!text) return showToast("אין טקסט לסיכום"); showToast("מסכם לנקודות...", "success"); try { const data = await apiCall(modelText, { contents: [{ parts: [{ text: `Summarize the following text into 3 clear key points for narration in Hebrew: "${text}".` }] }] }); const result = data.candidates?.[0]?.content?.parts?.[0]?.text; if (result) els.textInput.value = result.trim(); } catch (e) { if(e.message !== "Missing API Key") showToast(e.message); } } // ✨ Tone Analysis els.analyzeToneBtn.onclick = async () => { const text = els.textInput.value.trim(); if (!text) return showToast("אין טקסט לניתוח"); toggleLoader('tone', true); try { const data = await apiCall(modelText, { contents: [{ parts: [{ text: `Analyze the sentiment of the following text and pick the best speaking style from this list: (natural, cheerful, serious, whisper, excited, calm, authoritative, friendly, professional, storytelling, shouting, terrified, sad, angry, hopeful). Return ONLY the English word. Text: "${text}"` }] }] }); const choice = data.candidates?.[0]?.content?.parts?.[0]?.text?.trim().toLowerCase(); if (choice) { const cleanChoice = choice.replace(/[^a-z]/g, ''); const option = Array.from(els.styleSelect.options).find(o => o.value === cleanChoice); if (option) { els.styleSelect.value = cleanChoice; showToast(`הסגנון הותאם ל: ${option.text}`, "success"); } } } catch (e) { if(e.message !== "Missing API Key") showToast(e.message); } toggleLoader('tone', false); }; // ✨ Vocalization (Nikud) document.getElementById('vocalizeBtn').onclick = async () => { const text = els.textInput.value.trim(); if (!text) return showToast("אין טקסט לניקוד"); toggleLoader('vocalize', true); try { const data = await apiCall(modelText, { contents: [{ parts: [{ text: `הוסף ניקוד דקדוקי מלא ומדויק לטקסט הבא בעברית: "${text}". החזר רק את הטקסט המנוקד.` }] }] }); const result = data.candidates?.[0]?.content?.parts?.[0]?.text; if (result) els.textInput.value = result.trim(); } catch (e) { if(e.message !== "Missing API Key") showToast(e.message); } toggleLoader('vocalize', false); }; // --- TTS Core --- els.generateBtn.onclick = async () => { const text = els.textInput.value.trim(); if (!text) return showToast("הכנס טקסט לקריינות"); toggleLoader('btn', true); try { const result = await apiCall(modelAudio, { contents: [{ parts: [{ text: `Say in a ${els.styleSelect.value} style: ${text}` }] }], generationConfig: { responseModalities: ["AUDIO"], speechConfig: { voiceConfig: { prebuiltVoiceConfig: { voiceName: els.voiceSelect.value } } } } }); const pcmData = result.candidates?.[0]?.content?.parts?.[0]?.inlineData?.data; const mimeType = result.candidates?.[0]?.content?.parts?.[0]?.inlineData?.mimeType || ""; const sampleRate = parseInt(mimeType.split('rate=')[1]) || 24000; if (pcmData) { const blob = pcmToWav(pcmData, sampleRate); addTrack(blob, text.substring(0, 30)); showToast("קריינות הופקה בהצלחה!", "success"); } } catch (e) { if(e.message !== "Missing API Key") showToast(e.message); } toggleLoader('btn', false); }; // --- Helpers --- function toggleLoader(key, show) { const l = document.getElementById(key + 'Loader'); const i = document.getElementById(key + 'Icon'); const t = document.getElementById(key + 'Text'); if (l) l.classList.toggle('hidden', !show); if (i) i.classList.toggle('hidden', show); if (t) t.innerText = show ? "מעבד..." : "הפק קריינות עכשיו"; if (key === 'btn') els.generateBtn.disabled = show; } function pcmToWav(base64, rate) { const binary = atob(base64); const bytes = new Uint8Array(binary.length); for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i); const header = new ArrayBuffer(44); const v = new DataView(header); const s = (off, str) => { for (let i = 0; i < str.length; i++) v.setUint8(off + i, str.charCodeAt(i)); }; s(0, 'RIFF'); v.setUint32(4, 36 + bytes.length, true); s(8, 'WAVE'); s(12, 'fmt '); v.setUint32(16, 16, true); v.setUint16(20, 1, true); v.setUint16(22, 1, true); v.setUint32(24, rate, true); v.setUint32(28, rate * 2, true); v.setUint16(32, 2, true); v.setUint16(34, 16, true); s(36, 'data'); v.setUint32(40, bytes.length, true); return new Blob([header, bytes], { type: 'audio/wav' }); } function addTrack(blob, title) { els.noTracks.classList.add('hidden'); const url = URL.createObjectURL(blob); const div = document.createElement('div'); div.className = "card p-3 sm:p-4 rounded-xl sm:rounded-2xl flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3 shadow-sm border-slate-100 dark:border-slate-800"; div.innerHTML = ` <div class="flex-grow w-full sm:w-auto"> <div class="font-bold text-xs sm:text-sm truncate dark:text-white">${title}...</div> <div class="text-[10px] text-slate-400 mt-0.5">${els.voiceSelect.value} | ${els.styleSelect.value}</div> </div> <div class="flex items-center justify-between sm:justify-end w-full sm:w-auto gap-2 border-t sm:border-t-0 pt-2 sm:pt-0 border-slate-100 dark:border-slate-800"> <audio src="${url}" controls class="w-full sm:w-48"></audio> <a href="${url}" download="voice_${Date.now()}.wav" class="p-2 hover:bg-indigo-50 dark:hover:bg-slate-700 rounded-lg text-indigo-600 flex-shrink-0"> <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/></svg> </a> </div> `; els.tracksContainer.prepend(div); } document.getElementById('toggleDark').onclick = () => els.body.classList.toggle('dark-mode'); document.getElementById('clearTracks').onclick = () => { els.tracksContainer.querySelectorAll('.card').forEach(c => c.remove()); els.noTracks.classList.remove('hidden'); }; </script> </body> </html>
  • רשימה לבנה

    שאלות ועזרה הדדית
    29
    0 הצבעות
    29 פוסטים
    77 צפיות
    מ
    אכן יש בעיה באשף גם אני ניסתי כעת הפיתרון הוא להעלות קובץ ידני לשלוחה [או להתפלל לתיקון התקלה באשף ]
  • אחרי הודעת המערכת

    שאלות ועזרה הדדית
    47
    0 הצבעות
    47 פוסטים
    48 צפיות
    פ
    Spoiler > @פלוס כתב: למאסטר: 093130897. אין אפשרות לנתב לזה מימות המשיח כנראה חסום בוועד בני תורה
  • זהוי מספר טלפון

    שאלות ועזרה הדדית
    1
    0 הצבעות
    1 פוסטים
    11 צפיות
    אין תגובות
  • 0 הצבעות
    5 פוסטים
    12 צפיות
    נ
    @דודי-א כתב: שלום וברכה ראיתי שיש את האופציה אבל לא הבנתי בדיוק איך עושים את זה יש לי 2 שלוחות של השמעת קבצים ואני רוצה ששלוחה 3 תשמיע את הקבצים משתיהם ושתשמיע לפי סדר שהאחרון שהוקלט יושמע ראשון הבנתי שצריך להשתמש בהגדרה folder_to_play= אשמח להסבר מדויק תודה רבה https://f2.freeivr.co.il/post/56978
  • 0 הצבעות
    4 פוסטים
    23 צפיות
    נ
    @חסיד-חזק יש לי שרת ישן ועים מעדקנים טקסת שם למעזין אז זה משנה קול
  • 0 הצבעות
    20 פוסטים
    376 צפיות
    א
    @1668 אשמח שתשנה את הקישור למעלה ל-קישור הזה.. תודה רבה...
  • 0 הצבעות
    3 פוסטים
    40 צפיות
    ז
    @טבריה להביא לאן? מה אתה שואל?
  • 0 הצבעות
    214 פוסטים
    6k צפיות
    ה
    עשיתי את כל ההגדרות ולא הצלחתי לרשום את המערכת
  • הודעה אישית / ניהולו 🪧📣👨‍💼

    לא נפתר עזרה הדדית למשתמשים מתקדמים
    25
    0 הצבעות
    25 פוסטים
    134 צפיות
    ש
    @פלוס תנסה להיכנס ישר ל B בלי לעבור ב A תבדוק אם זה משמיע לך הודעות של אותו מספר
  • 0 הצבעות
    5 פוסטים
    42 צפיות
    נ
    @ARISH יש לי 079 זה טוב
  • מילוי טופס מקוון של  Google Forms דרך הקו

    בקשות לפיתוח
    36
    0 הצבעות
    36 פוסטים
    217 צפיות
    ח
    @S.I.Z תוכל לבדוק את המערכת באתר הישן למטה יש כיתוב קטן לגבי מספר חדש תוכל לקנות בשירות הלקוחות מספר מהמערכת הישנה ב-29.5 ש"ח
  • איכות השמע בשעות מסוימות

    שאלות ועזרה הדדית
    8
    1 הצבעות
    8 פוסטים
    54 צפיות
    ה
    אני חושב שמערכות שמשלמות כסף עובדות הרבה יותר טוב! עובדה - ברוב מוחלט של התקלות כל הקוים "הגדולים" עובדים
  • 11 הצבעות
    15 פוסטים
    212 צפיות
    ח
    @דוד_מלך_ישראל בהחלט מהפכני! יישר כוח! שאלות/ בקשות/ הצעות: א.לאחר ביצוע פעולת עריכה, הקובץ הערוך מושמע מההתחלה. הייתי שמחה שהוא יושמע מנקודת העצירה. ב.אם אפשר, הייתי שמחה שתתוסף "ביטול פעולה אחרונה"- מעין ctrl z ג. לאחר שמקישים את הסיסמה, מושמע תפריט המקשים. אם אפשר להוסיף הקשה שתחזיר אותי להאזנה לקובץ ללא ביצוע אף פעולה? שוב, יישר כוח גדול!
  • 0 הצבעות
    30 פוסטים
    238 צפיות
    מ
    @שלוחה-404 כן אבל אין לי את המייל שלך אז אולי תשלח לי מייל ואז אוכל להשיב לך
  • 0 הצבעות
    5 פוסטים
    52 צפיות
    ה
    @פיתה הגדרתי "שרות שיחה חוזרת" ואם לא מספיקים לענות המערכת המערכת משאירה הודעה בתא הקולי יש אפשרות לבטל? תודה רבה.