I am working on a Next.JS web app making voice recording and uploading the produced audio data to a mongo DB using GridFS.
Though it is basically working, the audio data being uploaded. I still get an error and the app crashes after the first upload. I hope somebody will be able to spot what is wrong in the following.
Here is the code. First, here is the function called when a voice recording ends:
const stopRecording = () => {
setRecordingStatus("inactive");
if (!mrRef.current) return
mrRef.current?.stop();
mrRef.current.onstop = async () => {
console.log("Here mimeType = ",mimeType)
const audioBlob = new Blob(audioChunksRef.current, {
type: mimeType});
const audioUrl = URL.createObjectURL(audioBlob);
setAudio(audioUrl);
const audioBuffer = await audioBlob.arrayBuffer();
const audioBase64 = Buffer.from(audioBuffer).toString('base64');
axios.post('/upload', { audio: audioBase64,
mimeType: mimeType })
.then((response) => {
const fileId = response.data.fileId;
console.log('File ID:', fileId);
})
.catch((error) => {
console.error('Upload error:', error);
});
};
}; /* End of stopRecording */
Then on the server side, this is the upload route code:
server.post('/upload', async (req, res) => {
console.log('Request Body (mimeType):', req.body.mimeType);
try {
if (!req.body.audio) {
return res.status(400).json({ message: 'No audio data uploaded.' });
}
const audioBuffer = Buffer.from(req.body.audio, 'base64');
const mimeType = req.body.mimeType
const fileId = await saveAudioToGridFS(audioBuffer); // Save audio to GridFS
res.json({ fileId });
} catch (error) {
console.error(error);
res.status(500).json({
message: 'An error occurred during upload.',
error: JSON.stringify(error)
});
}
});
And this is the saveAudioToGridFS function:
function saveAudioToGridFS(audioBlob) {
return new Promise((resolve, reject) => {
const gridFSBucket = new mongoose.mongo.GridFSBucket(conn.db),
now = new Date()
let upldName = 'Audio_'+now.getFullYear()
upldName += '-'+(now.getMonth()+1).toString().padStart(2,'0')
upldName += '-'+now.getDate().toString().padStart(2,'0')
upldName += ':'+now.getHours().toString().padStart(2,'0')
upldName += ':'+now.getMinutes().toString().padStart(2,'0')
upldName += ':'+now.getSeconds().toString().padStart(2,'0')
const writeStream = gridFSBucket.openUploadStream(upldName);
writeStream.on('close', (file) => {
console.log("file=",file)
console.log("file._id=",file._id)
resolve(file._id); // Return the GridFS file ID
});
writeStream.on('error', (error) => {
reject(error);
});
// Convert the Blob into a readable stream using streamifier
const readableStream = streamifier.createReadStream(audioBlob);
readableStream.pipe(writeStream);
});
} /* End of saveAudioToGridFS */
finally, this is what I get in the server logs, after making a first recording-upload:
me@MyMac myapp % npm run devsrv
> myapp@0.1.0 devsrv
> node server.js
> Ready on http://localhost:3000
Request Body (mimeType): video/webm
file= undefined
/Users/michelbouchet/Documents/Heroku/nxjsxprs2/server.js:93
console.log("file._id=",file._id)
^
TypeError: Cannot read properties of undefined (reading '_id')
at GridFSBucketWriteStream.<anonymous> (/Users/me/Documents/Heroku/myapp/server.js:94:22)
at GridFSBucketWriteStream.emit (node:events:514:28)
at /Users/me/Documents/Heroku/myapp/node_modules/mongodb/lib/gridfs/upload.js:172:20
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
Node.js v18.17.0
me@MyMac myapp %
I find it weird to get "file= undefined" inside:
writeStream.on('close', (file) => {...})
But I must certainly be missing something.