Running Graphicsmagick as a AWS Lambda layer - node.js

I'm trying to setup a Lambda layer to add a watermark to images with Graphicsmagick. I'm however a bit stuck at getting the binary to work with the libraries, so how do I setup a link to the libraries within the child process?
So far I've built the Graphicsmagick binary with the following options:
./configure --prefix=/opt/graphicsmagick --enable-shared=no --enable-static=yes --disable-shared --disable-installed
Pretty much followed the instructions on this answer and ideas from this Gist. Either one however does not concern running binaries as a layer. So wondering maybe there are some specifics to that which I'm missing here?
Heres the code from my handler:
module.exports.run = async (event, context, callback) => {
process.env['IM_PATH'] = '/opt/graphicsmagick/bin/'
process.env['LD_LIBRARY_PATH'] = '/opt/graphicsmagick/lib'
process.env['DYLD_LIBRARY_PATH'] = '/opt/graphicsmagick/lib'
process.env['MAGICK_HOME'] = '/opt/graphicsmagick/'
...
const graphicsmagick = '/opt/graphicsmagick/bin/gm'
const graphicsmagickArgs = [
'-dissolve', '15',
'-tile',
watermark,
inputImage,
output,
]
spawn(graphicsmagick, graphicsmagickArgs, { stdio: 'inherit' })
.on('close', () => console.log('success'))
.on('error', error => console.log('error', error))
...
}
I've also tried running an exec with the environment variables like so:
exec('/opt/graphicsmagick/bin/gm', { env:
{
'IM_PATH': `/opt/graphicsmagick/bin/`,
'LD_LIBRARY_PATH': '/opt/graphicsmagick/lib',
'DYLD_LIBRARY_PATH': '/opt/graphicsmagick/lib',
'MAGICK_HOME': `/opt/graphicsmagick/`,
}}, (err, stdout, stderr) => {
console.log('error', err)
console.log('stdout', stdout)
console.log('stderr', stderr)
})
The layer runs Graphicsmagick but does not find the libraries folder. I get the following error in the console:
/opt/graphicsmagick/bin/gm: error while loading shared libraries:libpng15.so.15: cannot open shared object file: No such file or directory

Related

How can I modify 'index.js' on '.nuxt' in order to execute cpp program which gets connected to nodejs server?

I'm a newbie to nodejs and currently working to run a certain cpp program running on a nodejs server with a click on a button.
After googling for a while, I've found that I can use something called 'Child process' to execute cpp program from a server side. And I've tried to include the following code in 'index.js' in '.nuxt' folder.
const { exec, spawn } = require("child_process");
exec('"C:\\Projects\\Monitoring_and_Diagnosis\\socketgraph\\build\\" spectrum_sim_cu', (error, stdout, stderr) => {
if (error) {
console.log(`error: ${error.message}`);
return;
}
if (stderr) {
console.log(`stderr: ${stderr}`);
return;
}
const child = spawn("./spectrum_sim_cu"); //where a is the exe file generated on compiling the code.
child.stdin.write("-10 10 (5/260) 70.03 0");
child.stdin.end();
child.stdout.on("data", (data) => {
console.log(`child stdout:\n${data}`);
});
});
I thought 'index.js' would be the right place to insert the above code since my cpp program needs to run and connect with the server as the nodejs server starts up. However, the whole '.nuxt' folder seems to be refreshed when I type 'npm run dev' to run the server.
Is it the right place or approach to run the cpp program on nodejs server.
Can anyone help me out please?
Thanks in advance.

cannot find ffmpeg in videoshow in nodejs

I want to create video from image files. So I have installed videoshow module. And configured the same as per the documentaion.
var videoOptions = {
fps: 25,
loop: 5, // seconds
transition: true,
transitionDuration: 1, // seconds
videoBitrate: 1024,
videoCodec: 'libx264',
size: '640x?',
audioBitrate: '128k',
audioChannels: 2,
format: 'mp4',
pixelFormat: 'yuv420p'
}
var images = [
"D:/PROJECTS/Video/storage/1.jpg",
"D:/PROJECTS/Video/storage/2.jpg"
];
app.get("/video", function () {
videoshow(images, videoOptions)
// .audio('song.mp3')
.save('video.mp4')
.on('start', function (command) {
console.log('ffmpeg process started:', command)
})
.on('error', function (err, stdout, stderr) {
console.error('Error:', err)
console.error('ffmpeg stderr:', stderr)
})
.on('end', function (output) {
console.error('Video created in:', output)
})
});
But When I run it shows the error on server
Error: Error: Cannot find ffmpeg
at D:\PROJECTS\Video\node_modules\videoshow\node_modules\fluent-ffmpeg\lib\processor.js:136:22
at D:\PROJECTS\Video\node_modules\videoshow\node_modules\fluent-ffmpeg\lib\capabilities.js:123:9
at D:\PROJECTS\Video\node_modules\videoshow\node_modules\async\dist\async.js:473:16
at next (D:\PROJECTS\Video\node_modules\videoshow\node_modules\async\dist\async.js:5315:29)
at D:\PROJECTS\Video\node_modules\videoshow\node_modules\async\dist\async.js:958:16
at D:\PROJECTS\Video\node_modules\videoshow\node_modules\fluent-ffmpeg\lib\capabilities.js:116:11
at D:\PROJECTS\Video\node_modules\videoshow\node_modules\fluent-ffmpeg\lib\utils.js:223:16
at F (D:\PROJECTS\Video\node_modules\videoshow\node_modules\which\which.js:68:16)
at E (D:\PROJECTS\Video\node_modules\videoshow\node_modules\which\which.js:80:29)
at D:\PROJECTS\Video\node_modules\videoshow\node_modules\which\which.js:89:16
Then I installed ffmpeg using
npm install ffmpeg --save
but not worked. So I tried installing at the global level using
npm install ffmpeg -g
Even installing on my window machine and setting the path of its bin folder in environment variables did not work?
What could be the issue?
Actually, I need to instal the ffmpeg in my system and set it to the environment path variable.
And you don't need to install in nodejs.
npm i videoshow
Just use this command

Strange behavior of node js spawn/exec with unzipped content

I'm trying to write a client which installs and updates packages using nodejs with mqtt. I tested all functionalities of data transfer and archiving but when I came to windows environment and actualy tried to run some scripts I came to some strange errors.
I will add some code so anyone can see exacly how I write downloaded content to disk but first I will explain behaviour.
Steps taken for each itteration:
download content from mqtt (works)
create buffer and stream from it (works)
unzip stream to disk (works)
run batch job in downloaded content (strange things happen)
run another batch job (even stranger)
Strange things: At first try spawn/exec respoonses with: error spawn cmd.exe ENOENT, but at second try (triggered by topic subscription) it goes over that stage. But the next itteration when first batch job passes second job returns Error: EBUSY: resource busy or locked, open C:\...appt#0.0.1\nssm.exe' where nssm.exe is file called from batch job
Code for downloading and extraction:
const debug = require('debug')('service-manager:functions:download')
const serviceBus = require('../helpers/mqtt-helper.js')
const stream = require('stream')
const unzip = require('unzip-stream')
module.exports = (service, to, from) => {
debug(`Downloading ${service}#${to}`)
return serviceBus.getFromBus(`service_manager/${service}/${to}`)
.then(data => {
debug(`Downloaded ${service}#${to}`)
return new Promise((resolve, reject) => {
debug(`Unzipping ${service}#${to}`)
const buffer = Buffer.from(data)
const bufferStream = new stream.PassThrough()
bufferStream.end(buffer)
bufferStream.pipe(unzip.Extract({
path: `${__dirname}/../../services/active/${service}#${to}`
})).on('finish', resolve)
}).then(() => {
debug(`Unzipped ${service}#${to}`)
})
})
}
Code used to run batch jobs:
const debug = require('debug')('service-manager:functions:runner')
const { exec } = require('child_process')
const { resolve } = require('path')
module.exports = (type, reverse) => (service, to, from) => {
return new Promise((resolve, reject) => {
debug(`Running ${type} for ${service}#${reverse ? from : to}`)
const batchFile = resolve(
`../../services/active/${service}#${reverse ? from : to}/${type}.sh`
)
exec(batchFile, (error, stdout, stderr) => {
if (error) {
return reject(error)
}
debug(`Gotten STDOUT on ${type} for ${service}#${reverse ? from : to}: ${stdout}`)
debug(`Gotten STDERR on ${type} for ${service}#${reverse ? from : to}: ${stderr}`)
return resolve()
})
})
}
It turns out that unzip-stream called finish and close event before files were written on dist which resulted in files not being accessible to run with batch script. I swaped libraries and it worked.

How to decompress gzip files in Node.js

I want to unzip gzip files in Node.js I've tried [some] packages but nothing is working. Can you provide a package with sample code which can decompress gzip files in Node.js?
gunzip-file node package worked fine!
Do:
npm install gunzip-file
Then:
'use strict'
const gunzip = require('gunzip-file')
// 'sitemap.xml.gz' - source file
// 'sitemap.xml' - destination file
// () => { ... } - notification callback
gunzip('sitemap.xml.gz', 'sitemap.xml', () => {
console.log('gunzip done!')
})
Finally, run with Node at your shell.
I would suggest to use zlib.Gunzip.
Function prototype is zlib.Gunzip(buf, callback). The first argument is the raw archive data as a buffer that you want to extract, the second one is a callback which accept two arguments (result and error).
An implementation would be:
zlib.Gunzip(raw_data, function (error, result) {
if (error) throw error;
// Access data here through result as a Buffer
})
You can use tar.gz npm package to take care of this problem.
write following method to extract it to specific path:
targz().extract('/bkp/backup.tar.gz', '/home/myuser')
.then(function(){
console.log('Job done!');
})
.catch(function(err){
console.log('Something is wrong ', err.stack);
});
For more details you can follow this link
To unzip files in a directory:
To zip files in a directory:
More information:
https://medium.com/#harrietty/zipping-and-unzipping-files-with-nodejs-375d2750c5e4

How To Execute Windows Shell Commands (Cmd.exe) with Node JS

I would like to
C:\>ACommandThatGetsData > save.txt
But instead of parsing and saving the data in the console, I would like to do the above command with Node.JS
How to execute a shell command with Node.JS?
Use process.execPath():
process.execPath('/path/to/executable');
Update
I should have read the documentations better.
There is a Child Process Module which allows to execute a child process. You will need either child_process.exec, child_process.execFile or child_process.spawn. All of these are similar in use, but each has its own advantages. Which of them to use depends on your needs.
You could also try the node-cmd package:
const nodeCmd = require('node-cmd');
nodeCmd.get('dir', (err, data, stderr) => console.log(data));
On newer versions of the package, the syntax changed a little:
const nodeCmd = require('node-cmd');
nodeCmd.run('dir', (err, data, stderr) => console.log(data));
I know this question is old, but it helped me get to my solution using promises.
Also see: this question & answer
const util = require('util');
const exec = util.promisify(require('child_process').exec);
async function runCommand(command) {
const { stdout, stderr, error } = await exec(command);
if(stderr){console.error('stderr:', stderr);}
if(error){console.error('error:', error);}
return stdout;
}
async function myFunction () {
// your code here building the command you wish to execute ...
const command = 'dir';
const result = await runCommand(command);
console.log("_result", result);
// your code here processing the result ...
}
// just calling myFunction() here so it runs when the file is loaded
myFunction();

Resources