How I can merge two audio files - JavaScript? - javascript

I have two audio files from RecordRTC both local & remote streams. Now I want to merge the two files into one file and upload it to the server via AJAX.
e.g. (audio1.webm) and (audio2.webm).
mediaRecorder.stopRecording(function() {
var blob = mediaRecorder.getBlob();
var fileName = getFileName('webm');
var fileObject = new File([blob], fileName, {
type: 'audio/webm'
});
var formData = new FormData();
formData.append('blob', fileObject);
formData.append('filename', fileObject.name);
$.ajax({
url: '{{ url('/') }}/save-audio',
data: formData,
cache: false,
contentType: false,
processData: false,
type: 'POST',
success: function(response) {
console.log(response);
}
});
});
Thank you in advance.
UPDATE:
I made it this way instead of recorder.addStreams, and still I can get the recorded.
var remoteVideos = $('#remoteVideos video');
var el = [];
$.each($('#remoteVideos video'), function(index, val) {
el[index] = val.srcObject;
});
el.push(stream);
multiMediaRecorder = new MultiStreamRecorder(el);

You can use a similar library: MediaStreamRecorder. Then use MultiStreamRecorder and pass two streams as below,
recorder = new MultiStreamRecorder([localStream, remoteStream]);
You will get localStream from getUserMedia and remoteStream from onaddstream event listener.
You may want to just pass the audio tracks in the array. The rest of the things as it is. FFmpeg and file merging is not necessary.

I got it now by doing this, as below;
function onMediaSuccess(localStream) {
var remoteVideos = $('#remoteVideos video')[0];
multiMediaRecorder = new MultiStreamRecorder([localStream, remoteVideos.srcObject]);
multiMediaRecorder.ondataavailable = function (blob) {
// POST/PUT "Blob" using FormData/XHR2
var blobURL = URL.createObjectURL(blob);
console.log(blobURL);
};
multiMediaRecorder.start();
}
But now there's another problem, ondataavailable is called twice but the first video is playable and working properly, while the second video is playable but (less than one second) I think it might be corrupted.
Cheers!

Related

How to convert node.js array-buffer to javascript array buffer

I send audio to client using node.js :
res.send(audio); / audio it is the buffer array
And I get object 'arrayBuffer' in data.
And I conver it to Blob and after to file (I want to get dataURL to show it in player)
.then(
(result) => {
result.arrayBuffer().then(function (data) {
const blob = new Blob([data], { type: 'audio/wav' });
var fileReader = new FileReader();
fileReader.readAsDataURL(blob);
fileReader.onload = function (evt) {
// Read out file contents as a Data URL
var url = evt.target.result;
res({blob, url})
};
})
}
)
And it works good. I use this url it as src of my <audio> attribute and it works.
But now I want to send this file from server as a part of json. Now I get audioBuffer from the serve in "audio" property. I chage arrayBuffer method to json in fetch:
result.json().then(function (data) {
const blob = new Blob([data.audio], { type: 'audio/wav' });
...
But now it doesn't work. I tried to use module www.npmjs.com/package/to-array-buffer to convert data.audio to js-arrayBuffer, but it doesn't help.
Maybe you know what's problem here?
Ok, I solved problem. I use module about whick I wrote to-array-buffer, but I use not toArrayBuffer(data.audio) but toArrayBuffer(data.audio.data)

turning canvas.toDataURL DOMString url into a blob,

i am using cropperjs to crop images
Using the method getCroppedCanvas to get reference to the cropped canvas image
Using the canvas method canvas.toDataURL to compress the images into a jpeg files.
I don't use canvas.toBlob as its browser support is not clear.
My question is how can i turn the string i get from canvas.toDataURL into a blob so i can later use it in formData.
Update
server expect form data - multi-part
One method that I used while working on some tool is to convert the dataURL to Blob using this function:
function dataURLtoBlob(dataurl) {
var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {type:mime});
}
And then you can send the Blob to the server using native xhr like this:
var blob = dataURLtoBlob(dataURI);
var fd = new FormData();
var xhr = new XMLHttpRequest ();
fd.append ('file', blob);
xhr.open('POST', '/endpoint', true);
xhr.onerror = function () {
console.log('error');
}
xhr.onload = function () {
console.log('success')
}
xhr.send (fd);
The blob builder code is taken from here: https://stackoverflow.com/a/30407840/2386736
use canvas.toDataURL to generate an JPEG image:
var JPEG_QUALITY=0.5;
var dataUrl = canvas.toDataURL('image/jpeg', JPEG_QUALITY).replace('data:image/jpeg;base64,', '');
And then send it to AJAX as data-multi-part:
jQuery.ajax({
url: 'php/upload.php',
data: dataUrl,
cache: false,
contentType: false,
processData: false,
type: 'POST',
success: function(data){
}
});
Depending on what your server side expects to receive.
By the way: You wrote "I don't use canvas.toBlob as its browser support is not clear" - You can see the browser support here:

Send image data to an API nodejs

I am attempting to send image data to a server API, though, the documentation included with the API only contains an example for JQuery, which I don't want to use with my nodejs project. Also, the JQuery example contains things that don't exist in Node, such as Blobs.
The example provided by the API is:
var sourceImage = new Image();
sourceImage.src = image; // add image data to object
sourceImage.onload = function() {
// Create a canvas with the desired dimensions
var canvas = document.createElement("canvas");
var dim = 256; // the image size
canvas.width = dim;
canvas.height = dim;
// Scale and draw the source image to the canvas
canvas.getContext("2d").drawImage(sourceImage, 0, 0, dim, dim);
var formDataWithCanvasImage = createFormData(canvas);
// Make ajax call here
}
function createFormData(canvas) {
var b64Img = canvas.toDataURL();
var binImg = dataURItoBlob(b64Img);
var fileName = new Date().getTime();// Name the file with the current timestamp and no extension
var fd = new FormData();
fd.append("imageClass", "preview");
fd.append("X-Requested-With", "Iframe");
fd.append("X-HTTP-Accept", "application/json, text/javascript, */*; q=0.01");
fd.append("file", binImg,fileName);
return fd;
}
$.ajax({
url: imageURL,
data: formDataWithCanvasImage,
processData: false,
contentType: false,
type: 'POST',
error: function() {alert("error uploading image");},
success: function(data){
console.log(data);
}
});
However, this wouldn't work with nodejs, because there is no canvas in nodejs, and no such thing as a blob. So, what I've done is read an image from the local disc and convert that buffer into an ArrayBuffer then encode it in analog-nico's request-promise like so:
let opts = {
uri: 'https://*****.com/api/images',
contentType: false,
processData: false,
type: 'POST',
formData: {
"imageClass": "application",
"X-Requested-With": "Iframe",
"X-HTTP-Accept": "application/json, text/javascript, */*; q=0.01"
"file": arraybuffer
},
}
request.post(opts).then(data => {....});
but the code throws TypeError: source.on is not a function. Has anyone encountered this problem before? How did you resolve it?
You could try loading the image from disk as a ReadStream and piping that using the request module to the API.
Rough Example:
fs.createReadStream(filename).pipe(request.put('http://example.com/api/images'))
The module is available via npm install request.

Windows store apps JS : uploading a video file with WinJS.xhr

I've some trouble into uploading a video to a form.
In my case, I need to upload some data with my video, so I left BackgroundUploader to use WinJS.xhr. But I can't figure it out how to convert my video file into something readable for my php.
My code:
var clickPicker = function () {
openPicker = Windows.Storage.Pickers.FileOpenPicker();
// We set the default location to the video library
openPicker.suggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.videosLibrary;
// Set de view to thumbnail
openPicker.viewMode = Windows.Storage.Pickers.PickerViewMode.thumbnail;
// Extension allowed to be taken
openPicker.fileTypeFilter.replaceAll([".mp4", ".avi"]);
openPicker.pickSingleFileAsync().done(function (file) {
uploadInit(file);
}, function (err) {
// MISTAAAAAAAAAAAAAAAAKEEEEEEEEE
console.log(err.message);
});
};
var uploadInit = function (file) {
// Creating the blob
var objectURL = window.URL.createObjectURL(file);
var url = "http://localhost/vdm_bo/videos/uploader";
var d = new Date();
var data = new FormData();
data.append("data[Video][pseudo]", 'H4mm3R');
data.append('data[Video][postal_code]', '67340');
// Converting date to a datetile mysql
data.append('data[Video][date]', ISODateString(d));
data.append('data[Video][age]', '24');
data.append("data[Video][email]", 'bliblu#hotmail.fr');
data.append("data[Video][question_selected]", 'qA');
data.append("data[Video][video_file]", file, file.name);
WinJS.xhr({
type: "POST",
url: url,
data: data
}).done(function (res) {
console.log('succes');
}, function (err) {
console.log(err.message);
}, function (res) {
});
};
So, to debug this I serialize the answer, and here is what I get :
When uploading with the file (without blob) :
s:36:"[object Windows.Storage.StorageFile]";
When uploading with blob (window.URL.createObjectURL(file))
s:41:"blob:9A06AB11-8609-42DC-B0A9-7FB416E70A9D";
And when I'm uploading the video just with my html form
a:5:{s:4:"name";s:36:"9147cb17e216d5182908ad370ff16914.mp4";s:4:"type";s:9:"video/mp4";s:8:"tmp_name";s:23:"C:\wamp\tmp\php13C8.tmp";s:5:"error";i:0;s:4:"size";i:26454182;}
Does anyone have a clue how to make it work ? Or maybe I do it all wrong and it's not the way I'm suppose to convert my file (It's the way to do for images, maybe not for video)
Okay, I found a way to do that. First ou need to get the file with getFileAsync() and not the Picker. Then you can create a blob with the stream of your file and add this blob to your form.
Here my code
var videosLibrary = Windows.Storage.KnownFolders.videosLibrary;
videosLibrary.getFileAsync(file.name).then(
function completeFile(file) {
return file.openAsync(Windows.Storage.FileAccessMode.readWrite);
}).then(
function completeStream(stream) {
var d = new Date();
// Do processing.
var blob = MSApp.createBlobFromRandomAccessStream("video/mp4", stream);
var data = new FormData();
data.append("data[Video][pseudo]", 'H4mm3R');
data.append('data[Video][postal_code]', '67340');
// Converting date to a datetile mysql
data.append('data[Video][date]', ISODateString(d));
data.append('data[Video][age]', '24');
data.append("data[Video][email]", 'bliblu#hotmail.fr');
data.append("data[Video][question_selected]", 'qA');
data.append("data[Video][video_file]", blob, file.name);
return WinJS.xhr({ type: "POST", url: "http://localhost/vdm_bo/videos/uploader", data: data });
}).then(
function (request) {
console.log("uploaded file");
},
function (error) {
console.log("error uploading file");
});

Save phonegap captured images to parse

I'm trying to save the photo captured using Phonegap's camera API. The function returns the file uri. When I save this, it directly saves the string uri and not the file.
I even tried specifying the content type as image in ajax header file. Gives me a broken link.
function capturePhoto(){
//alert(address);
navigator.camera.getPicture(uploadPhoto,onFail,{sourceType:1,quality:60,destinationType: Camera.DestinationType.FILE_URI});
}
function uploadPhoto(data){
var serverUrl = 'https://api.parse.com/1/files/myphoto.jpg';
$.ajax({
type: "POST",
headers: {'X-Parse-Application-Id': PARSE_APP,
'X-Parse-REST-API-Key':PARSE_REST
// "Content-Type": "image/png"
},
url: serverUrl,
data: data,
processData: false,
contentType: false,
success:function(e){
console.log(e.url);
},
error:function(){
console.loh("ERROR");
}
});
}
You will want to use destinationType: Camera.DestinationType.Native_URI. This will return the image's actual location on the device, typically something like file://storage/0/sdcard/.... You can then use this location to load/send/manipulate the image.
You need the FileTransfer API to get the contents of the file. In your uploadPhoto callback insert the following:
function uploadPhoto(data){
var ft = new FileTransfer();
var options = new FileUploadOptions();
options.mimeType = "image/jpeg";
options.chunkedMode = false;
options.params = { // Any params you need...
};
ft.upload(data, 'https://api.parse.com/1/files/myphoto.jpg',
function (e) {
console.log('Success');
},
function (e) {
alert("Upload failed");
}, options);
}
You might need to change some of the options and parameters depending on your backend (which you have not specified). Christopher Coenraets has a good video tutorial with code on how to do this. The other solution is base64 the result, in this you set the src of a image that you create to be the fileUri and then draw the image onto a canvas and get the dataUrl of the canvas. This method works with older versions of PhoneGap but is considerably slower than directly uploading using FileTransfer API.

Categories