We will use MediaDevices Web APIs to screen record and preview the video, downloading and uploading it using Vue 3 and Javascript.
Most of task management web applications provide a screen recording feature to record your computer screen and send it to another user. Have you ever wondered how they do that? It seems like coding for edges to create this feature or at least that is what I thought when a client asked me to program a screen recorder in the application. so I found out that the powerful web browsers we use nowadays provide MediaDevices Web APIs to screen records. It’s so simple and easy. so least do this step-by-step using Vue.js for cleaner code.
Create a Vue 3 application using Vite
Let’s create a new Vue.js application using Vite. Follow the below commands to set up the application and visit http://localhost:5173/ to make sure the application is installed correctly.
npm create vite@latest my-vue-app -- --template vue
cd my-vue-app
npm install
npm run dev
Screen recorder in Vue 3
Clear everything in ‘\src\App.vue’ let’s start coding but first we need to understand the steps that we need to do.
We have two important things first the the streaming data that we get and second the recorder class. To start recording we should pass the streaming data to the recorder class to control it. to do that we will create two variables stream
and recorder
<script setup>
import { ref } from 'vue'
let stream = '';
let recorder = '';
</script>
Then we need to create a new function to start recording and by starting recording, we will pass the streaming data to the stream
variable and the recorder class to the recorder
variable
<script setup>
import { ref } from 'vue'
let stream = '';
let recorder = '';
const startRecord = async ()=>{
try {
stream = await navigator.mediaDevices.getDisplayMedia();
recorder = new MediaRecorder(stream);
} catch (error) {
console.error('Error obtaining display media:', error);
}
}
</script>
We got the streaming data from the mediaDevices
APIs and we instantiate MediaRecorder
class for controlling the recording processing. We should put the code between try and catch to debug the errors.
We should create some trackers for the recording we follow the event listener of the MediaRecorder
. We have ‘start’, ‘error’, and ‘dataavailable’ when the video data is available to use.
To start the record call the start function recorder.start(), a
nd to get the video tracks stream.getVideoTracks();
and we can listen to its ‘end’ event to stop recording
Let’s use them with the startRecord
function the see the code.
let stream = '';
let recorder = '';
const startRecord = async ()=>{
videoLink.value = ''
videoBlob.value = null;
try {
stream = await navigator.mediaDevices.getDisplayMedia();
recorder = new MediaRecorder(stream);
recorder.addEventListener('start', () => {
console.log('Recording started');
});
recorder.addEventListener('dataavailable', (event) => {
console.log('Video recorded successfully');
});
recorder.addEventListener('error', (error) => {
console.log('Recording error');
});
recorder.start();
const [ video ] = stream.getVideoTracks();
video.addEventListener("ended", () => {
console.log('Recording ended');
});
} catch (error) {
console.error('Error obtaining display media:', error);
}
}
We need to get the recorded video link to preview on the webpage after recording to do that we will add this variable const videoLink = ref('');
and at the ‘dataavailable’ listener we add this code videoLink.value = URL.createObjectURL(evt.data);
const videoLink = ref('');
//
const startRecord = async ()=>{
//
recorder.addEventListener('dataavailable', (event) => {
videoLink.value = URL.createObjectURL(event.data);
});
//
}
//
Now you can pass this variable as a source link in the video HTML element videoLink
.
If you want to download the video that you recorded just create a
a link element and click it as the following code
const videoLink = ref('');
//
const startRecord = async ()=>{
//
recorder.addEventListener('dataavailable', (event) => {
videoLink.value = URL.createObjectURL(event.data);
//auto download
const a = document.createElement("a");
a.href = URL.createObjectURL(event.data);
a.download = "capture.webm";
a.click();
});
//
}
//
You re-run the serve and test the recording after finishing you should see the auto download of the video.
If you want to upload to the server you must pass the event data to a new variable videoBlob.value = event.data
and then pass it to a new form data class new FormData()
;
const videoLink = ref('');
const videoBlob = ref(null);
//
const startRecord = async ()=>{
//
recorder.addEventListener('dataavailable', (event) => {
//uploading data
videoBlob.value = event.data;
//video link
videoLink.value = URL.createObjectURL(event.data);
//auto download
const a = document.createElement("a");
a.href = URL.createObjectURL(event.data);
a.download = "capture.webm";
a.click();
});
//
}
//
I created a flag variable for recording const isRecording = ref(false);
to use with start and end events, and we can stop recording by calling the stop function recorder.stop();
Here is the enter code for start and stop recording.
<script setup>
import { ref } from 'vue'
// recording
const videoLink = ref('');
const videoBlob = ref(null);
const isRecording = ref(false);
let stream = '';
let recorder = '';
const startRecord = async ()=>{
videoLink.value = ''
videoBlob.value = null;
try {
stream = await navigator.mediaDevices.getDisplayMedia();
recorder = new MediaRecorder(stream);
recorder.addEventListener('start', () => {
isRecording.value = true;
console.log('Recording started');
});
recorder.addEventListener('dataavailable', (event) => {
//uploading data
videoBlob.value = event.data; // Store the recorded video blob
//video link
videoLink.value = URL.createObjectURL(event.data);
//auto download
const a = document.createElement("a");
a.href = URL.createObjectURL(event.data);
a.download = "capture.webm";
a.click();
console.log('Video recorded successfully');
});
recorder.addEventListener('error', (error) => {
});
recorder.start();
const [ video ] = stream.getVideoTracks();
video.addEventListener("ended", () => {
isRecording.value = false;
recorder.stop();
});
} catch (error) {
console.error('Error obtaining display media:', error);
}
}
const stopRecording = async () =>{
recorder.stop();
isRecording.value = false;
}
Here is the HTML template code and the CSS for start and stop buttons with video preview.
<template>
<div class="">
<button class="btn-start" v-if="!isRecording" @click="startRecord">Start record</button>
<button class="btn-stop" v-if="isRecording" @click="stopRecording">Stop record</button>
<div v-if="videoLink">
<div>Video preview</div>
<video controls class="w-100">
<source :src="videoLink" type="video/webm">
Your browser does not support the video tag.
</video>
</div>
</div>
</template>
<style scoped>
.w-100{
width: 100%;
}
.btn-start {
/* Styles for the start button */
background-color: green;
color: white;
border: none;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
cursor: pointer;
}
.btn-stop {
/* Styles for the stop button */
background-color: red;
color: white;
border: none;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
cursor: pointer;
}
</style>
This is the bonus function to upload the video to the server after stopping recording.
const uploadVideo = async () => {
if (!videoBlob.value) {
console.warn('No video recorded to upload');
return;
}
console.log(videoBlob.value);
const formData = new FormData();
formData.append('video', videoBlob.value); // Set appropriate filename
try {
axios.post('/save-video',formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
.then((res) => {
})
.catch( (error) => {
});
} catch (error) {
console.error('Error uploading video:', error);
}
};
Conclusion
Nowadays browsers provide a powerful API to screen recording the computer screen and manipulate the video data as we want for example we can upload, download, and preview the video.
Thank you for reading I hope that was useful for you.