Skip to content

WebNinjaDeveloper.com

Programming Tutorials




Menu
  • Home
  • Youtube Channel
  • Official Blog
  • Nearby Places Finder
  • Direction Route Finder
  • Distance & Time Calculator
Menu

Node.js Fluent-FFMPEG Audio Pitch & Speed Changer With Live Preview in Browser Using Express

Posted on March 16, 2023

 

Welcome folks today in this blog post we will be using the fluent-ffmpeg library to change the pitch and speed of mp3 audio file in browser using node.js and express in javascript. All the full source code of the application is shown below.

 

 

 

Get Started

 

 

In order to get started you need to make a new node.js project using the below command

 

 

npm init -y

 

 

npm i express

 

 

npm i fluent-ffmpeg

 

 

npm i multer

 

 

Now you will see the below directory structure at the end of this app

 

 

 

 

 

As you can see you need to make the uploads folder inside the public folder which will be the static directory for this project. And inside the uploads directory we will store all the audio files which will be uploaded by the user.

 

 

Dependencies

 

 

We will be using the following dependencies in our project:

 

 

  • express – a Node.js web framework

 

  • multer – middleware for handling file uploads

 

  • fluent-ffmpeg – a Node.js wrapper for FFmpeg

 

 

Backend Code

 

 

Now guys we need to make the index.js file inside the root directory and copy paste the following code

 

 

index.js

 

 

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
const express = require("express");
const multer = require("multer");
const ffmpeg = require("fluent-ffmpeg");
const path = require("path");
 
const app = express();
const port = 3000;
 
// Set up file upload middleware
const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, "public/uploads/");
  },
  filename: function (req, file, cb) {
    cb(null, Date.now() + path.extname(file.originalname));
  },
});
const upload = multer({ storage: storage });
 
// Set up static files middleware
app.use(express.static("public"));
 
// Handle file upload
app.post("/upload", upload.single("file"), (req, res) => {
  const filePath = req.file.path;
  const fileName = req.file.originalname;
 
  // Set up FFmpeg command
  const command = ffmpeg(filePath);
 
  // Handle pitch change
  if (req.body.pitch) {
    const pitch = parseFloat(req.body.pitch);
    const speedAdjustment = 1 / Math.pow(2, pitch / 12);
 
    command.audioFilters([
      {
        filter: "asetrate",
        options: `48000*${Math.pow(2, pitch / 12)}`,
      },
      {
        filter: 'atempo',
        options: speedAdjustment.toFixed(2),
      }
    ]);
  }
 
  // Handle speed change
  if (req.body.speed) {
    const speed = parseFloat(req.body.speed);
    command.audioFilters(`atempo=${speed}`);
  }
 
  // Generate output file name
  const outputFile = uuidv4() + path.extname(fileName);
 
  // Save modified file
  command
    .on("error", (err) => {
      console.log("An error occurred: " + err.message);
      res.status(500).send("An error occurred");
    })
    .on("end", () => {
      res.download(path.join(__dirname, "public/uploads", outputFile));
    })
    .save(path.join(__dirname, "public/uploads", outputFile));
});
 
// Start server
app.listen(port, () => {
  console.log(`App listening at http://localhost:${port}`);
});

 

 

Here’s what this code does:

 

  • We set up the file upload middleware using Multer.

 

  • We set up the static files middleware using Express.

 

  • We define a route for handling file uploads. When a file is uploaded, we use FFmpeg to modify the pitch and speed of the audio file, if the user has specified these parameters. We then save the modified file to the uploads directory and send it to the user for download.

 

  • We start the server listening on port 3000.

 

 

Frontend Code

 

 

Now guys inside the public folder we need to create the index.html file and copy paste the following code

 

 

index.html

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
<!DOCTYPE html>
<html>
 
<head>
  <meta charset="UTF-8">
  <title>Audio Pitch and Speed Changer</title>
  <style>
body {
  font-family: Arial, sans-serif;
  margin: 0;
  padding: 0;
}
 
h1 {
  margin: 0;
  padding: 1rem;
  text-align: center;
  background-color: #4CAF50;
  color: white;
}
 
form {
  margin: 1rem;
  padding: 1rem;
  background-color: #f2f2f2;
  border: 1px solid #ccc;
  border-radius: 5px;
  text-align: center;
}
 
.form-group {
  margin: 1rem;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
 
label {
  margin-bottom: 0.5rem;
  font-weight: bold;
}
 
input[type="range"] {
  width: 90%;
  margin-bottom: 0.5rem;
}
 
button[type="submit"] {
  padding: 0.5rem;
  background-color: #4CAF50;
  color: white;
  border: none;
  border-radius: 5px;
  cursor: pointer;
}
 
#result {
  margin: 1rem;
  padding: 1rem;
  background-color: #f2f2f2;
  border: 1px solid #ccc;
  border-radius: 5px;
  text-align: center;
}
 
#result audio {
  width: 100%;
}
 
#download-button {
  padding: 0.5rem;
  background-color: #4CAF50;
  color: white;
  border: none;
  border-radius: 5px;
  cursor: pointer;
}
</style>
</head>
 
<body>
  <h1>Audio Pitch and Speed Changer</h1>
 
  <form id="upload-form" enctype="multipart/form-data">
    <input type="file" name="file" required>
    <div class="form-group">
      <label for="pitch-slider">Pitch:</label>
      <input type="range" name="pitch" id="pitch-slider" min="-2" max="10" step="0.1" value="1">
      <span id="pitch-value">1</span>
    </div>
    <div class="form-group">
      <label for="speed-slider">Speed:</label>
      <input type="range" name="speed" id="speed-slider" min="0.5" max="10" step="0.1" value="1">
      <span id="speed-value">1</span>
    </div>
    <button type="submit">Upload and Modify</button>
  </form>
 
  <div id="result" style="display: none;">
    <h2>Modified Audio:</h2>
    <audio controls></audio>
    <a id="download-button" href="#" download="modified-audio.mp3">Download</a>
  </div>
 
  <script src="js/main.js"></script>
</body>
 
</html>

 

 

 

 

  • We set the font family to Arial and set the margin and padding of the body to 0.

 

  • We style the h1 element to have a green background, white text, and no margin or padding.

 

  • We style the form element to have a light gray background, a border, rounded corners, and some margin and padding.

 

  • We style the .form-group class to display its child elements as a column with center alignment, and add some margin.

 

  • We style the label element to have some margin and bold text.

 

  • We style the input[type="range"] elements to have a width of 90% and some margin.

 

  • We style the submit button to have a green background, white text, no border, rounded corners, and a pointer cursor.

 

  • We style the #result element to have a light gray background, a border, rounded corners, and some margin and padding.

 

  • We style the audio element inside #result to have a width of 100%.

 

  • We style the download button to have a green background, white text, no border, rounded corners, and a pointer cursor.

 

 

Now we need to add the client side ajax code which will actually make the fetch request to the backend server to actually change the pitch and the speed of the uploaded mp3 audio file as shown below

 

 

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
const form = document.getElementById("upload-form");
const pitchSlider = document.getElementById("pitch-slider");
const pitchValue = document.getElementById("pitch-value");
const speedSlider = document.getElementById("speed-slider");
const speedValue = document.getElementById("speed-value");
const result = document.getElementById("result");
const audio = result.querySelector("audio");
const downloadButton = result.querySelector("#download-button");
 
form.addEventListener("submit", (e) => {
  e.preventDefault();
 
  const formData = new FormData(form);
 
  fetch("/upload", {
    method: "POST",
    body: formData,
  })
    .then((res) => {
      if (!res.ok) {
        throw new Error("Network response was not ok");
      }
      return res.blob();
    })
    .then((blob) => {
      result.style.display = "block";
      audio.src = URL.createObjectURL(blob);
      downloadButton.href = audio.src;
      downloadButton.download = "modified-audio.mp3";
    })
    .catch((err) => {
      console.error("An error occurred: " + err.message);
      alert("An error occurred. Please try again later.");
    });
});
 
pitchSlider.addEventListener("input", (e) => {
  pitchValue.textContent = e.target.value;
});
 
speedSlider.addEventListener("input", (e) => {
  speedValue.textContent = e.target.value;
});
 
// Event listener for the download button
downloadButton.addEventListener("click", () => {
  const audioSrc = audioPlayer.src;
  const fileName = downloadButton.getAttribute("download");
  download(audioSrc, fileName);
});
 
// Function to download the modified audio
function download(src, fileName) {
  const link = document.createElement("a");
  link.href = src;
  link.download = fileName;
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
}

 

 

  • We select the form, sliders, value elements, result element, audio element, and download button element from the DOM.

 

  • We add an event listener to the form that prevents the default form submission behavior, creates a FormData object from the form data, and sends a POST request to the server using fetch(). When the response comes back, we display the result element, set the src of the audio element to a URL created from the response blob, and set the href and download attributes of the download button to the same URL and a file name respectively.

 

Recent Posts

  • Node.js Fluent-FFMPEG Audio Pitch & Speed Changer With Live Preview in Browser Using Express
  • React.js react-awesome-modal Example to Show Popup Modal With Animation in Browser Using Javascript
  • Node.js Express Server Side Form Validation With Custom Error Messages Using express-validator Library in Javascript
  • Node.js Express Project to Validate User Form Data Using joi Schema Validation Library Full Example
  • Node.js Puppeteer Project to Export Handlebars Resume Template to PDF Document in Express Using Javascript
  • Angular
  • Bunjs
  • C#
  • Deno
  • django
  • Electronjs
  • java
  • javascript
  • Koajs
  • kotlin
  • Laravel
  • meteorjs
  • Nestjs
  • Nextjs
  • Nodejs
  • PHP
  • Python
  • React
  • ReactNative
  • Svelte
  • Tutorials
  • Vuejs




©2023 WebNinjaDeveloper.com | Design: Newspaperly WordPress Theme