<body>
<style>
div {
padding: 0.25em 0;
}
</style>
<script>
// ===================================================
// ==================== Variables ====================
// ===================================================
var timeoutDuration = 60;
var timeoutID = NaN;
var tracks = [];
var speechText = "I love shots. Shotty shot shots";
var utterance = null;
// ===================================================
// ==================== DOM ====================
// ===================================================
function div() {
return document.body.appendChild(document.createElement("div"));
}
var audioRow = div();
var audioElement = audioRow.appendChild(document.createElement("audio"));
audioElement.autoplay = true;
audioElement.controls = true;
var tracksRow = div();
var tracksInputElement = tracksRow.appendChild(document.createElement("input"));
tracksInputElement.type = "file";
tracksInputElement.accept = "audio/*";
tracksInputElement.multiple = true;
var timeoutDurationRow = div();
var timeoutDurationInputElement = timeoutDurationRow.appendChild(document.createElement("input"));
timeoutDurationInputElement.type = "number";
timeoutDurationInputElement.min = 1;
timeoutDurationInputElement.value = timeoutDuration;
timeoutDurationRow.appendChild(document.createTextNode(" seconds per track"));
div();
div();
var speechRow = div();
var speechTextareaElement = speechRow.appendChild(document.createElement("textarea"));
speechTextareaElement.value = speechText;
var voiceRow = div();
voiceRow.appendChild(document.createTextNode("Voice: "));
var voiceSelectElement = voiceRow.appendChild(document.createElement("select"));
// ===================================================
// ==================== Functions ====================
// ===================================================
var next = null;
function play(index) {
// console.log(index);
// console.log(tracks[index]);
audioElement.src = URL.createObjectURL(tracks[index]);
next = function() {
// console.log("next");
clearTimeout(timeoutID);
if (!utterance) {
utterance = new SpeechSynthesisUtterance(speechText);
if (voiceSelectElement.value) {
utterance.voice = window.speechSynthesis.getVoices().filter(function(voice) {
return voice.name == voiceSelectElement.value;
})[0];
}
utterance.addEventListener("end", function(event) {
// console.log("end");
utterance = null;
play((index + 1) % tracks.length);
});
setTimeout(function() {
// console.log("speak");
window.speechSynthesis.speak(utterance);
}, 0);
}
URL.revokeObjectURL(audioElement.src);
audioElement.src = "";
};
timeoutID = setTimeout(next, timeoutDuration * 1000);
}
audioElement.addEventListener("ended", function(event) {
// console.log("ended");
if (!audioElement.src.length || utterance)
return;
if (typeof next === "function")
next();
});
audioElement.addEventListener("error", function(event) {
// console.log("error");
if (!audioElement.src.length || utterance)
return;
if (typeof next === "function")
next();
});
audioElement.addEventListener("seeked", function(event) {
// console.log("seeked");
if (!audioElement.src.length || utterance)
return;
clearTimeout(timeoutID);
timeoutID = setTimeout(next, (timeoutDuration - audioElement.currentTime) * 1000);
});
tracksInputElement.addEventListener("change", function(event) {
timeoutID = NaN;
tracks = [];
for (var i = 0; i < tracksInputElement.files.length; ++i)
tracks.push(tracksInputElement.files[i]);
if (tracks.length)
play(0);
});
function updateTimeoutDuration() {
timeoutDuration = parseInt(timeoutDurationInputElement.value);
var digits = String(timeoutDuration).length;
timeoutDurationInputElement.style.setProperty("width", (2 + (digits / 2)) + "em");
}
timeoutDurationInputElement.addEventListener("input", updateTimeoutDuration);
updateTimeoutDuration();
speechTextareaElement.addEventListener("input", function() {
speechText = speechTextareaElement.value;
});
function loadVoices() {
window.speechSynthesis.getVoices().forEach(function(voice) {
var optionElement = voiceSelectElement.appendChild(document.createElement("option"));
optionElement.value = voice.name;
optionElement.textContent = voice.name;
});
}
window.speechSynthesis.addEventListener("voiceschanged", loadVoices);
loadVoices();
</script>
</body>