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

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

Related

Using NodeJS to combine a png and mp3 to make a mp4

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?

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.

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?

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