Generate ffmpeg thumbnail from stream in Node.js - node.js

Im using node.js together with ffmpeg to receive an rtmp-stream and output this into m3u8-format.
[ '-y',
'-fflags',
'nobuffer',
'-analyzeduration',
'1000000',
'-i',
'rtmp://localhost:1935/live/ANMZJ2ZRUiMhKaAoygRXwAfHe',
'-c:v',
'copy',
'-c:a',
'aac',
'-f',
'tee',
'-map',
'0:a?',
'-map',
'0:v?',
'-y',
'-an',
'[hls_time=10:hls_list_size=0]./media/live/ANMZJ2ZRUiMhKaAoygRXwAfHe/SX3otgDdf6/index.m3u8|' ]
Together with this functionality I would also like to output a thumbnail. I tried to do this using the following format but without success.
[ '-y',
'-fflags',
'nobuffer',
'-analyzeduration',
'1000000',
'-i',
'rtmp://localhost:1935/live/ANMZJ2ZRUiMhKaAoygRXwAfHe',
'-c:v',
'copy',
'-c:a',
'aac',
'-f',
'tee',
'-map',
'0:a?',
'-map','0:v?',
'-y',
'-an',
'-vf' ,
'fps=1',
'C:/Users/media/out.png'
'[hls_time=10:hls_list_size=0]./media/live/ANMZJ2ZRUiMhKaAoygRXwAfHe/SX3otgDdf6/index.m3u8|' ]
The way I send this information to ffmpeg is by
this.ffmpeg_exec = spawn(ffmpeg_path, args);
Im unable to create a thumbnail using this approach. Does anyone know the problem/solution?

You have a log of extra arguments in the second command! You really only need the input, number of frames, and output.
[ '-i',
'rtmp://localhost:1935/live/ANMZJ2ZRUiMhKaAoygRXwAfHe',
'-frames:v',
'1',
'C:/Users/media/out.png'
]
Docs for -frames:v
https://ffmpeg.org/ffmpeg.html#Video-Options

fluent-ffmpeg support stream input and output :
var FfmpegCommand = require('fluent-ffmpeg');
var ffmpeg = FfmpegCommand();
ffmpeg.input(stream)
.seekInput("00:00:01.000")
.outputFormat("image2")
.pipe(res,{end:true});

Related

How do I add cross-fade when concatenating video with intermediate files using FFmpeg

I am working on concatenating each video with FFmpeg intermediate files, and want to add cross-fade when merging each of the videos.
const ffmpegArgs = [
"-y",
"-f",
"mpegts",
"-i",
`concat:${intermediateFiles.join("|")}`,
"-c",
"copy",
"-bsf:a",
"aac_adtstoasc",
resultPath,
];
Here is the function to take intermediate files for each video:
const ffmpegArgs = [
"-y",
"-i",
file,
"-c",
"copy",
"-bsf:v",
"h264_mp4toannexb",
"-shortest",
"-avoid_negative_ts",
"make_zero",
"-fflags",
"+genpts",
"-f",
"mpegts",
intermediateFilePath,
];

Can't play m3u8 file using react-hls-player npm package

I create a m3u8 file using ffmpeg, I need to play that file, for that i used a npm package called react-hls-player but it is not playing, what the mistake i make, below is my code
I used below code to create a m3u8 file using ffmpeg in nodejs
const ffmpeg = require('fluent-ffmpeg')
const ffmpegInstaller = require('#ffmpeg-installer/ffmpeg')
ffmpeg.setFfmpegPath(ffmpegInstaller.path)
ffmpeg('uploads/malayalam.mp4').addOptions([
'-c:a',
'aac',
'-ar',
'48000',
'-b:a',
'128k',
'-c:v',
'h264',
'-profile:v',
'main',
'-crf',
'20',
'-g',
'48',
'-keyint_min',
'48',
'-sc_threshold',
'0',
'-b:v',
'2500k',
'-maxrate',
'2675k',
'-bufsize',
'3750k',
'-hls_time',
'4',
'-hls_playlist_type',
'vod',
'-hls_segment_filename',
'uploads/video/720p_%03d.ts'
]).output('uploads/video/output.m3u8').on('end',(err,data)=>{
console.log(data)
console.log('end')
}).run()
below is the screenshot of my m3u8 file directory
I used react-hls-player to play the m3u8 file my nodejs server running on port:5000
below is the reactjs code
import React from 'react'
import ReactHlsPlayer from 'react-hls-player';
function M3u8_player() {
return (
<div className="userlist">
<ReactHlsPlayer
src="http://localhost:5000/uploads/video/output.m3u8"
autoPlay={false}
controls={true}
width="100%"
height="auto"
/>
</div>
)
}
export default M3u8_player
Here i cant play the m3u8 file someone please help me , is there any mistake i made creating m3u8 file
I think the problem that you need to pass an Authentication header within the hls player

How to execute locally installed Node.js application by child_process.spawn()?

I want to execute the Electron application by child_process.spawn:
import ChildProcess, {ChildProcess as ChildProcess__type} from 'child_process';
const childProcess: ChildProcess__type = ChildProcess.spawn(
'electron',
['ProjectInitializer__ElectronMain.js'],
{ cwd: __dirname } // current project root
);
I got Error: spawn electron ENOENT error. Electron has been installed locally, AFAIK is the good practice. Also, electron ProjectInitializer__ElectronMain.js works, it to execute this console command from my project directory.
Following frequently up-voted ENOENT error debugging guidance, I got the cause: there is no directory among process.env.PATH, which includes electron.
I know about PATH variable not much, so I can not answer what must be in this variable and what is not. But what I want to ask is: how to execute locally installed (in node_modules) Node.js applications (like electron)?
By the way, execa which is known as improved child_process runs electron without errors (update: version 2.x.x already do not runs):
import executeExternalCommand, { ExecaReturnValue } from 'execa';
try {
await executeExternalCommand(
'electron',
['ProjectInitializer__ElectronMain.js'],
{ cwd: __dirname }
);
} catch (error) {
console.error(error);
}
Somehow, thanks to { cwd: __dirname }, the execa v 1.x.x knows, where should to find the electron. Unfortunately, execa has too small community and small documentations, so stopped to use it.
Additional information
How I run this Node.js script which has the spawn parameter
By command my-library init which I created.
In package.json:
"bin": {
"my-library": "bin/my-library"
}
In bin/my-library (no filename extension):
#!/usr/bin/env node
require('../CLI').interpretConsoleCommandAndExecute(process.argv);
In CLI.js I parse the console command, and if it is the my-library init, I'll try to execute
const childProcess: ChildProcess__type = ChildProcess.spawn(
'electron',
[ 'ProjectInitializer__ElectronMain.js' ],
{ cwd: __dirname }
);
console.log(process.env) output
Below output is for PhpStorm build-in console, however in other consoles, e. g. in cmder, output is different.
{ FPS_BROWSER_APP_PROFILE_STRING: 'Internet Explorer',
CommonProgramFiles: 'C:\\Program Files\\Common Files',
PROMPT: '$P$G',
SESSIONNAME: 'Console',
COMPUTERNAME: 'MSI',
OneDriveConsumer: 'D:\\OneDrive',
__INTELLIJ_COMMAND_HISTFILE__:
'C:\\Users\\i\\.PhpStorm2019.1\\config\\terminal\\history\\history-34',
SystemDrive: 'C:',
NUMBER_OF_PROCESSORS: '12',
LOGONSERVER: '\\\\MSI',
TEMP: 'C:\\Users\\i\\AppData\\Local\\Temp',
TMP: 'C:\\Users\\i\\AppData\\Local\\Temp',
HOMEPATH: '\\Users\\i',
PATHEXT: '.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JSE;.WSF;.WSH;.MSC',
USERNAME: 'i',
ProgramFiles: 'C:\\Program Files',
USERDOMAIN_ROAMINGPROFILE: 'MSI',
LOCALAPPDATA: 'C:\\Users\\i\\AppData\\Local',
TERMINAL_EMULATOR: 'JetBrains-JediTerm',
PROCESSOR_IDENTIFIER: 'Intel64 Family 6 Model 158 Stepping 10, GenuineIntel',
DriverData: 'C:\\Windows\\System32\\Drivers\\DriverData',
APPDATA: 'C:\\Users\\i\\AppData\\Roaming',
ALLUSERSPROFILE: 'C:\\ProgramData',
USERDOMAIN: 'MSI',
OS: 'Windows_NT',
PROCESSOR_LEVEL: '6',
ProgramData: 'C:\\ProgramData',
ComSpec: 'C:\\Windows\\system32\\cmd.exe',
PROCESSOR_ARCHITECTURE: 'AMD64',
FPS_BROWSER_USER_PROFILE_STRING: 'Default',
SystemRoot: 'C:\\Windows',
PROCESSOR_REVISION: '9e0a',
OneDrive: 'D:\\OneDrive',
PSModulePath:
'C:\\Program Files\\WindowsPowerShell\\Modules;C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\Modules',
PATH:
'D:\\PhpStorm\\InHouseDevelopment\\my-library\\node_modules\\.bin;C:\\ProgramData\\DockerDesktop\\version-bin;C:\\Program Files\\Docker\\Docker\\Resources\\bin;C:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\iCLS\\;C:\\Program Files
\\Intel\\Intel(R) Management Engine Components\\iCLS\\;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Windows\\System32\\OpenSSH\\;C:\\Program Files (x86)\\NVIDIA Corporation\\PhysX\\Common;C:\\Pro
gram Files\\Intel\\WiFi\\bin\\;C:\\Program Files\\Common Files\\Intel\\WirelessCommon\\;C:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\DAL;C:\\Program Files\\Intel\\Intel(R) Management Engine Components\\DAL;C:\\Program Files (x86)\\Intel\\I
ntel(R) Management Engine Components\\IPT;C:\\Program Files\\Intel\\Intel(R) Management Engine Components\\IPT;C:\\Program Files (x86)\\Common Files\\Acronis\\VirtualFile\\;C:\\Program Files (x86)\\Common Files\\Acronis\\VirtualFile64\\;C:\\Program Files (x86)\\Com
mon Files\\Acronis\\FileProtector\\;C:\\Program Files (x86)\\Common Files\\Acronis\\FileProtector64\\;C:\\Program Files (x86)\\Common Files\\Acronis\\SnapAPI\\;C:\\Program Files\\nodejs\\;C:\\Program Files\\Git\\cmd;C:\\Program Files (x86)\\Yarn\\bin\\;C:\\Users\\t
okug\\AppData\\Local\\Microsoft\\WindowsApps;C:\\Users\\i\\AppData\\Roaming\\npm;C:\\Users\\i\\AppData\\Local\\Yarn\\bin;C:\\texlive\\2019\\bin\\win32',
'ProgramFiles(x86)': 'C:\\Program Files (x86)',
USERPROFILE: 'C:\\Users\\i',
windir: 'C:\\Windows',
ProgramW6432: 'C:\\Program Files',
configsetroot: 'C:\\Windows\\ConfigSetRoot',
'CommonProgramFiles(x86)': 'C:\\Program Files (x86)\\Common Files',
PUBLIC: 'C:\\Users\\Public',
HOMEDRIVE: 'C:',
CommonProgramW6432: 'C:\\Program Files\\Common Files' }
Trying to execute ChildProcess.spawn('env')
In Php Strorm console, it causes familiar Error: spawn env ENOENT.
As discussed in the chat, the error you are getting is usually caused by the fact that the executable you are trying to run is not available
Now there are multiple reasons the executable may not be available
The executable is not there at all anywhere on the system
The executable is there but not in the folders defined by system's PATH variable
The executable is there in the current directory but the directory context in which the process is being run is different
To fix #1 and #2 you just install the executable globally in system PATH
For fixing #3 you can do two things. Add the path for the current directory ({ cwd: __dirname}) and also a relative path to executable
const childProcess: ChildProcess__type = ChildProcess.spawn(
Path.resolve(__dirname, 'node_modules/.bin/electron'),
[ Path.resolve(__dirname, 'ProjectInitializer__ElectronMain.js') ],
{ cwd: __dirname}
);
or
const childProcess: ChildProcess__type = ChildProcess.spawn(
'./node_modules/.bin/electron'),
[ Path.resolve(__dirname, 'ProjectInitializer__ElectronMain.js') ],
{ cwd: __dirname}
);
or
const childProcess: ChildProcess__type = ChildProcess.spawn(
'node_modules/.bin/electron',
[ './ProjectInitializer__ElectronMain.js' ],
{ cwd: __dirname}
);
In case you decide to override the PATH environment variable you can do it passing the env parameters with more values
const childProcess: ChildProcess__type = ChildProcess.spawn(
'node_modules/.bin/electron',
[ './ProjectInitializer__ElectronMain.js' ],
{ cwd: __dirname, env: {....}}
);
You can use the existing environment variables from process.env and then update the same, and pass it to env parameter
it’s likely that you need to specify the full path to the electron command, since it isn’t on your path.
If you are running your script from your project root, electron is probably at in ./node_modules/.bin/electron, if they packaged up the app to be run that way.
I would guess that your alternative library checks node_modules by default.
The alternative would be to ensure electron is in your path, but that requires updating your system configuration, which it would be weird for a library to do.
Edit: example of call with path:
const childProcess: ChildProcess__type = ChildProcess.spawn(
'node_modules/.bin/electron',
[ 'ProjectInitializer__ElectronMain.js' ],
{ cwd: __dirname }
);
I'd also add some dumb logging on the process, so you know why the process failed:
function log(data) {
console.log("" + data)
}
child_process.stdout.on('data', log)
child_process.stderr.on('data', log)
child_process.on('close', log)

spawn ffmpeg process fails with permission denied

I'm trying to spawn a ffmpeg process to encode some audio files to hls compatible mpegts files. I need to feed the data via pipe in order to handle the live stream part. I'm using the code below to spawn my process:
var file = fs.createReadStream('./audio.mp3');
var child = spawn('ffmpeg',
['-y', '-i', 'pipe:', '-c', 'aac', '-b:a', '32k', '-hls_segment_type', 'mpegts', '-hls_time', 1, '-hls_list_size', 0, './' + req.body.uri + '_32k.m3u8'], {
env: process.env,
stdio: ['pipe', 1, 2]
}
);
file.pipe(child.stdin);
strangely I get pipe:: Permission denied from stderr of ffmpeg.

Node.js spawn not working with quotes inside argument

I'm trying to run this command with spawn
var args = ['-ss','00:00:15','-i',storage_path + doc.file_name,'-vframes','1','-vf','"scale='+size*2+':ih*'+size*2+'/iw,crop='+size+':'+size+'"','-f','image2','-q:v','5',storage_path + output_name];
var command = spawn('ffmpeg', args);
The issue seems to be with this part here: '"scale='+size*2+':ih*'+size*2+'/iw,crop='+size+':'+size+'"'
When I log the args, this is what I get:
[ '-ss',
'00:00:15',
'-i',
'/a/video.mp4',
'-vframes',
'1',
'-vf',
'"scale=150:ih*150/iw, crop=75:75"',
'-f',
'image2',
'-q:v',
'5',
'/a/75.jpg' ]
If I take that, and do .join(' '), I get the command:
-ss 00:00:15 -i /a/video.mp4 -vframes 1 -vf "scale=150:ih*150/iw, crop=75:75" -f image2 -q:v 5 /a/75.jpg
When I run ffmpeg with this, all is good.
Any ideas how to format this for spawn arguments?
Thank you!
Don't use quotes for vf:
'scale='+size*2+':ih*'+size*2+'/iw,crop='+size+':'+size

Resources