Why doesn't node-lame encode properly (nodeJS library)? - javascript

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);

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}`);
});

Related

Twilio - can't process phone number after clicking submit

I'm following this link for the tutorial (via twilio.) and have followed all the
required steps but when I run the localhost and input a number, I get no text message, nor does the window for verification open. It just stays at the same page of "enter your phone number".
Here's my HTML code
<!DOCTYPE HTML>
<HTML>
<head>
<title>Verify SMS Demo</title>
<style>
#verify-form,
#response-text {
display: none;
}
</style>
</head>
<body>
<form id="phone-form">
<h2>Enter your phone number with country code:</h2>
<input type="tel" id="phone-number-input" placeholder="15551235555" />
<input id="phone-submit" type="submit" />
</form>
<form id="verify-form">
<h2>Enter your verification code:</h2>
<input type="number" id="otp-input" placeholder="e.g. 123456" />
<input id="verify-submit" type="submit" />
</form>
<div id="response-text"></div>
</body>
<script type="text/javascript" src = "script.js"></script>
</html>`
And here's my code for script.js:
const phoneForm = document.getElementById('phone-form');
const verifyForm = document.getElementById('verify-form');
const responseText = document.getElementById('response-text');
let phoneNumber;
phoneForm.addEventListener('submit', async e => {
e.preventDefault();
phoneNumber = document.getElementById('phone-number-input').value;
const response = await fetch('/send-notification', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({phoneNumber : phoneNumber })
}).catch(e => console.log(e));
if (response.ok) {
phoneForm.style.display = 'none';
verifyForm.style.display = 'block';
}
});
verifyForm.addEventListener('submit', async e => {
e.preventDefault();
const otp = document.getElementById('otp-input').value;
const data = {
phoneNumber: phoneNumber,
otp: top
};
const response = await fetch('/verify-otp', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
body: JSON.stringify(data)
}).catch(e => console.log(e));
const check = await response.json();
const text = response.ok ? check.status : response.statusText;
responseText.innerHTML = text;
verifyForm.style.display = 'none';
responseText.style.display = 'block';
});
EDIT Here is my index.js file:
const express = require('express');
const path = require('path');
require('dotenv').config();
const client = require('twilio')(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);
const app = express();
const port = process.env.PORT || 3000;
app.use(express.static(__dirname + '/public'));
app.use(express.urlencoded({extended: true}));
app.use(express.json());
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, '/views/index.html'));
});
app.post('/send-verification', async (req, res) => {
client.verify.services(verify)
.verifications
.create({to: `+${req.body.phoneNumber}`, channel: 'sms'})
.then(verification => console.log(verification.status))
.catch(e => {
console.log(e)
res.status(500).send(e);
});
res.sendStatus(200);
});
app.post('/verify-otp', async (req, res) => {
const check = await client.verify.services(verify)
.verificationChecks
.create({to: `+${req.body.phoneNumber}`, code: req.body.otp})
.catch(e => {
console.log(e)
res.status(500).send(e);
});
res.status(200).send(check);
});
app.listen(port);
console.log('Server started at http://localhost:' + port);
Your front-end is making a request to /send-notification but your application end point is at /send-verification.
Update your front-end code to:
const response = await fetch('/send-verification', {
and you should be good to go.
Edit
Now, in the server you are getting the error:
sh-3.2$ node index.js Server started at localhost:3000
/Users/username/Downloads/keep_out-3/verify-sms-express/index.js:17
client.verify.services(verify)
^ ReferenceError: verify is not defined
You have the line:
const check = await client.verify.services(verify)
In the blog post this is:
client.verify.services(process.env.VERIFY_SERVICE_SID);
So, you have replaced the verify service sid with a non-existant verify variable. Go back and make sure you have VERIFY_SERVICE_SID set in your .env file and then change the code back to the original, and then you should be good to go!

req.file is undefined when uploading image from front end

I have checked other similar post but its still not working: Its giving me undefined when console.log. I also defined the multer middleware according to other posts so I don't know what happened. But when I upload an image through postman it works with returning an 201as expected. Any help is appreciated!
ReactJS function:
const UploadImageToBackend = async () => {
console.log(UploadedImage) //UploadedImage is something like /Users/.../.jpg
let formData = new FormData()
formData.append('profile',
{name : new Date() + "_profile", uri: UploadedImage, type:'image/jpg'})
try{
const res = await client.post('/upload-avatar',formData, {
headers:{
Accept : 'application/json',
authorization: 'JWT some JWT'
},
})
console.log(res.data)
}catch(error){
console.log(error.response.data) //gives "Error while uploading Image, try after some time" error
}
}
Backend Routes:
const fileFilter = (req,file,callback) => {
if (file.mimetype.startsWith('image')){
callback(null,true)
}else{
callback('invalid image file', false)
}
}
const storage = multer.diskStorage({})
const uploads = multer({storage, fileFilter})
router.post('/upload-avatar',isAuth, uploads.single('profile'),uploadProfile)
backend upload function (to Cloudinary)
exports.uploadProfile = async (req,res)=>{
const user = req.user
if (!user){
return res.status(401).json({success:false,message:"unauthorized access!"})
}else{
console.log(req.file.path) //undefined
try{
const upload_result = await cloudinary.uploader.upload(req.file.path, {
public_id: `${user._id}_profile`,
width:500,
height:500,
crop: 'fill'
})
await User.findByIdAndUpdate(user._id, {avatar: upload_result.url})
res.status(201).json({success:true,message: "Profile picture successfully uploaded"})
}catch (error){
res.status(500).json({success:false,message:
"Error while uploading Image, try after some time"})
}
}
}
create this function (to upload into Cloudinary), e.g. "lib/cloudinary.js" and add this code:
import cloudinary from "cloudinary";
cloudinary.config({
cloud_name: "YOUR_CLOUD_NAME",
api_key: "YOUR_API_KEY",
api_secret: "YOUR_API_SECRET",
});
const upload = {};
upload.subir = async (file) => {
try {
const res = await cloudinary.uploader.upload(file);
// return the secure url
return res.secure_url;
} catch (error) {
return error;
}
}
export default upload;
Now in your controller, e.g. add this code, do not forget to install express-fileupload:
import cloudinary from "../lib/cloudinary.js";
const upload = {};
upload.uploadProfile = async (req, res) => {
const a_file = await cloudinary.subir(req.files.a_file.tempFilePath);
// show the secure url, e.g.:
// https://res.cloudinary.com/xx/image/upload/yy/winter.jpg
console.log(a_file);
// ... more code
}
export default upload;
Now in your main application e.g., "app.js" add this code to use the express middleware for uploading files:
import express from 'express';
import fileUpload from 'express-fileupload';
const app = express();
app.use(express.json());
app.use(express.urlencoded({extended: true}));
app.use(fileUpload({useTempFiles: true}));
// ... more code
Test the function using postman and the file has been uploaded
  NOTE: Do not forget and
remember that this only is an alternative, exist anothers many ways i hope you understand and i hope it works for you

constant display of uploaded image React

I have a page where i display a static image. I want to display there the image i just uploaded. For that I have implemented file upload using express-fileUpload on my server and its working fine, it gets the photo and saves it into a folder, but i cannot display it on my page ( after page refresh it disappears).
How could i make this image remain even after refresh?
server.js code:
require('dotenv').config()
const express = require('express')
const mongoose = require('mongoose')
const cookieParser = require('cookie-parser')
const Years = require('./models/yearModel')
const Users = require('./models/userModel')
const bcrypt = require("bcrypt");
const cors = require('cors')
const fileUpload = require('express-fileupload')
const app = express()
app.use(express.json())
app.use(cors())
app.use(cookieParser())
app.use(fileUpload())
app.post('/upload', (req, res) => {
if (req.files === null) {
return res.status(400).json({ msg: 'No file uploaded' });
}
const file = req.files.file;
const fileName = "orar.jpg"+file.name
file.mv(`${__dirname}/client/public/uploads/${fileName}`, err => {
if (err) {
console.error(err);
return res.status(500).send(err);
}
res.json({ fileName: file.name, filePath: `/uploads/${file.name}` });
});
});
const PORT = process.env.PORT || 5000
app.listen(PORT, () => {
console.log('Server running on port: ', PORT)
})
And this is the code of my page where i want to display the image ( without return markup ):
const Orar = () => {
const [file, setFile] = useState("");
const [filename, setFilename] = useState("Choose File");
const [uploadedFile, setUploadedFile] = useState({});
const onChange = (e) => {
setFile(e.target.files[0]);
setFilename(e.target.files[0].name);
};
const onSubmit = async (e) => {
e.preventDefault();
const formData = new FormData();
formData.append("file", file);
try {
const res = await axios.post("/upload", formData, {
headers: {
"Content-Type": "multipart/form-data",
}
});
const { fileName, filePath } = res.data;
setUploadedFile({ fileName, filePath });
setMessage("File Uploaded");
} catch (err) {
if (err.response.status === 500) {
setMessage("There was a problem with the server");
} else {
setMessage(err.response.data.msg);
}
}
};
I don't know the architecture of your website and database so if you stock only one image inside your website, you can store the id of the uploaded image inside your browser localstorage: link here (I don't recommend this practice).
A good practice is to store the id or path of your uploaded image inside your database. For example, if you want to edit or display a profile picture, go to your user schema (in your db), stock the id or the path of the uploaded image here. Then when you'll call the #GET /users/:userId, you will retrieve the image id or the image path (depends on which of them you stock).
If you retrieve the link to your image, just do that inside your html code:
<img src={myImageLocation} alt={myImageAlt} />
If you stock your image on a dedicated server (it's what you're doing), you can only retrieve the image id and render the image like that:
<img src={`${serverPATH}/${imageId}`} alt={myImageAlt} />

How to send SMS to a number stored in a JSON file?

I need to send SMS (by Twilio) to defined phone numbers, which are saved in the phone.json file when the submit button will be clicked.
I am using node.js
How am I going to do this?
This is how my phone.json looks:
[
{"Nombre": "Nombre1" ,
"Numero": "+34...."
},
{"Nombre": "Nombre2",
"Numero": "+34..."
}
]
In SMS.js I would create a function like this:
function submit() {
client.messages
.create({
body: "content",
from: "+....",
to: ""}) //this number should come from phone.json
.then(message => console.log(message.sid));
}
This is how my index.js looks:
const http =require('http');
const express = require('express');
const MessagingResponse = require('twilio').twiml.MessagingResponse;
const { fstat } = require('fs');
const { response } = require('express');
const info = require("./database.json");
const app = express();
app.use(express.static("public"));
app.use(express.urlencoded({extended: true}));
app.listen(8000, console.log(`Server running at http://localhost:8000`));
I would be very happy about every suggestion.
I'm assuming you want to do this server-side in Node.js, then you need fs to read the JSON and then you just loop over it in your submit() like this:
import fs from "fs"; // CommonJS syntax: const fs = require("fs");
phone_numbers = JSON.parse(fs.readFileSync("phone.json", "utf8"));
phone_numbers.forEach(function(item, index) {
console.log(item, index);
client.messages
.create({
body: "content",
from: "+....",
to: item["Numero"],
})
.then(message => console.log(message.sid));
});

How to download a video file into browser

I made the routes below in express to download a video from youtube, but the video file goes into my project folder and it is not downloaded into the browser. It's like it works only in localhost.
This is my project folder:
node_modules
src
-app.js
static
-index.html
-styles.css
package.json
'THE FILE DOWNLOADED'
This is the code i made
const express = require('express')
const router = express.Router()
const fs = require('fs')
const ytdl = require('ytdl-core')
const youtube = require('simple-youtube-api')
router.post('/downloadByUrl', async (req, res) => {
let url = req.body.url
await downloadVideo(url)
return res.redirect('/')
})
router.post('/downloadByName', async (req, res) => {
let videoName = req.body.videoName
let youtubeClient = new youtube('MY YOUTUBE API KEY')
await youtubeClient.searchVideos(videoName, 1)
.then(results => {
downloadVideo('https://youtu.be/' + results[0].id)
})
.catch(console.log)
return res.redirect('/')
})
function downloadVideo(URL) {
let videoReadableStream = ytdl(URL)
ytdl.getInfo(URL, (err, info) => {
let title = info.title.replace('|', '').toString('ascii')
let stream = videoReadableStream.pipe(fs.createWriteStream(title + '.mp4'))
stream.on('finish', () => {
console.log('Finished')
})
})
}
module.exports = router
I want to host my website so i want to make possible the download of the file into the 'download' section of the browser.
How can I do that?

Categories

Resources