Fluent-ffmpeg won't create video file sometime it will create? - node.js

anyone know the reason of this problem? what is the issue?
in this code, i am trying to convert a blob into video format. but sometime it is working and sometime not. can anyone help me in this?
const recordVideo = require('../model/recordVideo_model')
const { join, dirname } = require('path');
const { fileURLToPath } = require('url')
const { mkdir, open, unlink, writeFile } = require('fs/promises');
const {Blob, Buffer} = require('buffer');
const { path } = require('#ffmpeg-installer/ffmpeg');
const ffmpeg = require('fluent-ffmpeg');
ffmpeg.setFfmpegPath(path)
// const __dirname = dirname(fileURLToPath(import.meta.url));
const saveData = async(data, roomid, course_id)=>{
//console.log(data);
const videoPath = join(__dirname, '../video');
//final folder name
//const dirName = new Date().toLocaleDateString().replace(/\./g, '_');
const dirName = roomid;
// console.log(`dirName: ${dirName}`);
//const dirPath = `${videoPath}/${dirName}`;
const dirPath = `./public/video/canvideo/${dirName}`;
const fileName= `${Date.now()}-${roomid}.webm`;
//const fileName= `${roomid}.webm`;
const tempFilePath = `${dirPath}/temp-${fileName}`;
const finalFilePath = `${dirPath}/${fileName}`;
let fileHandle;
try {
fileHandle = await open(dirPath);
console.log(`open the file${fileHandle}`)
}
catch {
await mkdir(dirPath);
console.log(`making directory${fileHandle}`)
}
finally {
if (fileHandle) {
fileHandle.close();
console.log(`closing ${fileHandle}`)
}
}
try {
const videoBlob = new Blob(data, {
type: 'video/webm'
})
const videoBuffer = Buffer.from(await videoBlob.arrayBuffer())
const res = await recordVideo.findOne({roomid:roomid, recordType:'canvas'})
if(!res){
await writeFile(tempFilePath, videoBuffer)
await ffmpeg(tempFilePath)
.outputOptions([
'-c:v libvpx-vp9',
'-c:a copy',
'-crf 35',
'-b:v 0',
'-vf scale=1280:720','-max_muxing_queue_size 1024'
])
.on('end', async () => {
await unlink(tempFilePath)
console.log(`*** File ${fileName} created`)
//insert database entry (recorded video entry with same details roomid, finename, finalfilepath, created at)
await recordVideo.create({roomid:roomid,filename:fileName,filePath:finalFilePath,recordType:'canvas', courseid:course_id});
}).on('error', function(err) {
console.log('An error occurred: ' + err.message);
})
.save(finalFilePath, dirPath);
}
}
catch (e) {
console.log('*** Erro in code ', e)
}
}
module.exports = {saveData,};
if any help me in this. it would be great for me.
in this code, i am trying to convert a blob into video format. but sometime it is working and sometime not. can anyone help me in this?

Related

Cloudinary uploader.upload executed after next async command in file

I'm trying to upload file with Multer and cloudinary node.js api and then remove temp file from hard drive, however file gets deleted before upload finished. Then I commented unlink files uploaded correctly
Here is my controller
const createGame = async (req, res) => {
const options = {
use_filename: true,
unique_filename: false,
overwrite: true,
};
try {
const data = req.body;
const files = req.files;
let posterPath = "";
let videoPath = "";
let distroPath = "";
if (files?.poster?.length) {
posterPath = files?.poster[0]?.path || "";
try {
const newPath = await uploader.upload(posterPath, options);
// Bug - unlink happens before file uploaded
await unlink(posterPath);
posterPath = newPath as string;
} catch (err) {
// Upload failure - remove files from disk
await unlink(posterPath);
posterPath = "";
}
}
if (files?.video?.length) {
videoPath = files?.video[0]?.path || "";
try {
const newPath = await uploader.upload(videoPath, {
...options,
resource_type: "video",
});
// Bug - unlink happens before file uploaded
await unlink(videoPath);
videoPath = newPath as string;
} catch (err) {
// Upload failure - remove files from disk
await unlink(videoPath);
videoPath = "";
}
}
const currentPublisher = await publishersRepository.findOneBy({
id: req.user.id,
});
if (!currentPublisher) {
res.status = 301;
return res.json({
message:
"You must be authenticated as publisher in order to add a game",
});
}
const newGameData = gamesRepository.create({
...data,
poster: posterPath,
video: videoPath,
distro: distroPath,
publisher: currentPublisher,
});
const newGame = await gamesRepository.save(newGameData);
res.status(200);
return res.json({ message: "Game added", data: newGame });
} catch (err) {
console.log("Error creating the game", err);
res.status(400);
return res.json({ message: "Error creating the game" });
}
};
I'm assuming you're using just one multer instance.
From what I looked at the docs of multer, the upload function is not a Promise. So the await function in front of uploader.upload method will not work.
What you need is to promisify your upload function. Here's an example:
const util = require('util');
// your code ...
try {
const promisifiedUploadFunc = util.promisify(uploader.upload);
const newPath = await promisifiedUploadFunc(posterPath, options);
// Bug - unlink happens before file uploaded
await unlink(posterPath);
posterPath = newPath as string;
} catch (e) {
// continue code..
}

image resize on node.js

I want to save images after resize so used sharp package but dont small image size.Iadded await sharp(uploadImage.name).resize(600, 600); line after save folder What am I missing?
const path = require('path');
const fs = require('fs');
const AdminBro = require('admin-bro');
const sharp=require('sharp');
/** #type {AdminBro.After<AdminBro.ActionResponse>} */
const after = async (response, request, context) => {
const { record, uploadImage } = context;
if (record.isValid() && uploadImage) {
// console.log(uploadImage.name);
await sharp(uploadImage.name).resize(600, 600);
const filePath = path.join('uploads', record.id().toString(), uploadImage.name);
await fs.promises.mkdir(path.dirname(filePath), { recursive: true });
await fs.promises.rename(uploadImage.path, filePath);
await record.update({ imagePath: `/${filePath}` });
}
return response;
};
/** #type {AdminBro.Before} */
const before = async (request, context) => {
if (request.method === 'post') {
const { uploadImage, ...otherParams } = request.payload;
// eslint-disable-next-line no-param-reassign
context.uploadImage = uploadImage;
return {
...request,
payload: otherParams,
};
}
return request;
};
module.exports = { after, before };
const filePath = path.join('uploads', record.id().toString(), uploadImage.name);
await fs.promises.mkdir(path.dirname(filePath), { recursive: true });
await sharp(uploadImage.path).withMetadata().resize(600,600).toFile(filePath);//here added correct paths but now although it saved image, doesnt reduce imageSize
You are not writing the processed image to a file.
Let's say this is your storage path:
const outputPath = __dirname + `/../storage/myImage.jpeg`;
You can give that path to sharp
await sharp('path/of/originalImage').withMetadata().resize(600, 600).toFile(outputPath);
And I highly recommend you to use withMetaData() otherwise you lose your images metaData

Finding the differences between 2 files in nodejs

I have 2 json files which have static data.
File A.json
{
"data": ["A","B","C","D"]
}
File B.json
{
"data":["A","B","C"]
}
Now I want find the difference between these two files.
I tried using this code to get files by its name
const express = require("express");
const jsonfile = require("jsonfile");
const app = express();
const fs = require("fs");
app.use(express.json());
const BASEPATH = "./data"
app.get("/api/v1/data/:name", async (req,res) => {
const fileName = req.params.name;
const filePath = `${BASEPATH}/${fileName}.json`
try {
const readData = await jsonfile.readFile(filePath);
res.status(200).json(readData);
}catch (e) {
res.status(404).send(e);
}
});
The URL is : localhost:3000/api/v1/data/A
To add data I used,
app.put("/api/v1/data",(req,res) => {
const fileName = req.body.name;
const data = req.body.data;
const filePath = `${BASEPATH}/${fileName}.json`
fs.exists(filePath, async exists => {
if(exists) {
try {
await jsonfile.writeFile(filePath,{data:data});
res.status(200).send();
}catch(e) {
res.send(500).json(e);
}
} else {
try {
await jsonfile.writeFile(filePath,{data:data});
res.status(201).send();
}catch(e) {
res.send(500).json(e);
}
}
})
});
Example of added data:
{ "name":"C", "data":["A","B","Z"]}
URL is: localhost:3000/api/v1/data
you can try like this,
app.get("/api/v1/data/diff", async (req,res) => {
try {
const file1 = req.query.file1;
const file2 = req.query.file2;
console.log(file1,file2)
if(file1 === undefined || file2 === undefined ) {
res.status(401).send("BAD REQUEST. SEND FILE NAMES");
return;
} else {
const filePath1 = `${BASEPATH}/${file1}.json`
const filePath2 = `${BASEPATH}/${file2}.json`
const file1Data = await jsonfile.readFile(filePath1);
const file2Data = await jsonfile.readFile(filePath2);
let difference = file1Data.data.filter(x => !file2Data.data.includes(x));
let difference2 = file2Data.data.filter(x => !file1Data.data.includes(x));
res.status(200).json({diff: [...difference,...difference2]});
}
}catch(e) {
res.status(500).json(e);
}
});
you have to use the url like : localhost:3000/api/v1/data/diff?file1=A&file2=B
the output will be
{
"diff": [
"D"
]
}

Azure Function NodeJS: blobService.createAppendBlobFromLocalFile Promise does not resolve

I am new to azure functions and I am currently just trying to save an image as a blob to my storage. However, my Promise never resolve but the functions ends successfully. The image exists in my directory.
Here is my code so far:
module.exports = async function (context, req) {
const path = require('path');
const storage = require('azure-storage');
const STORAGE_ACCOUNT_NAME = 'something';
const ACCOUNT_ACCESS_KEY = 'also something';
const blobService = storage.createBlobService(STORAGE_ACCOUNT_NAME, ACCOUNT_ACCESS_KEY);
const filePath = './product-example.jpg';
function uploadLocalFile (filePath) {
return new Promise((resolve, reject) => {
const fullPath = path.resolve(filePath);
context.log('before call');
blobService.createAppendBlobFromLocalFile('productimageupload', 'image-upload-post', fullPath, function(err) {
if(err) {
context.log('err');
reject(err);
} else {
context.log('resolve');
resolve({message: 'resolved successfully'});
}
});
});
};
const output = uploadLocalFile(filePath);
context.log(output);
};
Here is the Protokoll output when executing the function:
2019-04-23T11:03:46 Welcome, you are now connected to log-streaming service.
2019-04-23T11:03:59.185 [Information] Executing 'Functions.branding-tool-app' (Reason='This function was programmatically called via the host APIs.', Id=xyz)
2019-04-23T11:04:00.793 [Information] before call
2019-04-23T11:04:00.794 [Information] Promise { <pending> }
2019-04-23T11:04:00.926 [Information] Executed 'Functions.xyz' (Succeeded, Id=xzy)
As you can see the Promise has still the status 'pending' and is not resolve in the createBlob function. What am I doing wrong here?
Here is the complete function for uploading localfile to blob
await uploadLocalFile(aborter, containerURL, localFilePath);
console.log(`Local file "${localFilePath}" is uploaded`);
async function uploadLocalFile(aborter, containerURL, filePath) {
filePath = path.resolve(filePath);
const fileName = path.basename(filePath);
const blockBlobURL = BlockBlobURL.fromContainerURL(containerURL, fileName);
return await uploadFileToBlockBlob(aborter, filePath, blockBlobURL);
}
For reference i am passing the complete quick start functionality.
const {
Aborter,
BlockBlobURL,
ContainerURL,
ServiceURL,
SharedKeyCredential,
StorageURL,
uploadStreamToBlockBlob,
uploadFileToBlockBlob
} = require('#azure/storage-blob');
const fs = require("fs");
const path = require("path");
if (process.env.NODE_ENV !== "production") {
require("dotenv").config();
}
const STORAGE_ACCOUNT_NAME = process.env.AZURE_STORAGE_ACCOUNT_NAME;
const ACCOUNT_ACCESS_KEY = process.env.AZURE_STORAGE_ACCOUNT_ACCESS_KEY;
const ONE_MEGABYTE = 1024 * 1024;
const FOUR_MEGABYTES = 4 * ONE_MEGABYTE;
const ONE_MINUTE = 60 * 1000;
async function showContainerNames(aborter, serviceURL) {
let response;
let marker;
do {
response = await serviceURL.listContainersSegment(aborter, marker);
marker = response.marker;
for(let container of response.containerItems) {
console.log(` - ${ container.name }`);
}
} while (marker);
}
async function uploadLocalFile(aborter, containerURL, filePath) {
filePath = path.resolve(filePath);
const fileName = path.basename(filePath);
const blockBlobURL = BlockBlobURL.fromContainerURL(containerURL, fileName);
return await uploadFileToBlockBlob(aborter, filePath, blockBlobURL);
}
async function uploadStream(aborter, containerURL, filePath) {
filePath = path.resolve(filePath);
const fileName = path.basename(filePath).replace('.md', '-stream.md');
const blockBlobURL = BlockBlobURL.fromContainerURL(containerURL, fileName);
const stream = fs.createReadStream(filePath, {
highWaterMark: FOUR_MEGABYTES,
});
const uploadOptions = {
bufferSize: FOUR_MEGABYTES,
maxBuffers: 5,
};
return await uploadStreamToBlockBlob(
aborter,
stream,
blockBlobURL,
uploadOptions.bufferSize,
uploadOptions.maxBuffers);
}
async function showBlobNames(aborter, containerURL) {
let response;
let marker;
do {
response = await containerURL.listBlobFlatSegment(aborter);
marker = response.marker;
for(let blob of response.segment.blobItems) {
console.log(` - ${ blob.name }`);
}
} while (marker);
}
async function execute() {
const containerName = "demo";
const blobName = "quickstart.txt";
const content = "hello!";
const localFilePath = "./readme.md";
const credentials = new SharedKeyCredential(STORAGE_ACCOUNT_NAME, ACCOUNT_ACCESS_KEY);
const pipeline = StorageURL.newPipeline(credentials);
const serviceURL = new ServiceURL(`https://${STORAGE_ACCOUNT_NAME}.blob.core.windows.net`, pipeline);
const containerURL = ContainerURL.fromServiceURL(serviceURL, containerName);
const blockBlobURL = BlockBlobURL.fromContainerURL(containerURL, blobName);
const aborter = Aborter.timeout(30 * ONE_MINUTE);
console.log("Containers:");
await showContainerNames(aborter, serviceURL);
await containerURL.create(aborter);
console.log(`Container: "${containerName}" is created`);
await blockBlobURL.upload(aborter, content, content.length);
console.log(`Blob "${blobName}" is uploaded`);
await uploadLocalFile(aborter, containerURL, localFilePath);
console.log(`Local file "${localFilePath}" is uploaded`);
await uploadStream(aborter, containerURL, localFilePath);
console.log(`Local file "${localFilePath}" is uploaded as a stream`);
console.log(`Blobs in "${containerName}" container:`);
await showBlobNames(aborter, containerURL);
const downloadResponse = await blockBlobURL.download(aborter, 0);
const downloadedContent = downloadResponse.readableStreamBody.read(content.length).toString();
console.log(`Downloaded blob content: "${downloadedContent}"`);
await blockBlobURL.delete(aborter)
console.log(`Block blob "${blobName}" is deleted`);
await containerURL.delete(aborter);
console.log(`Container "${containerName}" is deleted`);
}
execute().then(() => console.log("Done")).catch((e) => console.log(e));
Reference
https://github.com/Azure-Samples/azure-storage-js-v10-quickstart

Async Recursive File System Traversal

I am trying to compile an array out of data present in some specific files, using a recursive approach to read directories and the file system methods are asynchronous. I am unable to figure out the apt place for the callback invocation.
const fs = require('fs');
const ENTRY = "../a/b";
const FILE_NAME = 'index.json';
var nodes = [];
function doThisOnceDone() {
console.log(nodes);
}
function readFile(path) {
fs.readFile(path + '/' + FILE_NAME,{
encoding:"UTF-8"
}, function(err, data) {
if(err) {
return;
}
nodes.push(data);
});
}
function compileArray(path, callback) {
fs.readdir(path, {
encoding:"UTF-8"
}, function(err, files) {
if(err) {
console.error(err);
return;
}
files.forEach(function(file) {
var nextPath = path + '/' + file;
fs.stat(nextPath, function(err, stats) {
if(err) {
return;
}
if(stats.isDirectory()) {
if(file === 'specific') {
readFile(nextPath);
}
else {
compileArray(nextPath);
}
}
});
});
});
}
compileArray(ENTRY, doThisOnceDone);
When do I know that the recursion tree has been done with , and I can access the nodes array ?
Try this
const util = require('util');
const fs = require('fs');
const stat = util.promisify(fs.stat);
const readFile = util.promisify(fs.readFile);
const readdir = util.promisify(fs.readdir);
const ENTRY = "../a/b";
const FILE_NAME = 'index.json';
var nodes = [];
const compileArray = async (path) => {
try {
const files = await readdir(path);
files.forEach((file) => {
try {
var nextPath = path + '/' + file;
const stats = await stat(nextPath); //check other conditions
if (file === 'specific') {
const data = await readFile(path + '/' + FILE_NAME, {
encoding: "UTF-8"
});
nodes.push(data);
}
} catch (error) {
console.log(error);
}
});
} catch (error) {
console.log(error);
}
}
const util = require('util');
const fs = require('fs');
const stat = util.promisify(fs.stat);
const readFile = util.promisify(fs.readFile);
const readdir = util.promisify(fs.readdir);
const ENTRY = "../a/b";
const FILE_NAME = 'index.json';
var nodes = [];
const compileArray = async (path) => {
try {
const files = await readdir(path);
files.forEach(async (file) => {
try {
var nextPath = path + '/' + file;
const stats = await stat(nextPath); //check other conditions
if (file === 'specific') {
const data = await readFile(path + '/' + FILE_NAME, {
encoding: "UTF-8"
});
nodes.push(data);
}
} catch (error) {
console.log(error);
}
});
} catch (error) {
console.log(error);
}
}
compileArray(ENTRY)

Resources