'Sending & Saving MediaRecorder Data Producing Extremely Glitchy Results?
I have a script that sends MediaRecorder data over Websockets to the backend when the MediaStream is running. The backend then saves this data to a file to be replayed.
I am running into an issue where the result is coming out like this 
The video is extremely glitchy (sometimes it comes out somewhat smooth but mostly it comes out glitchy) and I do not know why.
I have tested this on Chrome (latest version) and Microsoft Edge and both produce the same glitchy results. I did notice though that Firefox seems to be smoother but i did limited tests on Firefox.
My front end code:
const socket = io('/')
document.querySelector("#startReccy").addEventListener('click', async () => {
socket.emit('recID', ROOM_ID)
let screenStream = await navigator.mediaDevices.getDisplayMedia({
video: {
cursor: "never"
},
audio: true
})
let vidId = document.querySelector("#myLiveVid")
vidId.srcObject = screenStream;
let videoMediaRecObj = new MediaRecorder(screenStream, {
audioBitsPerSecond: 128000,
videoBitsPerSecond: 2500000
});
//Send to server
videoMediaRecObj.addEventListener('dataavailable', (e) => {
//console.log(e.data)
//socket.emit('writeInfoData', ROOM_ID, e.data)
e.data.arrayBuffer().then ( buf => {
socket.emit('writeInfoData', ROOM_ID, buf)
})
})
videoMediaRecObj.start(3000)
//When we stop
screenStream.addEventListener('ended', () => {
videoMediaRecObj.stop();
//screenStream.getTracks().forEach(track => track.stop());
})
})
The backend
const express = require('express')
const app = express()
server = require('http').Server(app)
const io = require('socket.io')(server)
var fs = require('fs');
const { v4: uuidV4 } = require('uuid')
app.set('view engine', 'ejs')
app.use(express.static("public"))
app.get("/", (req, res) => {
res.redirect(`${uuidV4()}`)
})
app.get('/:room', (req, res) => {
res.render('room', {roomId: req.params.room})
})
io.on('connection', socket => {
socket.on('screen-rec', (roomId)=> {
/* Seems to get room ID with no problem*/
console.log(`${roomId}`)
/* We join a room*/
socket.join(roomId)
socket.roomId = path.join(__dirname, 'media', roomId + '.webm')
socket.emit('startRecording')
})
/* Write media file to disk*/
socket.on('writeInfoData', (roomId, data) => {
/* trying to read the data */
//console.log(data) - This works
fs.appendFile(`file-${roomId}.webm`, data, function (err) {
if (err) {
throw err;
}
console.log(`${Date().toLocaleString()} - ${roomId} - Saved!`);
});
})
})
server.listen(3000, () => {
console.log("Listening")
})
I am thinking the issue is because they may be received out of order, which I guess i can solve by making continuous POST requests but I know Websockets run on TCP so the packets have to come in order and I am sending it every 2 seconds so it should have time to send the data and save to the disk before the next request comes in (not sure though, just my guess)
Is there something wrong in my implementation?
Edit: Solved by O. Jones. I thought having a bigger timing is better but it seems that I need a really small time. Thank you so much!
Solution 1:[1]
Each time MediaRecorder calls your ondataavailable handler it gives you a Blob in event.data. That Blob contains all the accumulated encoded data. At a combined datarate of 2.6 megabits per second, three seconds of that is almost a megabyte. That's a very large payload for a POST request, and for appendFile.
Call ondataavailable less often. Use .start(20) instead of .start(3000). You're still moving a lot of data, but moving it in smaller chunks makes it less likely that things will get out of order, or that you'll lose some.
And, consider using nodejs streams to write your files.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
