0

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.

Michel
  • 10,303
  • 17
  • 82
  • 179

0 Answers0