REST API with node-rtsp-stream NPM - node.js

I am trying to stream a RTSP in HTML5 pages using node-rtsp-stream NPM. Here I can see the live stream in HTML page. But the thing is when I try to do REST API with this it throws TypeError: stream is not a constructor. when I call my post method first time its working properly. when I try to do the same again it throws error.
here is my API:
RTSPRouter.post('/getPreview', (req, res) => {
// stream.mpeg1Muxer.kill();
stream = new stream({
name: 'name',
streamUrl: req.body.RTSPURL,
wsPort: 9999,
ffmpegOptions: {
'-r': 30
}
})
res.send(stream)
})
API for Kill :
RTSPRouter.get('/killPreview', (req, res) => {
process.kill(req.body.pid1)
stream.prototype.stop()// this method also not working
})
Even I killed the stream alone using the PID it's throwing the same error.
Kindly help me to fix this problem, thanks in advance!

you're getting a typeError because you haven't imported Stream.
Your code should look like this:
Stream = require("node-rtsp-stream");
stream = new Stream({
name: "name",
streamUrl: "rtsp://184.72.239.149/vod/mp4:BigBuckBunny_115k.mov",
wsPort: 9999,
ffmpegOptions: {
// options ffmpeg flags
"-stats": "", // an option with no neccessary value uses a blank string
"-r": 30, // options with required values specify the value after the key
},
});
res.send(stream);
Also don't forget to run npm install node-rtsp-stream.

After a few days I found the answer for this question.
You should not create stream like this:
var stream = require('node-rtsp-stream')
stream = new stream({
name: 'name',
streamUrl: req.body.RTSPURL,
wsPort: 9999,
ffmpegOptions: {
'-r': 30
}
})
Instead of this, try the below code:
var stream = require('node-rtsp-stream')
var streamObj;
streamObj = new stream({
name: 'name',
streamUrl: req.body.RTSP,
wsPort: 9999,
ffmpegOptions: { // options ffmpeg flags
'-stats': '', // an option with no neccessary value uses a blank string
'-r': 30 // options with required values specify the value after the key
}
})
The actual error is that I had imported a stream with the name stream, and tried to initiate the stream with same variable name stream. You have to use a different variable name to initialize the stream. In my case I used streamobj.

Related

ssh2-sftp-client get() request giving 'denied permission - error'

I am using this code in my electron app to connect to an sftp server where I need to collect some data. I have no problem listing the files in the /out folder, but it fails to get the sftp file with 'deined permission' error. Ideally I would like to be able get() file and access the text data within directly in the function without storing to a file.
let Client = require('ssh2-sftp-client');
let sftp = new Client();
var root = '/out';
var today = new Date();
var mon = ((today.getMonth()+1) < 10)? "0" + (today.getMonth()+1) : (today.getMonth()+1);
var date = (today.getDate() < 10)? "0" + today.getDate() : today.getDate();
var fileDate = mon + date;
sftp.connect({
host: '<server-address>',
port: 2222,
username: 'XXXXXXXX',
password: 'xxxxxxxx',
privateKey: fs.readFileSync(path.join(__dirname, '../rsa/<file-name-here>.pem'))
})
.then(() => {
return sftp.list(root, 'SN5M' + fileDate);
})
.then((fileInfo) => {
if (fileInfo) {
var filePath = root + '/' + fileInfo[fileInfo.length - 1].name;
return sftp.get(filePath).then((file) => {
console.log(file);
event.returnValue = file;
sftp.end();
})
.catch((err) => {
console.log('File get error', err);
event.returnValue = err;
sftp.end();
});
}
})
.catch((err) => {
console.log('File info error', err);
event.returnValue = err;
sftp.end();
});
Try this and see if it works or not
'get' returns (String|Stream|Buffer).
let dst = fs.createWriteStream('/local/file/path/data.txt');
sftp.get(filePath,dst)
Refer https://www.npmjs.com/package/ssh2-sftp-client#orga0dfcd5
Looking at your code, you have two problems.
If you call get() with only 1 argument, it returns a buffer, not a file. To get the file, just do
client.get(sourceFilePath, localFilePath)
and the file will be saved locally as localFilePath. Both arguments are strings and need to be full paths i.e. include the filename, not just the directory. The filename for the second argument can be different from the first. However, if all you want is to retrieve the file, you are better off using fastGet() rather than get(). The get() method is good for when you want to do something in the code with the data e.g. a buffer or write stream piping/processing. The fastGet() method is faster than get() as it does the transfer using concurrent processes, but does not permit use of buffers or streams for further processing.
The error message you are seeing is either due to the way you are calling get() or it is an indication you don't have permission to read the file your trying to access (as the user your connected with). Easiest way to check this is to use the openSSH sftp program (available on Linux, mac and windows) and the key your using (use the -i switch) to try and download the file. If it fails with a permission error, then you know it is a permission error and not a problem with your code or ssh2-sftp-client module.
EDIT: I just noticed you are also using both a password and a key file. You don't need both - either one will work, but you don't need to use both. I tend to use a keyfile when possible as it avoids having to have a password stored somewhere. Make sure not to add a passphrase to your key. Alternatively, you can use something like the dotenv module and store your credentials and other config in a .env file which you do not check into version control.

Speech to Text: Piping microphone stream to Watson STT with NodeJS

I am currently trying to send a microphone stream to Watson STT service but for some reason, the Watson service is not receiving the stream (I'm guessing) so I get the error "Error: No speech detected for 30s".
Note that I have streamed a .wav file to Watson and I have also tested piping micInputStream to my local files so I know both are at least set up correctly. I am fairly new to NodeJS / javascript so I'm hoping the error might be obvious.
const fs = require('fs');
const mic = require('mic');
var SpeechToTextV1 = require('watson-developer-cloud/speech-to-text/v1');
var speechToText = new SpeechToTextV1({
iam_apikey: '{key_here}',
url: 'https://stream.watsonplatform.net/speech-to-text/api'
});
var params = {
content_type: 'audio/l16; rate=44100; channels=2',
interim_results: true
};
const micParams = {
rate: 44100,
channels: 2,
debug: false,
exitOnSilence: 6
}
const micInstance = mic(micParams);
const micInputStream = micInstance.getAudioStream();
micInstance.start();
console.log('Watson is listening, you may speak now.');
// Create the stream.
var recognizeStream = speechToText.recognizeUsingWebSocket(params);
// Pipe in the audio.
var textStream = micInputStream.pipe(recognizeStream).setEncoding('utf8');
textStream.on('data', user_speech_text => console.log('Watson hears:', user_speech_text));
textStream.on('error', e => console.log(`error: ${e}`));
textStream.on('close', e => console.log(`close: ${e}`));
Conclusion: In the end, I am not entirely sure what was wrong with the code. I'm guessing it had something to do with the mic package. I ended up scrapping the package and using "Node-audiorecorder" instead for my audio stream https://www.npmjs.com/package/node-audiorecorder
Note: This module requires you to install SoX and it must be available in your $PATH. http://sox.sourceforge.net/
Updated Code: For anyone wondering what my final code looks like here you go. Also a big shoutout to NikolayShmyrev for trying to help me with my code!
Sorry for the heavy comments but for new projects I like to make sure I know what every line is doing.
// Import module.
var AudioRecorder = require('node-audiorecorder');
var fs = require('fs');
var SpeechToTextV1 = require('watson-developer-cloud/speech-to-text/v1');
/******************************************************************************
* Configuring STT
*******************************************************************************/
var speechToText = new SpeechToTextV1({
iam_apikey: '{your watson key here}',
url: 'https://stream.watsonplatform.net/speech-to-text/api'
});
var recognizeStream = speechToText.recognizeUsingWebSocket({
content_type: 'audio/wav',
interim_results: true
});
/******************************************************************************
* Configuring the Recording
*******************************************************************************/
// Options is an optional parameter for the constructor call.
// If an option is not given the default value, as seen below, will be used.
const options = {
program: 'rec', // Which program to use, either `arecord`, `rec`, or `sox`.
device: null, // Recording device to use.
bits: 16, // Sample size. (only for `rec` and `sox`)
channels: 2, // Channel count.
encoding: 'signed-integer', // Encoding type. (only for `rec` and `sox`)
rate: 48000, // Sample rate.
type: 'wav', // Format type.
// Following options only available when using `rec` or `sox`.
silence: 6, // Duration of silence in seconds before it stops recording.
keepSilence: true // Keep the silence in the recording.
};
const logger = console;
/******************************************************************************
* Create Streams
*******************************************************************************/
// Create an instance.
let audioRecorder = new AudioRecorder(options, logger);
//create timeout (so after 10 seconds it stops feel free to remove this)
setTimeout(function() {
audioRecorder.stop();
}, 10000);
// This line is for saving the file locally as well (Strongly encouraged for testing)
const fileStream = fs.createWriteStream("test.wav", { encoding: 'binary' });
// Start stream to Watson STT Remove .pipe(process.stdout) if you dont want translation printed to console
audioRecorder.start().stream().pipe(recognizeStream).pipe(process.stdout);
//Create another stream to save locally
audioRecorder.stream().pipe(fileStream);
//Finally pipe translation to transcription file
recognizeStream.pipe(fs.createWriteStream('./transcription.txt'));

change author of mp3 file

I'd like to set the author of a mp3 file based on the data sent by the user.
So far, I managed to get the data sent by the user (hardly an exploit anyway), but I can't manage to change the author of the file. I've tried using both node-id3 package and ffmetadata package, as suggested by this answer, but none of this worked.
The node-id3 approach
Here is a part of code that I wrote for the node-id3 approach, and whille the tags shown in readTags are indeed the ones that I added in the update method, it doesn't change the author of the file when I read it on my computer (with itunes) or on my android phone (with samsung music), which means this approach doesn't work.
const NodeID3 = require('node-id3')
//getting the filename and fileAuthor, as well as creating the file on the server
let tags = {
title: filename,
composer: fileAuthor,
artist: fileAuthor,
remixArtist: fileAuthor,
conductor: fileAuthor,
originalArtist: fileAuthor,
}
let success = NodeID3.update(tags, toBeDownloadedFilePath)
console.log(success)
let readTags = NodeID3.read(toBeDownloadedFilePath)
console.log(readTags)
the ffmetadata approach
Here is the same part written with the ffmetadata approach :
const ffmetadata = require("ffmetadata");
//getting the filename and fileAuthor, as well as creating the file on the server
let tags = {
artist: fileAuthor,
}
ffmetadata.write(toBeDownloadedFilePath, tags, function(err) {
if (err) console.error("Error writing metadata", err);
else console.log("Data written");
});
and with this approach, I'm getting the error :
[mp3 # 0x7f90f8000000] Format mp3 detected only with low score of 1, misdetection possible!
[mp3 # 0x7f90f8000000] Failed to read frame size: Could not seek to 1026.
music1.mp3: Invalid argument
(music1.mp3 being my filename), and my mp3 file is perfectly recognised by all audio reader with which I tested it.
Thank you very much for your help.
So I finally found where was the problem (at least with the node-id3 approach) :
to better understand it, I'll add some details to the creating the file on server step.
Here was my unfunctional code :
const NodeID3 = require('node-id3')
const fs = require('fs-extra'); // file system
fs.ensureFileSync(toBeDownloadedFilePath); //because I need to create the file if it doesn't exist
const toBeDownloadedFile = fs.createWriteStream(toBeDownloadedFilePath);
//the way the audio stream is created isn't relevant, but if you're interested, it's a youtube stream, as per https://www.npmjs.com/package/youtube-audio-stream
let fileWriteStream = audioStream.pipe(toBeDownloadedFile)
let tags = {
title: filename,
composer: fileAuthor,
artist: fileAuthor,
remixArtist: fileAuthor,
conductor: fileAuthor,
originalArtist: fileAuthor,
}
let success = NodeID3.update(tags, toBeDownloadedFilePath)
console.log(success)
let readTags = NodeID3.read(toBeDownloadedFilePath)
console.log(readTags)
And the problem was that my tags were written but immediately deleted by the audiostream.pipe
the solution was therefore quite simple, and I ended up with this code :
const NodeID3 = require('node-id3')
const fs = require('fs-extra'); // file system
fs.ensureFileSync(toBeDownloadedFilePath); //because I need to create the file if it doesn't exist
const toBeDownloadedFile = fs.createWriteStream(toBeDownloadedFilePath);
let fileWriteStream = audiSstream.pipe(toBeDownloadedFile)
fileWriteStream.on('finish', () => {
let tags = {
title: filename,
artist: fileAuthor,
}
NodeID3.update(tags, toBeDownloadedFilePath)
//any additional action, in my case, send the file for a download
})
Hope this helps people with similar problem.

Gulp streams not supported Error using gulp-istanbul

I'm getting an error with streams.
I'm working on adding istanbul to my existing mocha task. When I run this task I get the error below.
I'm using gulp-istanbul
(note: the config.test.src.bdd.features is set to the value 'test/bdd/features/**/*-spec.js')
var stream = gulp.src([config.test.src.bdd.features], { read: false });
gulp.task('mocha-bdd-features', function(cb) {
process.env.PORT = 8001;
return stream
.pipe(istanbul())
.pipe(istanbul.hookRequire())
.pipe(mocha({
compilers: {
js: babel
},
reporter: config.test.mocha.reporter,
ui: 'bdd'
}))
.on('finish', function () {
stream.pipe(istanbul.writeReports())
stream.pipe(istanbul.enforceThresholds({thresholds: {global: 90}}))
stream.on('end', cb);
});
});
the error I get is:
events.js:85
throw er; // Unhandled 'error' event
^
Error: streams not supported
and who knows I may not be setting up this task right when trying to incorporate gulp-istanbul but trying to at least get past this error first.
I was facing the exact same issue.
I believe the problem is in line:
var stream = gulp.src([config.test.src.bdd.features], { read: false });
Setting the read option to false causes the file.contents to be null and therefore istanbul is not able to cover the files. (check here)
so try the same thing but without the read option.
var stream = gulp.src([config.test.src.bdd.features]);
Hope this helps.

node.js retrieve http csv file and load into mongoose

I'm very new to coding in general, so I apologize ahead of time if this question should be rather obvious. Here's what I'm looking to do, and following that I'll post the code I've used so far.
I'm trying to get gzip'd csv rank data from a website and store it into a database, for a clan website that I'm working on developing. Once I get this figured out, I'll need to grab the data once every 5 minutes. The grabbing the csv data I've been able to accomplish, although it stores it into a text file and I need to store it into mongodb.
Here's my code:
var DB = require('../modules/db-settings.js');
var http = require('http');
var zlib = require('zlib');
var fs = require('fs');
var mongoose = require('mongoose');
var db = mongoose.createConnection(DB.host, DB.database, DB.port, {user: DB.user, pass: DB.password});
var request = http.get({ host: 'www.earthempires.com',
path: '/ranks_feed?apicode=myapicode',
port: 80,
headers: { 'accept-encoding': 'gzip' } });
request.on('response', function(response) {
var output = fs.createWriteStream('./output');
switch (response.headers['content-encoding']) {
// or, just use zlib.createUnzip() to handle both cases
case 'gzip':
response.pipe(zlib.createGunzip()).pipe(output);
break;
default:
response.pipe(output);
break;
}
});
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function callback () {
var rankSchema = new mongoose.Schema({
serverid: Number,
resetid: Number,
rank: Number,
countryNumber: Number,
name: String,
land: Number,
networth: Number,
tag: String,
gov: String,
gdi: Boolean,
protection: Boolean,
vacation: Boolean,
alive: Boolean,
deleted: Boolean
})
});
Here's an example of what the csv will look like(first 5 lines of file):
9,386,1,451,Super Kancheong Style,22586,318793803,LaF,D,1,0,0,1,0
9,386,2,119,Storm of Swords,25365,293053897,LaF,D,1,0,0,1,0
9,386,3,33,eug gave it to mak gangnam style,43501,212637806,LaF,H,1,0,0,1,0
9,386,4,128,Justpickupgirlsdotcom,22628,201606479,LaF,H,1,0,0,1,0
9,386,5,300,One and Done,22100,196130870,LaF,H,1,0,0,1,0
Hope it's not too late to help, but here's what I'd do:
Request the CSV formatted data and store it in memory or a file.
Parse the CSV data to convert each row into an object.
For each object, use Model.create() to create your new entry.
First, you need to create a model from your Schema:
var Rank = db.model('Rank', rankSchema);
Then you can parse your block of CSV text (whether you read it from a file or do it directly after your request is up to you.) I created my own bogus data variable since I don't have access to the api, but as long as your data is a newline delimited block of CSV text this should work:
/* Data is just a block of CSV formatted text. This can be read from a file
or retrieved right in the response. */
var data = '' +
'9,386,1,451,Super Kancheong Style,22586,318793803,LaF,D,1,0,0,1,0\n' +
'9,386,2,119,Storm of Swords,25365,293053897,LaF,D,1,0,0,1,0\n' +
'9,386,3,33,eug gave it to mak gangnam style,43501,212637806,LaF,H,1,0,0,1,0\n' +
'9,386,4,128,Justpickupgirlsdotcom,22628,201606479,LaF,H,1,0,0,1,0\n' +
'9,386,5,300,One and Done,22100,196130870,LaF,H,1,0,0,1,0\n';
data = data.split('\n');
data.forEach(function(line) {
line = line.split(',');
if (line.length != 14)
return;
/* Create an object representation of our CSV data. */
var new_rank = {
serverid: line[0],
resetid: line[1],
rank: line[2],
countryNumber: line[3],
name: line[4],
land: line[5],
networth: line[6],
tag: line[7],
gov: line[8],
gdi: line[9],
protection: line[10],
vacation: line[11],
alive: line[12],
deleted: line[13]
};
/* Store the new entry in MongoDB. */
Rank.create(new_rank, function(err, rank) {
console.log('Created new rank!', rank);
});
});
You could put this in a script and run it every 5-minutes using a cron job. On my Mac, I'd edit my cron file with crontab -e, and I'd setup a job with a line like this:
*/5 * * * * /path/to/node /path/to/script.js > /dev/null

Resources