1

I've been trying to use the node-lame library to encode a file from the uploaded bitrate to 32 kbps to save space the same way I do it with sharp to compress my images.

My code first checks if the file is an audio file. If it is it then makes the encoder and it should encode it:

if (aud.test(user_file)){

        const encoder = new Lame({
            "output": req.file.path,
            "bitrate": 32,
        }).setFile(req.file.path);
        
        await encoder
            .encode()
            .then(() => {})
            .catch((error) => {
                // Something went wrong
            });
    }

The problem is that it doesn't actually get encoded. I have also tried this in my .then but it doesn't help.

.then(data => {
    fs.writeFileSync(req.file.path + '.mp3', data);
    user_file = user_file + '.mp3';
    fs.unlinkSync(req.file.path)
})

This is supposed to be a fairly simple library so I don't know what I'm doing wrong. I am trying to encode from file to file.

Also tried this:

const encoder = new Lame({
            "output": user_file + '.mp3',
            "bitrate": 32,
        }).setFile(req.file.path);
Nik
  • 96
  • 7
  • What have you done to troubleshoot? Does the file you are trying to convert actually work? What error do you get, if any? What does `unlinkSync` do? Have you tried it without that? Is that the correct bitrate for the file you are encoding? – Matt Oestreich Aug 31 '21 at 20:52
  • I've checked for errors but I don't get any. I tried writing a new encoded file and deleting the old one with the fs like with sharp to see if it would help but judging on the documentation it probably doesn't. The idea is to input an uploaded file, run it through the encoder and get the same clip but with lower bitrate out. – Nik Aug 31 '21 at 21:37
  • What does your route look like? Are you sure you're successfully uploading the file? – Matt Oestreich Aug 31 '21 at 23:29

1 Answers1

1

I went ahead and wrote a demo for this. You can find the full repo here. I have verified this does work but keep in mind this is only a proof of concept.

This is what my Express server looks like:


const express = require('express');
const fs = require('fs');
const path = require('path');
const fileUpload = require('express-fileupload');
const Lame = require('node-lame').Lame;

const app = express();

app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(fileUpload());

// File upload path
app.post('/upload', async (req, res) => {
  const fileToEncode = req.files.uploadedFile;
  if (!fileToEncode) {
    res.status(500).end();
    return;
  }

  const filePath = path.resolve('./uploads', fileToEncode.name);
  const outputPath = path.resolve('./uploads', fileToEncode.name + '-encoded.mp3');

  // Save uploaded file to disk
  await fileToEncode.mv(filePath);

  try {
    const encoder = new Lame({ 
      output: outputPath,
      bitrate: 8,
    }).setFile(filePath);
    await encoder.encode();
    res.download(outputPath);
  } catch (encodingError) {
    console.error(encodingError);
    res.status(500).send(encodingError);
  }

  // Removed files we saved on disk
  res.on('finish', async () => {
    await fs.unlinkSync(filePath);
    await fs.unlinkSync(outputPath);
  })
});

// Home page
app.get('*', (req, res) => {
    res.status(200).send(`
    <!DOCTYPE html>
    <html>
    <body>

    <p id="status"></p>

    <form method="post" enctype="multipart/form-data" action="/upload" onsubmit="handleOnSubmit(event, this)">
      <input name="uploadedFile" type="file" />
      <button id="submit">Submit Query</button>
    </form>

    <script>
    async function handleOnSubmit(e,form) {
      const statusEl = document.getElementById("status");
      statusEl.innerHTML = "Uploading ...";
      e.preventDefault();
      const resp = await fetch(form.action, { method:'post', body: new FormData(form) });
      const blob = await resp.blob();
      const href = await URL.createObjectURL(blob);
      Object.assign(document.createElement('a'), {
        href,
        download: 'encoded.mp3',
      }).click();
      statusEl.innerHTML = "Done. Check your console.";
    }
    </script>

    </body>
    </html>    
    `);
});

process.env.PORT = process.env.PORT || 3003;

app.listen(process.env.PORT, () => { 
    console.log(`Server listening on port ${process.env.PORT}`);
});
Matt Oestreich
  • 8,219
  • 3
  • 16
  • 41