Extract Frames From a Video? - node.js

I want to extract frames from a Video and save the frames
var express = require("express"),
var video = "./s/video.mp4";
var storeOutput = "./store"
function getVideoFrames(){
// get frames
}

Generally, when it comes to work with video, ffmpeg is a great tool to use.
There is a ffmpeg-extract-frames package on the npm repository, based on fluent-ffmpeg, that perform exactly that.
const extractFrames = require('ffmpeg-extract-frames')
extractFrames({
input: 's/video.mp4',
output: './store/frame-%d.jpg'
})
If you need, you can pass an array of time, in milliseconds, to the offsets option to extract only specific frames.
extractFrames({
input: 's/video.mp4',
output: './store/screenshot-%i.jpg',
offsets: [
1000,
2000,
3000
]
})

Related

first m3u8 ts segment not working after mp4 to m3u8 conversion by node js

index.js
const ffmpegPath = require('#ffmpeg-installer/ffmpeg').path;
const ffmpeg = require('fluent-ffmpeg');
const process = require('process');
const args = process.argv.slice(2);
if (args.length !== 4) {
console.error('Incorrect number of arguments');
process.exit(1);
}
const startTime = args[0];
const timeDuration = args[1];
const inputFile = args[2];
const outputFile=args[3];
ffmpeg.setFfmpegPath(ffmpegPath);
ffmpeg(inputFile)
.setStartTime(startTime)
.setDuration(timeDuration)
.output(outputFile)
.outputOptions('-hls_list_size 0')
.on('end', function(err) {
if(!err) { console.log('conversion Done') }
})
.on('error', function(err){
console.log('error: ', err)
}).run();
Here is the index.js and I'm running it by hitting the command on the terminal
node index.js 5 40 ./input.mp4 ./output.m3u8
Here 5 is for starting time and 40 is the time duration in seconds. The process creates m3u8 with ts files but the first ts file isn't getting created properly. It's been created in kb format while all the other files in mb format.
the output_test0 isn't getting generated properly and so that's why while playing the m3u8 file, the first few seconds is just static picture. This issue has been happening with the first ts output only. Any trick on how to fix it?
Following your comment about how it seems to be caused by the use of input seeking instead of output seeking:
Use seek() or seekOutput() instead of setStartTime(). The documentation describes the difference:
seek(time): seek output
Aliases: seekOutput().
Seeks streams before encoding them into the output. This is different from calling seekInput() in that the offset will only apply to one output. This is also slower, as skipped frames will still be decoded (but dropped).
The time argument may be a number (in seconds) or a timestamp string (with format [[hh:]mm:]ss[.xxx]).
ffmpeg('/path/to/file.avi')
.seekInput('1:00')
.output('from-1m30s.avi')
.seek(30)
.output('from-1m40s.avi')
.seek('0:40');
setStartTime() is an alias for seekInput(). From the same documentation:
seekInput(time): set input start time
Alias: setStartTime().
Seeks an input and only start decoding at given time offset.
Note that seek() or seekOutput() should be applied to the output and not on the input as seekInput(), i.e. after output().

Problem with using naudiodon / portaudio?

When I try the "playing audio streaming audio data" from the naudiodon library I only get noise on the speaker. I'm interested in how to get real sound from an app (for example when playing music from youtube). I wonder if the sound is then saved in my case in stream4800.wav?
I wonder what all the dependency I need for the project?
When I just record over a microphone with inOptions: {} I get a successfully saved stream (sound). But when I want to get the sound out of the speakers outOptions: {} then the story becomes unclear to me.
Here is an example of my code:
const portAudio = require('naudiodon');
const wav = require("wav");
const ao = new portAudio.AudioIO({
outOptions: {
channelCount: 2,
sampleFormat: portAudio.SampleFormat64Bit,
sampleRate: 44100,
}
});
const name = "stream4800.wav";
const file = fs.createReadStream(`./${name}`);
const reader = new wav.Reader();
ao.start();
reader.on("data",chunk=>ao.write(chunk));
file.pipe(reader);
Thanks for any help
Hi please check the audio file [stream4800.wav] is Mono or Sterio. I would recommend you to use sterio file with applicable sampleRate will help you out.

How to convert wav file into 8000hz using Nodejs

I have tried to convert speech wav file to text using nodejs but it displays error like this:
Error:
data: '{\n "error": "This 8000hz audio input requires a narrow band
model."\n}',
Code :
let directory = `File Directory`;
let dirbuf = Buffer.from(directory);
let files = fs.readdirSync(directory);
// Create the stream.
// Pipe in the audio.
files.forEach(wav_files => {
//how can i convert that wav file into 8000hz and use that same wav file for speech to text convert
fs.createReadStream(wav_files).pipe(recognizeStream);
recognizeStream.on('data', function(event) { onEvent('Data:',event,wav_files); });
}
I am not sure whether you've already explored wav package or not. But I created a cheat like this:
const fs = require('fs');
const WaveFile = require('wavefile').WaveFile;
let wav = new WaveFile(fs.readFileSync("source.wav"));
// do it like this
wav.toSampleRate(8000);
// or like following way with your choice method
// wav.toSampleRate(44100, {method: "cubic"});
// write new file
fs.writeFileSync("target-file.wav", wav.toBuffer());
For complete running example clone node-cheat wav-8000hz and run node wav.js followed by npm i wavefile.

How to solve output underflow error using naudiodon / portaudio?

I am writing a small node.js program that will be able to play wav sound files on a chosen audio device.
The sound starts well but it is stoped before the end of the file.
Here is my code :
const fs = require("fs");
const wav = require("wav");
const portAudio = require("naudiodon");
const ao = new portAudio.AudioIO({
outOptions: {
channelCount: 2,
sampleFormat: portAudio.SampleFormat24Bit,
sampleRate: 44100,
}
});
const name = "myfile.wav";
const file = fs.createReadStream(`./sounds/${name}`);
const reader = new wav.Reader();
reader.on("format", () => {
reader.pipe(ao);
ao.start();
});
file.pipe(reader);
process.on("SIGINT", ao.quit);
When I modify the highWaterMark option of fs.createReadStream, it slightly change the cut position in the sound but it never goes until the end of it.
I always get a portAudio status - output underflow log error.
Thanks for any help !
I have been experiencing a similar error, and my solution was to manually write to the AudioIO stream instead of using the pipe commands.
So instead of
reader.on("format", () => {
reader.pipe(ao);
ao.start();
});
You would use
ao.start();
reader.on("data",chunk=>ao.write(chunk));
Output underflow is generally not an issue, but to avoid it I initialised a new instance of PortAudio before playing every file, however that is only applicable if you don't care about slight latency.

Creating A MP4 clip with Node js

Can I create video clips from an mp4 video with node js streams? I am sure there are npms for this task, but is this something that can be done with just streams?
When I create a server, I can pipe a brief clip from the beginning of a video to an HttpResponse stream and pipe it to a file Stream with the following code: (It works!)
const fs = require('fs');
const http= require('http');
http.createServer(async (req, res) => {
// Creating clip from the beginning to 5% of the video
var { size } = fs.statSync('./Fun.mp4');
var start = 0
var end = .05*size;
var videoClip = fs.createReadStream('./Fun.mp4', { start, end })
var fileCopy = fs.createWriteStream('./Fun-Copy.mp4')
res.writeHead(200, {'Content-Type': 'video/mp4'})
videoClip.pipe(res)
videoClip.pipe(fileCopy)
}).listen(3000);
However, if I change the start position to the middle of the video, it doesn't work. I don't see the clip in the web browser, and Qucktime cannot play the copy that was produced.
// Attempting to create a clip from 50% to 60% of the video
var { size } = fs.statSync('./Fun.mp4');
var start = 0.5*size;
var end = 0.6*size;
It seems like mp4 is incomplete without the beginning. Is there a way that I can create clips from a larger video file with streams. Is there some meta elements or something, or a specific number of bytes that need to be copied from the beginning of an mp4 file?
Does node js handle audio the same way? Can I build audio clips from a larger file with node js streams?
There is not a specific number of bytes needed. MP4 uses an index like structure to organize the files. If you modify the file at all, the index (called the moov box) needs to be rewritten in its entirety.

Resources