Hello!
This is related to my last post, but a different rabbit trail.
I am trying to make a media into an interactive transcript that highlights each line as it comes to it, or you can click on the line that you want to hear and the audio/video will play from there. There is a working codepen here, and I have some media that I’ve been playing with on my Sandbox page. The only one that complete works so far is the one that is pretty much a character for character cut and paste from the codepen, but it doesn’t show the timestamp and it’s not as user-friendly for inputing the data. The two main others that I’ve been concentrating on are two versions of the same thing: an audio and a video (I wanted to make sure that either media type would work).
Thus far, I have gotten it where it is not throwing any errors, but only bits and pieces of the code works. I think it’s mainly it’s the EventListeners that don’t work.
This is my code:
document.addEventListener("DOMContentLoaded", function() {
intTranscriptScript = () => {
// get media element
const mediaContainer = document.querySelector(".media-render.file");
const mediaTag = mediaContainer.firstElementChild.tagName;
let mediaThing;
if (mediaTag === "VIDEO") {
mediaThing = document.querySelector("video");
} else if (mediaTag === "AUDIO") {
mediaThing = document.querySelector("audio");
}
function testing(){
mediaThing.play();
console.log("Testing " + mediaTag + "!");
}
// register the time cues
const cues = document.querySelectorAll("tbody#transcriptText > tr.cue");
const dTimes = document.querySelectorAll("td.date-time");
// Add click event listener on each cue to jump to respective time
// Event listener to update current line hightlight as audio plays
mediaThing.addEventListener("timeupdate", updateTime);
// convert the "hh:mm:ss" time notation to total seconds
function timeToSeconds(time) {
const [hours, minutes, seconds] = time.split(":").map(Number);
return hours * 3600 + minutes * 60 + seconds;
}
for (i=0; i<cues.length && i<dTimes.length; i++) {
const cue = cues[i];
const dT = dTimes[i];
const dTime = dT.innerText;
function updateTime() {
const currentTime = mediaThing.currentTime;
//console.log(currentTime);
const cueTime = timeToSeconds(dTime);
const nextCue = cue.nextElementSibling;
const nextCueTime = nextCue ? timeToSeconds(nextCue.getAttribute("data-time")) : Infinity;
function cueClick() {
mediaThing.currentTime = timeToSeconds(dTime);
mediaThing.play();
console.log("cue" + i + " clicked");
}
if (!cue.getAttribute("data-time")) {
cue.setAttribute("data-time", dTime);
}
if (currentTime >= cueTime && currentTime < nextCueTime) {
cue.classList.add("active");
} else {
cue.classList.remove("active");
}
}
}
};
/*
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', intTranscriptScript);
} else {
intTranscriptScript();
}
*/
});
I have tried both putting it in the HTML block and uploading it into my asset/js
folder. I do have a “click me” button to as a tester, but it has a built-in Event Listener and definition through its HTML block since it’s so small.
Can anyone tell me what I’m doing wrong?