Using NodeJS to combine a png and mp3 to make a mp4 - node.js

So I am trying to combine a mp3 file and png with nodejs to make a mp4 file. I tried searching for modules and such, but cannot find one.

You can use the fluent-ffmpeg package:
For example of how ot work, here is an example of resizing a mp4:
var ffmpeg = require( 'fluent-ffmpeg' );
ffmpeg( path.join( toDirectory, newVideo._id + '.orig.mp4' ) )
.size( '1024x576' )
.fps( 25 )
.videoCodec( 'libx264' )
.videoBitrate( '1024k' )
.output( path.join( toDirectory, newVideo._id + '.mp4' ) )
.audioBitrate( '92k' )
.audioFrequency( 48000 )
.audioChannels( 2 )
.run();
For creating a mp4 from image with sound (Not tested):
var ffmpeg = require( 'fluent-ffmpeg' );
let newMp4 = ffmpeg();
newMp4
.input("./test.png")
.input("./another.png")
.addInput('/path/to/audio.file')
.save("./test.mp4")
.outputFPS(1) // Control FPS
.frames(2) // Control frame number
.on('end', () => {
console.log("done");
});

I do recommend using ffmpeg, by using this npm package https://www.npmjs.com/package/ffmpeg.
I think this answer would help you creating mp4 from png images and audio How to create a video from images with FFmpeg?

Related

Node.js : How can I add meta data to an audio file?

I have a .wav audio file that I would like to add meta data to, in Node.js:
let original = fs.readFileSync('./somewhere/something.wav').toString('base64')
let withMeta = addMeta(original)
fs.writeFileSync('./somewhere/something-more.wav', withMeta)
Is this possible ? Is there some Js library that allows you to write metadata (not just read/extract it) to an existing audio file.
Assuming you have ffmpeg on your system, you could use that in node via fluent-ffmpeg doing something like the following:
const ffmpeg = require('fluent-ffmpeg')
ffmpeg('./somewhere/something.wav')
.audioCodec('copy')
.outputOptions(
'-metadata', 'title=testtitle',
'-metadata', 'artist=testartist'
)
.output('./somewhere/something-more.wav')
.on('end', () => { console.log('done') })
.run()
Acceptable metadata keys for wave files in ffmpeg are: (source)
artist
comment
copyright
date
genre
language
title
album
track
encoder
timecode
encoded_by

Pass multiple input files to ffmpeg using a single stream in Node

I'm trying to use ffmpeg to merge multiple video files. Every file has the same encoding, and they just need to be stitched together. The problem I'm having is that I'd like to do this using streams, but ffmpeg only supports one input stream per command.
Since the files have the same encoding, I thought I could merge them into a single stream, and feed it as an input to ffmpeg.
const CombinedStream = require("combined-stream")
const ffmpeg = require("fluent-ffmpeg")
const AWS = require("aws-sdk")
const s3 = new AWS.S3()
const merge = ({ videos }) => {
const combinedStream = CombinedStream.create();
videos //I take my videos from S3 and merge them
.map((video => {
return s3
.getObject({
Bucket: "myAWSBucketName",
Key: video
})
.createReadStream()
}))
.forEach(stream => {
combinedStream.append(stream)
})
ffmpeg()
.input(combinedStream)
.save("/tmp/file.mp4")
}
merge({ videos: ["video1.mp4", "video2.mp4"]})
I was hoping ffmpeg could read the files from the single stream and output them together, but I got this error instead:
Error: ffmpeg exited with code 1: pipe:0: Invalid data found when processing input
Cannot determine format of input stream 0:0 after EOF
Error marking filters as finished
Conversion failed!
Can anyone help me?

HLS from node to iOS app

I created a API in node that you can upload a video (.mp4, .avi, etc). Then, the video is request by a iOS app in swift.
I would like to use HTTP Live streaming from the app. Can you help me how can I transform the video file to chunks .ts and generate the playlist file (m3u8) to be consumed by the app?
This is the correct flow?
What it's the best solution?
Thanks!
Finally I have a solution, I use fluent-ffmpeg like this :
var ffmpeg = require('fluent-ffmpeg');
ffmpeg(video, { timeout: 432000 })
.addOption('-level', 3.0)
// size
.addOption('-s','640x360')
// start_number
.addOption('-start_number', 0)
// set hls segments time
.addOption('-hls_time', 10)
// include all the segments in the list
.addOption('-hls_list_size', 0)
// format -f
.format('hls')
// setup event handlers
.on('start', function(cmd) {
console.log('Started ' + cmd);
})
.on('error', function(err) {
logger.error('an error happened: ' + err.message);
})
.on('end', function() {
logger.debug('File has been converted succesfully');
})
.save(outputDir)
ffmpeg comes with HLS streaming capability.
ffmpeg -i "input" output.m3u8
For more information visit: ffmpeg hls documentation

fluent-ffmpeg thumbnail creation error

i try to create a video thumbnail with fluent-ffmpeg here is my code
var ffmpeg = require('fluent-ffmpeg');
exports.thumbnail = function(){
var proc = new ffmpeg({ source: 'Video/express2.mp4',nolog: true })
.withSize('150x100')
.takeScreenshots({ count: 1, timemarks: [ '00:00:02.000' ] }, 'Video/', function(err, filenames) {
console.log(filenames);
console.log('screenshots were saved');
});
}
but i keep getting this error
"mate data contains no duration, aborting screenshot creation"
any idea why,
by the way am on windows, and i put the ffmpeg folder in c/ffmpeg ,and i added the ffmpeg/bin in to my environment varableļ¼Œ i dont know if fluent-ffmpeg need to know the path of ffmpeg,but i can successfully create a thumbnail with the code below
exec("C:/ffmpeg/bin/ffmpeg -i Video/" + Name + " -ss 00:01:00.00 -r 1 -an -vframes 1 -s 300x200 -f mjpeg Video/" + Name + ".jpg")
please help me!!!
I think the issue can be caused by the .withSize('...') method call.
The doc says:
It doesn't interract well with filters. In particular, don't use the size() method to resize thumbnails, use the size option instead.
And the size() method is an alias of withSize().
Also - but this is not the problem in your case - you don't need to set either the count and the timemarks at the same time. The doc says:
count is ignored when timemarks or timestamps is specified.
Then you probably could solve with:
const ffmpeg = require('fluent-ffmpeg');
exports.thumbnail = function(){
const proc = new ffmpeg({ source: 'Video/express2.mp4',nolog: true })
.takeScreenshots({ timemarks: [ '00:00:02.000' ], size: '150x100' }, 'Video/', function(err, filenames) {
console.log(filenames);
console.log('screenshots were saved');
});
}
Have a look at the doc:
https://github.com/fluent-ffmpeg/node-fluent-ffmpeg#screenshotsoptions-dirname-generate-thumbnails
FFmpeg needs to know the duration of a video file, while most videos have this information in the file header some file don't, mostly raw videos like a raw H.264 stream.
A simple solution could be to remux the video prior to take the snapshot, the FFmpeg 0.5 command for this task it's quite simple:
ffmpeg -i input.m4v -acodec copy -vcodec copy output.m4v
This command tells FFmpeg to read the "input.m4v" file, to use the same audio encoder and video encoder (no encoding at all) for the output, and to output the data into the file output.m4v.
FFmpeg automatically adds all extra metadata/header information needed to take the snapshot later.
Try this code to create thumbnails from Video
// You have to Install Below packages First
var ffmpegPath = require('#ffmpeg-installer/ffmpeg').path;
var ffprobePath = require('#ffprobe-installer/ffprobe').path;
var ffmpeg = require('fluent-ffmpeg');
ffmpeg.setFfmpegPath(ffmpegPath);
ffmpeg.setFfprobePath(ffprobePath);
var proc = ffmpeg(sourceFilePath)
.on('filenames', function(filenames) {
console.log('screenshots are ' + filenames.join(', '));
})
.on('end', function() {
console.log('screenshots were saved');
})
.on('error', function(err) {
console.log('an error happened: ' + err.message);
})
// take 1 screenshots at predefined timemarks and size
.takeScreenshots({ count: 1, timemarks: [ '00:00:01.000' ], size: '200x200' }, "Video/");

how to generate video thumbnail in node.js?

I am building an app with node.js, I successfully uploaded the video, but I need to generate a video thumbnail for it. Currently I use node exec to execute a system command of ffmpeg to make the thumbnail.
exec("C:/ffmpeg/bin/ffmpeg -i Video/" + Name + " -ss 00:01:00.00 -r 1 -an -vframes 1 -f mjpeg Video/" + Name + ".jpg")
This code is coming from a tutorial from http://net.tutsplus.com/tutorials/javascript-ajax/how-to-create-a-resumable-video-uploade-in-node-js/
the code above did generate a jpg file but it's not a thumbnail but a video screen shot, I wonder is there any other method to generate video thumbnail, or how to exec the ffmpeg command to make a real thumbnail (resized), and I prefer png file.
Reference to GitHub fluent-ffmpeg project.
Repeating example from original StackOverflow answer:
var proc = new ffmpeg('/path/to/your_movie.avi')
.takeScreenshots({
count: 1,
timemarks: [ '600' ] // number of seconds
}, '/path/to/thumbnail/folder', function(err) {
console.log('screenshots were saved')
});
Resize by adding a -s widthxheight option to your command.
There is a node module for this:
video-thumb
It basically just wraps a call to exec ffmpeg
I recommend using https://www.npmjs.com/package/fluent-ffmpeg to call ffmpeg from Node.js
Using media-thumbnail, you can easily generate thumbnails from your videos. The module basically wraps the ffmpeg thumbnail functionality.
const mt = require('media-thumbnail')
mt.forVideo(
'./path/to/video.mp4',
'./path/to/thumbnail.png', {
width: 200
})
.then(() => console.log('Success'), err => console.error(err))
You can also create thumbnails from your images using this package.
Instead I would recommend using thumbsupply. In addition to provide you with thumbnails, it caches them to improve performance significantly.
npm install --save thumbsupply
After installing the module, you can use it in a following way.
const thumbsupply = require('thumbsupply')("com.example.application");
thumbsupply.generateThumbnail('some-video.mp4')
.then(thumb => {
// serve thumbnail
})
app.post('/convert', upload.any(), (req, res) => {
console.log("calling", req.files)
let thumbNailName = req.files[0].filename.split('.')
var gm = require('gm');
gm('./src/Upload/'+req.files[0].filename)// get pdf file from storage folder
.thumb(
50, // Width
50, // Height
'./src/thumbnail/'+thumbNailName[0]+'.png', // Output file name
80, // Quality from 0 to 100
function (error, stdout, stderr, command) {
if (!error) {
console.log("processing");
} else {
console.log("error")
}
}
);
})

Resources