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.
Related
I am using Amazon polly for text to speech.
Here is the code
static async _ttsUsingPolly(text, gender, destPath, speed) {
let params = {
'Text': 'Hi, my name is #anaptfox.',
'OutputFormat': 'pcm',
'VoiceId': 'Kimberly',
SampleRate: "8000"
}
const data = await this.Polly.synthesizeSpeech(params).promise();
if (data.AudioStream instanceof Buffer) {
console.log("buffer", data);
// Initiate the source
const bufferStream = new Stream.PassThrough();
// convert AudioStream into a readable stream
bufferStream.end(data.AudioStream);
// Pipe into Player
bufferStream.pipe(fs.createWriteStream(destPath));
}
}
this saves the file to .wav format. destPath is public\audio\abc\1212_1660649369899.wav.
But when i play this file it says
This file isn’t playable. That might be because the file type is unsupported, the file extension is incorrect, or the file is corrupt.
0xc00d36c4
what is the issue (if someone can explain)? and how can i fix this?
Update1
actually this generates the pcm format file, so i tried wav converter
var pcmData = fs.readFileSync(path.join(__dirname, './audios/audio_wav', fileName))
var wavData = wavConverter.encodeWav(pcmData, {
numChannels: 1,
sampleRate: 8000,
byteRate: 16
})
fs.writeFileSync(path.resolve(__dirname, './audios/audio_wav', './16k.wav'), wavData)
pcm generated file is of almost 67KB but converted wav file is of 1KB.
if i change pcm to mp3 in polly params it works.
Any help?
I directly passed the stream to wav-converter
._convertPcmToWav(data.AudioStream, fileName);
and
static _convertPcmToWav(stream, fileName) {
const wavData = wavConverter.encodeWav(stream, {
numChannels: 1,
sampleRate: 8000,
byteRate: 2
});
const wavFileName = path.parse(fileName).name;
fs.writeFileSync(path.resolve(__dirname, './audios/audio_wav', `./${wavFileName}.wav`), wavData)
}
now the file is generated correctly and playable.
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
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?
I want to be able to extract jpegs from a Uint8 array containing the data for a mpeg or avi video.
The module ffmpeg has the function fnExtractFrameToJPG but it only accepts a filename pointing to the video file. I want to be able to extract the frames from the UInt8Array.
One way to do it is to write the UInt8Array to a tmp file and then use the tmp file with ffmpeg to extract the frames:
const tmp = require("tmp");
const ffmpeg_ = require("ffmpeg");
function convert_images(video_bytes_array){
var tmpobj = tmp.fileSync({ postfix: '.avi' })
fs.writeFileSync(tmpobj.name, video_bytes_array);
try {
var process = new ffmpeg(tmpobj.name);
console.log(tmpobj.name)
process.then(function (video) {
// Callback mode
video.fnExtractFrameToJPG('./', { // make sure you defined the directory where you want to save the images
frame_rate : 1,
number : 10,
file_name : 'my_frame_%t_%s'
}, function (error, files) {
if (!error)
tmpobj.removeCallback();
});
});
} catch (e) {
console.log(e.code);
console.log(e.msg);
}
}
Another possibitlity is to use opencv after you save the UInt8Array to a tmp file. Another solution is to use stream and ffmpeg-fluent which would not require using tmp files.
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.