אתר "קולות" – יצירת קרינות ותמלול AI בקלות
-
@המתכנת-הראשי תוכל להביא את הקוד של הקובץ? אני לא מצליח להוריד את העמוד HTML שצירפת
תודה
-
אני רוצה לעלות אותו לאחסון אצלי תחת tts.link.tz
-
@שולי אני מקווה שעליתי על הבעיה. בגלל שהתעסקתי עכשיו בטמרטורה של הקול כנראה שהבעיה לא הייתה במפתח שלך, אלא במנגנון קיבוע הטון: במודלי קול של AI, קיבוע טמפרטורה לאפס גרם למודל של גוגל לקרוס אל "טוקן שקט", וההגדרה הזו נשארה שמורה בדפדפן גם אחרי מחיקת המפתח.
עכשיו תיקנתי את זה בשרת: שיניתי את מנגנון קיבוע הטון לשימוש בגרעין קולי קבוע (Seed) עם טמפרטורה אקוסטית מאוזנת שמבטיחה שמע מלא, חזק וברור.
תעשה עכשיו רענון מלא של הדף (לחץ Ctrl + F5 כדי לנקות את המטמון הישן).
ותנסה להפיק עכשיו קובץ שמע (עם מפתח או בלעדיו) – השמע יופק מיד בצורה חלקה וברורה בעז"ה!בנוגע לקובץ HTML שיחקתי בו עכשיו ושיניתי בו כמה דברים לכן מחקתי את הקובץ מפה ועדיין לא העליתי קובץ חדש, תוריד את הקובץ מהאתר בלשונית "מצב פשוט ומהיר" שמה למעלה יש אפשרות "קובץ HTML עצמאי" תלחץ עליו וזה יוריד.
-
@שולי תיקנתי את הקישור למעלה הקישור החדש הוא https://ais-pre-hwh53agkcctwmzdhgq5ecq-703503104887.europe-west2.run.app/simple-tts.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>יצירת שמע פשוטה ועקבית (Gemini TTS)</title> <style> :root { --primary: #f59e0b; --primary-hover: #d97706; --bg: #0f172a; --card-bg: #1e293b; --border: #334155; --text: #f8fafc; --text-muted: #94a3b8; } * { box-sizing: border-box; margin: 0; padding: 0; font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; } body { background-color: var(--bg); color: var(--text); display: flex; justify-content: center; align-items: center; min-height: 100vh; padding: 20px; } .container { background-color: var(--card-bg); border: 1px solid var(--border); border-radius: 16px; width: 100%; max-width: 600px; padding: 28px; box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.5); } h1 { font-size: 20px; margin-bottom: 6px; color: var(--primary); display: flex; align-items: center; gap: 8px; } p.subtitle { font-size: 13px; color: var(--text-muted); margin-bottom: 22px; } .form-group { margin-bottom: 16px; } label { display: block; font-size: 13px; font-weight: 600; margin-bottom: 6px; color: #e2e8f0; } input[type="text"], input[type="password"], textarea, select { width: 100%; padding: 10px 14px; background-color: #0f172a; border: 1px solid var(--border); border-radius: 10px; color: #fff; font-size: 14px; outline: none; transition: border-color 0.2s; } input:focus, textarea:focus, select:focus { border-color: var(--primary); } textarea { resize: vertical; min-height: 110px; } .grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; } .lock-box { background: rgba(245, 158, 11, 0.1); border: 1px solid rgba(245, 158, 11, 0.3); padding: 12px 14px; border-radius: 10px; display: flex; align-items: center; gap: 10px; cursor: pointer; margin-bottom: 18px; } .lock-box input[type="checkbox"] { width: 18px; height: 18px; accent-color: var(--primary); cursor: pointer; } .lock-text { font-size: 13px; line-height: 1.3; } .lock-text strong { color: var(--primary); display: block; } .lock-text small { color: var(--text-muted); font-size: 11px; } button.btn-primary { width: 100%; background: var(--primary); color: #0f172a; font-weight: 700; font-size: 15px; padding: 12px; border: none; border-radius: 10px; cursor: pointer; transition: background 0.2s, transform 0.1s; } button.btn-primary:hover { background: var(--primary-hover); } button.btn-primary:active { transform: scale(0.99); } button.btn-primary:disabled { opacity: 0.5; cursor: not-allowed; } .player-area { margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--border); display: none; } audio { width: 100%; margin-bottom: 12px; } .download-btn { display: inline-block; text-align: center; width: 100%; background: #334155; color: #fff; padding: 10px; border-radius: 8px; text-decoration: none; font-size: 13px; font-weight: 600; transition: background 0.2s; } .download-btn:hover { background: #475569; } .status { font-size: 12px; margin-top: 10px; text-align: center; color: var(--text-muted); } </style> </head> <body> <div class="container"> <h1>🔊 יצירת שמע פשוטה ועקבית (Gemini TTS)</h1> <p class="subtitle">קובץ HTML עצמאי וקל ליצירת קרינות נקייה עם נעילת טון וקצב קבוע</p> <div class="form-group"> <label for="apiKey">מפתח Gemini API:</label> <input type="password" id="apiKey" placeholder="הדבק כאן מפתח מגוגל AI Studio (AIzaSy...)"> </div> <div class="form-group"> <label for="textInput">טקסט להקראה בעברית:</label> <textarea id="textInput" placeholder="הקלד כאן את הטקסט שברצונך להקריא..."></textarea> </div> <div class="grid"> <div class="form-group"> <label for="voiceSelect">קול קריין:</label> <select id="voiceSelect"> <option value="Puck">איתן (Puck) - גברי צעיר/קצבי</option> <option value="Charon">אלון (Charon) - גברי עמוק/בטוח</option> <option value="Kore" selected>רות (Kore) - נשי חם/טבעי</option> <option value="Fenrir">יהונתן (Fenrir) - גברי סמכותי</option> <option value="Aoede">מאיה (Aoede) - נשי צלול</option> <option value="Zephyr">דן (Zephyr) - גברי רגוע</option> </select> </div> <div class="form-group"> <label for="speedSelect">מהירות:</label> <select id="speedSelect"> <option value="0.8">0.8x (איטי ומדוד)</option> <option value="1.0" selected>1.0x (מהירות רגילה)</option> <option value="1.2">1.2x (קצבי ומהיר)</option> </select> </div> </div> <!-- מנגנון נעילת טון וקצב עקבי --> <label class="lock-box"> <input type="checkbox" id="lockTone" checked> <div class="lock-text"> <strong>🔒 קיבוע טון וסגנון קבוע (Consistent Tone - Zero Jitter)</strong> <small>משתמש ב-Seed קבוע וטמפרטורה יציבה כדי שכל הפקה תישמע בדיוק באותו טון</small> </div> </label> <button class="btn-primary" id="generateBtn" onclick="generateSpeech()">הפק שמע עכשיו</button> <div class="status" id="statusText"></div> <div class="player-area" id="playerArea"> <audio id="audioElement" controls></audio> <a href="#" class="download-btn" id="downloadBtn" download="speech.wav">הורד קובץ שמע WAV</a> </div> </div> <script> // שמירת מפתח בזיכרון הדפדפן לנוחות const savedKey = localStorage.getItem('gemini_simple_tts_key'); if (savedKey) document.getElementById('apiKey').value = savedKey; function pcmToWav(pcmData, sampleRate = 24000, numChannels = 1, bitsPerSample = 16) { if (pcmData.length >= 4 && String.fromCharCode(...pcmData.slice(0, 4)) === 'RIFF') { return pcmData; } const byteRate = (sampleRate * numChannels * bitsPerSample) / 8; const blockAlign = (numChannels * bitsPerSample) / 8; const dataSize = pcmData.length; const buffer = new ArrayBuffer(44 + dataSize); const view = new DataView(buffer); function writeString(offset, string) { for (let i = 0; i < string.length; i++) { view.setUint8(offset + i, string.charCodeAt(i)); } } writeString(0, 'RIFF'); view.setUint32(4, 36 + dataSize, true); writeString(8, 'WAVE'); writeString(12, 'fmt '); view.setUint32(16, 16, true); view.setUint16(20, 1, true); // PCM view.setUint16(22, numChannels, true); view.setUint32(24, sampleRate, true); view.setUint32(28, byteRate, true); view.setUint16(32, blockAlign, true); view.setUint16(34, bitsPerSample, true); writeString(36, 'data'); view.setUint32(40, dataSize, true); new Uint8Array(buffer, 44).set(pcmData); return new Uint8Array(buffer); } async function generateSpeech() { const apiKey = document.getElementById('apiKey').value.trim(); const text = document.getElementById('textInput').value.trim(); const voice = document.getElementById('voiceSelect').value; const speed = document.getElementById('speedSelect').value; const lockTone = document.getElementById('lockTone').checked; const statusText = document.getElementById('statusText'); const generateBtn = document.getElementById('generateBtn'); const playerArea = document.getElementById('playerArea'); const audioElement = document.getElementById('audioElement'); const downloadBtn = document.getElementById('downloadBtn'); if (!apiKey) { alert('נא להזין מפתח Gemini API'); return; } if (!text) { alert('נא להזין טקסט להקראה'); return; } localStorage.setItem('gemini_simple_tts_key', apiKey); generateBtn.disabled = true; statusText.innerText = 'מפיק קרינות מול שרתי Google Gemini... אנא המתן'; playerArea.style.display = 'none'; try { // Deterministic seed for consistency const seed = Math.abs(voice.split('').reduce((acc, c) => acc * 31 + c.charCodeAt(0), 0) + Math.round(Number(speed) * 100)) % 2147483647; const requestBody = { contents: [{ parts: [{ text }] }], generationConfig: { responseModalities: ["AUDIO"], temperature: lockTone ? 0.55 : 0.7, ...(lockTone ? { seed: seed } : {}), speechConfig: { voiceConfig: { prebuiltVoiceConfig: { voiceName: voice } } } } }; // מודל TTS יציב וייעודי של גוגל const models = ['gemini-3.8-flash-lite-tts', 'gemini-3.8-flash-tts', 'gemini-2.5-flash-preview-tts']; let base64Audio = null; let lastError = null; for (const model of models) { try { const res = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${apiKey}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(requestBody) }); const data = await res.json(); if (data?.candidates?.[0]?.content?.parts?.[0]?.inlineData?.data) { base64Audio = data.candidates[0].content.parts[0].inlineData.data; break; } if (data.error) { lastError = data.error.message; } } catch (e) { lastError = e.message; } } if (!base64Audio) { throw new Error(lastError || 'לא התקבלו נתוני שמע מגוגל. בדוק את תקינות המפתח.'); } // פיענוח לקובץ WAV const binaryString = window.atob(base64Audio); const len = binaryString.length; const bytes = new Uint8Array(len); for (let i = 0; i < len; i++) { bytes[i] = binaryString.charCodeAt(i); } const wavBytes = pcmToWav(bytes, 24000, 1, 16); const blob = new Blob([wavBytes], { type: 'audio/wav' }); const blobUrl = URL.createObjectURL(blob); audioElement.src = blobUrl; downloadBtn.href = blobUrl; playerArea.style.display = 'block'; statusText.innerText = 'הקרינות הופקה בהצלחה!'; audioElement.play().catch(() => {}); } catch (err) { statusText.innerText = 'שגיאה: ' + err.message; } finally { generateBtn.disabled = false; } } </script> </body> </html> -
- למה הוא מייצר לי קבצים רק של שניה או שתי שניות ולא יותר
- בכל הקלטה הוא קצת משנה את הקול בסגנון שונה
לא הכנסתי מפתח API כי בנטפרי אי אפשר להוציא מפתחות API
-
@יענקי-פולק
אפשר לנעול את הקול לקול אחיד
תראה כאן -
- תודה על המענה אבל קודם כל אני צריך שהוא יעשה לי קבצים שלמים
- יכול להיות שזה קשור בגלל שלא הכנסתי מפתח API
- האם יש לך פיתרון להוציא בנטפרי מפתחות API
-
@יענקי-פולק בנוגע לקבצים של ה2 שניות זה בגלל שאין לך מפתח API וזה קשור למפתחות של גוגל שיש עליהם מגבלה, הפיתרון היחיד לזה זה הוצאת מפתח API.
בנוגע לשינוי בקול צריך ללחוץ על "נעל טון זה" -
יענקי-פולק כתב:
האם יש לך פיתרון להוציא בנטפרי מפתחות API
-
@יענקי-פולק בעיקרון יש גישה לנטפרי להוציא מפתח זה הגבלות קהילה שחוסמות תנסה לפתוח או במחשב אחר
-
@שלוחה-404
תכל'ס אני יושב בחדר מחשבים במסלול הכי שמור של נטפרי ואין לי גישה למחשב אחר, האם יש לך פיתרון להוציא מפתחות API -
הגירסה המקוצרת זמינה בכתובת: https://tts.link.tz
-
@שולי
עדיין לא נבדק בנטפרי אם אתה יכול לשלוח בקשה לבדיקה אשמח מאוד -
@יענקי-פולק אין לי נטפרי
-
@יענקי-פולק שלחתי לבדיקה
שלום! נראה שהשיחה הזו מעניינת אותך, אבל עדיין אין לך חשבון.
נמאס לכם לגלול בין אותם הפוסטים בכל ביקור? כשנרשמים לחשבון, תמיד תחזרו בדיוק למקום שבו הייתם קודם, ותוכלו לבחור לקבל התראות על תגובות חדשות (בין אם במייל, ובין אם בהתראת פוש). תוכלו גם לשמור סימניות ולפרגן ב-upvote לפוסטים כדי להביע הערכה לחברי קהילה אחרים.
בעזרת התרומה שלך, הפוסט הזה יכול להיות אפילו טוב יותר 💗
הרשמה התחברות