Play audio with Node.JS - node.js

I'm currently using child_process and command-line mplayer to play audio on the local machine, with my Node.JS application. This works, but it's not really an excellent solution. My biggest issue is that it takes 500ms from mplayer is started to audio starts playing.
Are there better ways to play audio? Preferably compressed audio, but I'll take what I can get.

I would suggest using node-speaker, which outputs raw PCM data to your speakers (so basically, it plays audio).
If you're playing something like mp3 files you might need to decode it first to PCM data, which is exactly what node-lame does.
Hope that helps.

Simplest I've found (on Mac OS) is to use
exec('afplay whatever.mp3', audioEndCallback)

Introducing, audic. It doesn't use any native dependencies so it can't break like in the answers higher up.
Observe:
import Audic from 'audic';
const audic = new Audic('audio.mp3');
await audic.play();
audic.addEventListener('ended', () => {
audic.destroy();
});
or more simply:
import {playAudioFile} from 'audic';
await playAudioFile('audio.mp3');

I think what you asking is there any good modules that work with audio in the nodejs ecosystem?
Whenever you have this type of question you should first go the npmjs and just type a appropiate keyword.
Here is list of modules that related to audio I found on the npmjs site.
substacks's baudio looks good to me.

You can use play-sound module also:
Install using npm, Run command:
npm install play-sound --save
Now use in your code:
var player = require('play-sound')(opts = {})
player.play('./music/somebody20.flac', function (err) {
if (err) throw err;
console.log("Audio finished");
});

Check out sound-play, it's a simple solution that works on Windows and MacOS without using external players:
const sound = require('sound-play')
sound.play('music.mp3')
Disclaimer: I'm the author of this package.

Check out node-groove - Node.js binding to libgroove:
This library provides decoding and encoding of audio on a playlist. It is intended to be used as a backend for music player applications, however it is generic enough to be used as a backend for any audio processing utility.
Disclaimer: I wrote the library, which is free, open source, and not affiliated with any product, service, or company.

You can use the play sound module and path to achieve this.
npm install play-sound
import path from 'path';
const __dirname = path.resolve();
import sound from 'sound-play';
const filePath = path.join(__dirname, "file.mp3");
sound.play(filePath);

Related

Record audio on frontend send to backend for Google Speech API call

I am trying to build what I thought was simple functionality into a website that I am building with ReactJS and Express for backend. But it's turning out to be much more difficult than I thought at first.
Essentially what I want is to have a button on the frontend that begins and ends a recording of the user's voice. Then I'd like to take that audio and send it to the server from which I make an API call to Google's Speech2Text API to get the text. My problem is two-fold, first of all which library do you recommend in order to do the recording? I used RecorderJS at first but after following the steps and converting the data into what I thought was the right format (16-signed bit linear PCM) when I send it and save it I get garbage and not what I recorded. Now I am trying to use the node-recorder-lpcm16 library which records with precisely the encoding that I need, however I am not sure if I am running it correctly since in the docs they write them for node such as
recorder = require('node-recorder-lpcm16');
recorder.record();
But what I do in my React code is:
import recorder from 'node-record-lpcm16';
...
onButtonPress() {
recorder.record();
And I am not getting an error on the import statement, but I am getting an error on the record() call. The error that I am getting is Uncaught Error: No such recorder found: sox, but in my config I am not passing sox as the recordProgram but 'rec', not to mention I have sox installed both with brew install sox and with npm install sox in the frontend directory.
Secondly, I am not 100% the best way to send the audio to the server. Right now I am taking my buffer, sending it as a comma-separated string using a POST request; and on the server side splitting the string by commas and casting it as the correct array. However this isn't viable for longer recordings and I am wandering if there is a way I can stream it somehow, and what libs or tools I should use for this. For example in the google speech docs they have an example using the node-lpcm library that goes like this:
const recorder = require('node-record-lpcm16');
const speech = require('#google-cloud/speech');
const client = new speech.SpeechClient();
const recognizeStream = client
.streamingRecognize(request)
.on('error', console.error)
.on('data', data => {whatever});
recorder
.record({
sampleRateHertz: sampleRateHertz,
threshold: 0,
recordProgram: 'rec'
})
.stream()
.on('error', console.error)
.pipe(recognizeStream);
And I am wondering how I set up this type of piping from client to server? Do I have to send a POST request each time on('data') or is there a smarter way of doing this?
Sorry for the length and thanks for any help.

ionic 2 how to play sound effects

I'm actually developping an application with Ionic 2 / angular2.
It's an app to learn english tenses that runs with a SQLite database.
I would like to add a background sound that plays in loop all the time.
The users can exercice themselves with a quizz. I would like to play sound effects when the user submit his answer.
Two different sounds : one for good and one for bad answers.
I've already tried with Nativeaudio, angular-audio and Ionic audio modules but each times the documentation is based on javascript and not typescript, or it is not helpfull.
With native audio, I've succeed once playing the background sound but after it didn't work at all and came up with an error : EXCEPTION: Uncaught (in promise): A reference does not exist for the specified audio id.
For the other solutions (angular-audio and ionic-audio) either i didn't get how to install it either, once installed, I had nothing : no sound and no error.
Thank you very much for your help.
Install:
$ ionic plugin add --save cordova-plugin-nativeaudio
$ npm install --save #ionic-native/native-audio
Usage:
import { NativeAudio } from '#ionic-native/native-audio';
constructor(private nativeAudio: NativeAudio) { }
...
this.nativeAudio.preloadSimple('uniqueId1', 'path/to/file.mp3').then(onSuccess, onError);
this.nativeAudio.preloadComplex('uniqueId2', 'path/to/file2.mp3', 1, 1, 0).then(onSuccess, onError);
this.nativeAudio.play('uniqueId1').then(onSuccess, onError);
// can optionally pass a callback to be called when the file is done playing
this.nativeAudio.play('uniqueId1', () => console.log('uniqueId1 is done playing'));
Reference:
https://ionicframework.com/docs/native/native-audio/

Get video resolution in nodejs

I have been trying to get an answer to this without really finding any. Excuse me if this sounds stupid or obvious.
I have a nodejs application and basically I would like to simply get the resolution of a video. Imagine I have film stored on disk and I would like to be able to know if it is in 720p or 1080p or anything else.
I understood that I might need to use ffmpeg to do so, but then I also understood that ffmpeg was mostly used to "record, convert and stream audio and video files".
That does not mean retrieve video resolution.
Thank you for your help
Edit 1:
The node.js app is a desktop app and needs to be portable to Linux, windows and OS X. If possible a portable answer would be more appreciated but of course any answer is welcome.
To be honest I think the best method I found was to use fluent-ffmpeg with ffprobe as you are able to set the the path to the executable. The only problem is that ffmpeg has to be shipped with the app. So different executables have to be shipped, one for each distribution/os/derivation. If anyone has anything better I am open to answers.
Getting the width, height and aspect ratio using fluent-ffmpeg is done like so:
var ffmpeg = require('fluent-ffmpeg');
ffmpeg.setFfprobePath(pathToFfprobeExecutable);
ffmpeg.ffprobe(pathToYourVideo, function(err, metadata) {
if (err) {
console.error(err);
} elseĀ {
// metadata should contain 'width', 'height' and 'display_aspect_ratio'
console.log(metadata);
}
});
There's a npm package called get-video-dimensions that also use ffprobe and it's much easier to use. It also support promises and async/await.
import getDimensions from 'get-video-dimensions';
Using promise:
getDimensions('video.mp4').then(dimensions => {
console.log(dimensions.width);
console.log(dimensions.height);
})
or async/await:
const dimensions = await getDimensions('video.mp4');
console.log(dimensions.width);
console.log(dimensions.height);
I use node-ffprobe to accomplish this for images:
var probe = require('/usr/lib/node_modules/node-ffprobe');
probe(filePath, function (err, data) {
//the 'data' variable contains the information about the media file
});
fileMetaData will have width, height, codec info, aspect ratio etc ...
const ffprobe = require('ffprobe')
const ffprobeStatic = require('ffprobe-static')
const fileMetaData = await ffprobe(fileName, { path: ffprobeStatic.path })
fileName could be video('webm', 'mov', 'wmv', 'mpg', 'mpeg', 'mp4','flv' etc..) or image(jpg, gif, png etc..) path.
fileName example: /path/to/video.mp4 or http://example.com/video.mp4
One way to do this would be to to run another application as a child process, and get the resolution from std out. I'm not aware of any pure node.js solution for this.
See child_process.exec https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback
and ffprobe
How can I get the resolution (width and height) for a video file from a linux command line?

is it possible to read /proc/{pid}/stat then transfer to client real time?

suppose i want to monitor mysql, as far as i know, all mysql runtime info is stored in /proc/{mysql_pid}/stat. so is it possible to read and parse mysql stat info via node.js and client display the chart real time ?
nagios and alternative is so heavy, and sometimes i just want to monitor some progress info. so i want a lightweight solution.
I tried using Node Inotify, which is an excellent library. Yet, it seems like the proc filesystem doesn't event to inotify when the stat files are changed. If you're watching a file on a normal filesystem, though, this is how you can do it using that library:
sys = require('sys');
fs = require('fs');
Inotify = require('inotify').Inotify;
var inotify = new Inotify();
function callback(ev) {
console.log(sys.inspect(ev));
}
var home_dir = {
path: '/proc/5499/stat'
, watch_for: Inotify.IN_ALL_EVENTS
, callback: callback
};
var home_watch_descriptor = inotify.addWatch(home_dir);
Just change Inotify.IN_ALL_EVENTS to whatever action you want to watch for, which is documented on the github page I linked.
Sorry this doesn't solve your particular problem, but I thought I'd post it informationally.
I'm assuming you haven't tried implementing a solution to your problem. What exactly do you mean by "real time"? What sort of client are you talking about?
If you're talking about a web browser client, there's no reason you couldn't update some sort of display every half-second with loads of clients (or much faster, if the charts aren't too intricate).
You should be more specific if you want a more specific answer than that.

Playing a sound in a Firefox add-on

I would like to create a simple add-on that would play a different MP3 recording every time the user double clicks a word in a webpage he is visiting and selects a special option from the context menu.
The MP3 files are located on a remote server. Normally I would use JavaScript+Flash to play the MP3 file. In a Firefox add-on, however, I'm unable to load external scripts for some reason (playing the sound works fine if it's the webpage itself that loads the scripts, but of course I need it to work with every website and not just the ones that include the script).
So what's the easiest way to play a remote MP3 file in a Firefox add-on using JavaScript?
This may not entirely solve your question, as I don't BELIEVE it plays MP3s, but I'm not certain.
Firefox has nsISound, which I KNOW can play remote WAV files, as I've tested and proved it.
You may want to test it for yourself and see if it leads you a little closer!
var ios = Components.classes['#mozilla.org/network/io-service;1'].getService(Components.interfaces.nsIIOService);
var sound = ios.newURI("http://www.yoursite.com/snds/haha.wav", null, null);
var player = Components.classes["#mozilla.org/sound;1"].createInstance(Components.interfaces.nsISound);
player.play(sound);
Good luck, I hope this at least gets you close!
I know this is an old question, but if someone needs a way to do it:
let player = document.createElement("audio");
player.src = browser.runtime.getURL(SOUND_URL);
player.play();
There is one caveat: the user must have allowed autoplay on the website.
Here is a working code....
var sound = Components.classes["#mozilla.org/sound;1"].createInstance(Components.interfaces.nsISound);
var soundUri = Components.classes['#mozilla.org/network/standard-url;1'].createInstance(Components.interfaces.nsIURI);
soundUri.spec = "chrome://secchat/content/RING.WAV";
sound.play(soundUri);
var window = require('sdk/window/utils').getMostRecentBrowserWindow();
var audio = ('http://example.com/audio.mp3');
audio.play();

Resources