| |
| fetch('BhagvatGlory.json') |
| .then(response => response.json()) |
| .then(jsonData => initializeApp(jsonData)) |
| .catch(error => console.error('Error loading JSON:', error)); |
|
|
| const skandaList = document.getElementById("skanda-list"); |
| const chapterTitle = document.getElementById("chapter-title"); |
| const slokeContainer = document.getElementById("sloke-container"); |
|
|
| function initializeApp(data) { |
| |
| const skandaItem = document.createElement("li"); |
| skandaItem.textContent = data.skandaTitle; |
|
|
| const chapterList = document.createElement("ul"); |
| data.chapters.forEach((chapter, chapterIndex) => { |
| const chapterItem = document.createElement("li"); |
| chapterItem.textContent = chapter.chapterTitle; |
| chapterItem.onclick = () => displayChapter(chapter); |
| chapterList.appendChild(chapterItem); |
| }); |
|
|
| skandaItem.appendChild(chapterList); |
| skandaList.appendChild(skandaItem); |
| } |
|
|
| |
| function displayChapter(chapter) { |
| chapterTitle.textContent = chapter.chapterTitle; |
|
|
| slokeContainer.innerHTML = ""; |
| const slokes = chapter.slokes |
| .replace(/श्लोक\s*\d+:/g, "") |
| .trim() |
| .split("\n"); |
|
|
| slokes.forEach((sloke, index) => { |
| const slokeItem = document.createElement("div"); |
| slokeItem.className = "sloke-item"; |
|
|
| const slokeText = document.createElement("p"); |
| slokeText.textContent = sloke.trim(); |
|
|
| const speakButton = document.createElement("button"); |
| speakButton.textContent = "Speak"; |
| speakButton.onclick = () => speakSloke(sloke.trim()); |
|
|
| const downloadButton = document.createElement("button"); |
| downloadButton.textContent = "Download"; |
| downloadButton.onclick = () => downloadAudio(sloke.trim(), `sloke-${index + 1}.wav`); |
|
|
| slokeItem.appendChild(slokeText); |
| slokeItem.appendChild(speakButton); |
| slokeItem.appendChild(downloadButton); |
|
|
| slokeContainer.appendChild(slokeItem); |
| }); |
| } |
|
|
|
|
| |
| function speakSloke(text) { |
| |
| const normalizedText = text |
| .normalize("NFC") |
| .replace(/ऽ/g, " "); |
|
|
| |
| const phrases = normalizedText.split(/[।॥]/).filter(phrase => phrase.trim().length > 0); |
|
|
| let phraseIndex = 0; |
|
|
| function speakNextPhrase() { |
| if (phraseIndex >= phrases.length) return; |
|
|
| const currentPhrase = phrases[phraseIndex].trim(); |
| const utterance = new SpeechSynthesisUtterance(currentPhrase); |
|
|
| |
| utterance.lang = "sa-IN"; |
| utterance.pitch = 0.8; |
| utterance.rate = 0.8; |
| utterance.volume = 1.0; |
|
|
| |
| const voices = speechSynthesis.getVoices(); |
| utterance.voice = voices.find(voice => voice.lang === "sa-IN" && voice.name.includes("Male")); |
|
|
| |
| utterance.onend = () => { |
| phraseIndex++; |
| setTimeout(speakNextPhrase, 500); |
| }; |
|
|
| |
| utterance.onerror = (error) => { |
| console.error(`Error speaking phrase: ${currentPhrase}`, error); |
| phraseIndex++; |
| setTimeout(speakNextPhrase, 500); |
| }; |
|
|
| console.log(`Speaking phrase with bold voice: ${currentPhrase}`); |
| speechSynthesis.speak(utterance); |
| } |
|
|
| speakNextPhrase(); |
| } |
|
|
|
|
|
|
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| function downloadAudio(text, filename) { |
| const utterance = new SpeechSynthesisUtterance(text); |
| utterance.lang = "sa-IN"; |
|
|
| const audioChunks = []; |
| const streamDestination = new MediaStreamAudioDestinationNode(new AudioContext()); |
| const mediaRecorder = new MediaRecorder(streamDestination.stream); |
|
|
| utterance.onstart = () => mediaRecorder.start(); |
| utterance.onend = () => { |
| mediaRecorder.stop(); |
| const audioBlob = new Blob(audioChunks, { type: "audio/wav" }); |
| const audioUrl = URL.createObjectURL(audioBlob); |
|
|
| const link = document.createElement("a"); |
| link.href = audioUrl; |
| link.download = filename; |
| link.click(); |
| }; |
|
|
| mediaRecorder.ondataavailable = event => audioChunks.push(event.data); |
| speechSynthesis.speak(utterance); |
| } |
|
|