I have created an app in HTML and JavaScript where the screen and system sounds are recorded, and then when the user clicks "stop recording", a video element containing the recorded video appears. I would like to add functionality that allows the user to select a starting point and ending point, and trim the video to that selected section. Here is the code that I already have:
<!DOCTYPE html>
<html>
<head>
<style>
.videoBox {
border-style: solid;
border-color: black;
width: 310px;
height: 310px;
margin-bottom: 20px;
}
.videoControls {
margin-left: 50px;
margin-top: 50px;
}
.playOrPauseButton {
margin-bottom: 10px;
}
.endButton {
margin-left: 10px;
}
.savingInfo {
margin-top: 10px;
}
</style>
</head>
<body>
<input type="hidden" id="recording" value="0" />
<div class="videoBox">
<div class="videoControls">
<div class="playOrPauseButton">
<button type="button" id="record" onclick="playOrPause()">Start Recording</button>
<div class="recordingTime" id="recordingTime"></div>
</div>
<div class="endButton">
<a id="downloadLink"><button type="button" id="endRecording" onclick="stopRecording()">Save
Video</button></a>
</div>
<div class="savingInfo">
Your video will download, and it will also appear below when you save your video.
</div>
</div>
</div>
<div id="videoItself" class="videoItself"></div>
<script>
numberOfClicks = 1;
let chunks = [];
let mediaStream = null;
let recorder = null;
let seconds = 0;
let videoNumber = 1;
let filename = "";
let videoLink = document.getElementById("downloadLink");
let videoURL = "";
async function setupMediaStream() {
mediaStream = await navigator.mediaDevices.getDisplayMedia({ video: true, audio: true });
recorder = new MediaRecorder(mediaStream);
recorder.addEventListener("dataavailable", function (e) {
chunks.push(e.data);
});
recorder.onstop = function () {
document.getElementById("videoItself").innerHTML = "";
if (filename.trim().length == 0) {
filename = "video " + videoNumber;
}
videoNumber++;
let mostRecentChunk = [];
mostRecentChunk.push(chunks[chunks.length - 1]);
let blob = new Blob(mostRecentChunk, { 'type': 'video/mp4' });
videoURL = window.URL.createObjectURL(blob);
videoLink.setAttribute("href", videoURL);
videoLink.setAttribute("download", filename);
document.getElementById("endRecording").click();
videoLink.removeAttribute("download");
videoLink.removeAttribute("href");
document.getElementById("recordingTime").innerHTML = "";
document.getElementById("recording").value = 0;
document.getElementById("record").innerHTML = "Start Recording";
let video = document.createElement("video");
video.src = videoURL;
video.controls = true;
video.style.width = "400px";
video.style.height = "400px";
video.setAttribute("id", "theVideo");
document.getElementById("videoItself").appendChild(video);
let seekBox = document.createElement("input");
seekBox.setAttribute("type", "textbox");
seekBox.setAttribute("id", "seekBox");
let seekButton = document.createElement("button");
seekButton.setAttribute("id", "seekButton");
seekButton.innerHTML = "Seek Time (seconds)";
seekButton.setAttribute("onclick", "seekTime()");
let videoLength = document.createElement("p");
videoLength.setAttribute("id", "videoLength");
document.getElementById("videoItself").appendChild(seekBox);
document.getElementById("videoItself").appendChild(seekButton);
videoLength.innerHTML = "The length of the video is " + seconds + " seconds";
document.getElementById("videoItself").appendChild(videoLength);
seconds = 0;
};
}
setupMediaStream();
function seekTime() {
let seekBox = document.getElementById("seekBox");
let video = document.getElementById("theVideo");
video.currentTime = parseInt(seekBox.value);
}
function playOrPause() {
const recording = parseInt(document.getElementById("recording").value);
recording == 0 ? record() : pause();
}
function record() {
if (recorder != null) {
try {
recorder.start();
} catch (err) {
recorder.resume();
}
myInterval = setInterval(countTime, 1000);
document.getElementById("recording").value = 1;
document.getElementById("record").innerHTML = "Pause";
} else {
console.log("You must grant permission for the app to share your screen and use your microphone");
}
}
function pause() {
if (recorder != null) {
recorder.pause();
clearInterval(myInterval);
document.getElementById("recording").value = 0;
document.getElementById("record").innerHTML = "Continue Recording";
let timeLabel = document.getElementById("recordingTime").innerHTML;
document.getElementById("recordingTime").innerHTML = "" + recorder.state + ": " + timeLabel.substring(timeLabel.indexOf(":") + 1, timeLabel.length);
} else {
console.log("You must grant permission for the app to share your screen and use your microphone");
}
}
function stopRecording() {
if (recorder != null) {
if (recorder.state != "inactive") {
pause();
filename = prompt("Save As: (Do not include the dot file extension)", "video " + videoNumber);
if (filename != null) {
recorder.stop();
}
}
} else {
console.log("You must grant permission for the app to share your screen and use your microphone");
}
}
function countTime() {
seconds++;
let hours = Math.floor(seconds / 3600);
let minutes = Math.floor((seconds - (hours * 3600)) / 60);
let secs = seconds - (hours * 3600) - (minutes * 60);
let hourString = "";
if (hours < 10) {
hourString += "0";
}
hourString += hours;
let minuteString = "";
if (minuteString < 10) {
minuteString += "0";
}
minuteString += minutes;
let secString = "";
if (secs < 10) {
secString += "0";
}
secString += secs;
let timeString = hourString + ":" + minuteString + ":" + secString;
document.getElementById("recordingTime").innerHTML = "" + recorder.state + ": " + timeString;
}
</script>
</body>
</html>
Now, what I am struggling to figure out is this: What is the entity that contains the actual video data with timestamps and everything? To better explain what I am asking, what is it that I would have to manipulate in order to trim the video? Would I have to do something with the blob object that was used to create the video as seen here?:
let blob = new Blob(mostRecentChunk, { 'type': 'video/mp4' });
videoURL = window.URL.createObjectURL(blob);
I tried doing something with mediaStream.getVideoTracks(), but that doesn't do anything. Can anyone please tell me what it is that I would have to manipulate?