Created
July 14, 2025 11:59
-
-
Save aditnanda/b282ab215def06d118500ef63fdfd5ae to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Text-to-Speech Sederhana (ID)</title> | |
| <style> | |
| body { | |
| font-family: sans-serif; | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| min-height: 100vh; | |
| background-color: #f0f0f0; | |
| margin: 0; | |
| } | |
| .container { | |
| background-color: white; | |
| padding: 30px; | |
| border-radius: 8px; | |
| box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); | |
| text-align: center; | |
| } | |
| textarea { | |
| width: 100%; | |
| height: 100px; | |
| margin-bottom: 15px; | |
| padding: 10px; | |
| border: 1px solid #ccc; | |
| border-radius: 4px; | |
| font-size: 16px; | |
| resize: vertical; | |
| } | |
| button { | |
| padding: 10px 20px; | |
| background-color: #007bff; | |
| color: white; | |
| border: none; | |
| border-radius: 4px; | |
| cursor: pointer; | |
| font-size: 16px; | |
| transition: background-color 0.3s ease; | |
| } | |
| button:hover { | |
| background-color: #0056b3; | |
| } | |
| #voiceSelect { | |
| width: 100%; | |
| padding: 8px; | |
| margin-bottom: 15px; | |
| border: 1px solid #ccc; | |
| border-radius: 4px; | |
| font-size: 16px; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <h1>Text-to-Speech Bahasa Indonesia</h1> | |
| <form> | |
| <label for="textInput">Masukkan teks Anda di sini:</label><br> | |
| <textarea id="textInput" placeholder="Ketik sesuatu dalam bahasa Indonesia..."></textarea><br> | |
| <label for="voiceSelect">Pilih Suara:</label><br> | |
| <select id="voiceSelect"></select><br><br> | |
| <button type="button" id="speakButton">Baca Teks</button> | |
| </form> | |
| </div> | |
| <script> | |
| const textInput = document.getElementById('textInput'); | |
| const speakButton = document.getElementById('speakButton'); | |
| const voiceSelect = document.getElementById('voiceSelect'); | |
| let voices = []; | |
| // Fungsi untuk mengisi pilihan suara | |
| function populateVoiceList() { | |
| voices = window.speechSynthesis.getVoices(); | |
| voiceSelect.innerHTML = ''; // Kosongkan opsi sebelumnya | |
| let idVoiceFound = false; | |
| voices.forEach((voice) => { | |
| const option = document.createElement('option'); | |
| option.textContent = `${voice.name} (${voice.lang})`; | |
| if (voice.default) { | |
| option.textContent += ' -- Default'; | |
| } | |
| option.setAttribute('data-lang', voice.lang); | |
| option.setAttribute('data-name', voice.name); | |
| voiceSelect.appendChild(option); | |
| // Otomatis pilih suara Indonesia jika ditemukan | |
| if (voice.lang === 'id-ID' && !idVoiceFound) { | |
| option.selected = true; | |
| idVoiceFound = true; | |
| } | |
| }); | |
| // Jika tidak ada suara ID-ID yang ditemukan, coba default atau yang pertama | |
| if (!idVoiceFound && voices.length > 0) { | |
| // Coba temukan suara default | |
| const defaultVoice = voices.find(v => v.default); | |
| if (defaultVoice) { | |
| voiceSelect.value = `${defaultVoice.name} (${defaultVoice.lang})`; | |
| } else { | |
| // Jika tidak ada default, pilih yang pertama | |
| voiceSelect.selectedIndex = 0; | |
| } | |
| } | |
| } | |
| // Event listener untuk saat suara tersedia | |
| if (speechSynthesis.onvoiceschanged !== undefined) { | |
| speechSynthesis.onvoiceschanged = populateVoiceList; | |
| } else { | |
| // Panggil langsung jika event sudah fired (terkadang terjadi) | |
| populateVoiceList(); | |
| } | |
| speakButton.addEventListener('click', () => { | |
| const textToSpeak = textInput.value; | |
| if ('speechSynthesis' in window) { | |
| const utterance = new SpeechSynthesisUtterance(textToSpeak); | |
| // Set bahasa untuk utterance (penting!) | |
| utterance.lang = 'id-ID'; | |
| // Dapatkan suara yang dipilih dari dropdown | |
| const selectedOption = voiceSelect.selectedOptions[0]; | |
| const selectedVoiceName = selectedOption.getAttribute('data-name'); | |
| const selectedVoice = voices.find(voice => voice.name === selectedVoiceName); | |
| if (selectedVoice) { | |
| utterance.voice = selectedVoice; | |
| } else { | |
| console.warn('Suara yang dipilih tidak ditemukan, menggunakan suara default.'); | |
| } | |
| utterance.pitch = 1; | |
| utterance.rate = 1; | |
| utterance.volume = 1; | |
| window.speechSynthesis.speak(utterance); | |
| } else { | |
| alert('Maaf, browser Anda tidak mendukung Text-to-Speech API.'); | |
| } | |
| }); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment