tts / script.js
bhagvat's picture
Update script.js
bbdce84 verified
Raw
History Blame Contribute Delete
5.18 kB
// Fetch data from JSON file and initialize
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) {
// Populate Skanda and Chapter List
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);
}
// Display Slokes
function displayChapter(chapter) {
chapterTitle.textContent = chapter.chapterTitle;
slokeContainer.innerHTML = "";
const slokes = chapter.slokes
.replace(/श्लोक\s*\d+:/g, "") // Remove "श्लोक-X"
.trim()
.split("\n"); // Split by newline
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);
});
}
// Speak Sloke with Advanced Features
function speakSloke(text) {
// Normalize and preprocess the text
const normalizedText = text
.normalize("NFC")
.replace(/ऽ/g, " "); // Replace avagraha with a space for better pronunciation
// Split the text into meaningful phrases
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);
// Set voice and TTS parameters for a bold, heavy tone
utterance.lang = "sa-IN";
utterance.pitch = 0.8; // Lower pitch for a deeper, heavier voice
utterance.rate = 0.8; // Slower rate for gravitas and clarity
utterance.volume = 1.0; // Full volume for boldness
// Select the male Sanskrit voice
const voices = speechSynthesis.getVoices();
utterance.voice = voices.find(voice => voice.lang === "sa-IN" && voice.name.includes("Male"));
// Handle completion of the current phrase
utterance.onend = () => {
phraseIndex++;
setTimeout(speakNextPhrase, 500); // Slightly longer pause for dramatic effect
};
// Handle errors gracefully
utterance.onerror = (error) => {
console.error(`Error speaking phrase: ${currentPhrase}`, error);
phraseIndex++;
setTimeout(speakNextPhrase, 500);
};
console.log(`Speaking phrase with bold voice: ${currentPhrase}`); // Debugging
speechSynthesis.speak(utterance);
}
speakNextPhrase(); // Start speaking the sloke
}
// Speak Sloke
// function speakSloke(text) {
// alert(text)
// const utterance = new SpeechSynthesisUtterance(text);
// utterance.lang = "sa-IN";
// utterance.rate = 0.8;
// utterance.pitch = 1.0;
// const voices = speechSynthesis.getVoices();
// utterance.voice = voices.find(voice => voice.lang === "sa-IN" && voice.name.includes("Male"));
// speechSynthesis.speak(utterance);
// }
// Download Audio
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);
}