I'm using Recorderjs lib to record audio from browser, so, I have the wav blob on some variable.
To upload to the server, i'm using FormData converting blob to base64 string:
var reader = new FileReader();
reader.onload = function (event) {
toUpload.append("audio", event.target.result);
$.ajax(ajaxConfig); // my ajax call
}
reader.readAsDataURL(myBlob);
When the file reaches to the server, i'm using NAudio.Lame to compress to mp3 format (recordjsmp3 is very slow, want to do it on server-side):
using (var ms = new MemoryStream(myFile))
using (var wav = new WaveFileReader(ms))
.net throws the exception:
FormatException: Not a WAVE file - no RIFF header
Ok, let's try to save the file on disk to play on Windows Media Player:
File.WriteAllBytes("c:\\test.wav", myFile);
When I try to play the file saved on disk, media player says that file is corrupted.
My endpoint is Asp.Net web api, and i'm doing this to take the byte array:
var multipart = await Request.Content.ReadAsMultipartAsync();
multipart.Contents.SingleOrDefault(f => f.Headers.ContentDisposition.Name.ToLower().Contains("audio")).ReadAsByteArrayAsync();
What am I missing?
Related
I have a very simple application I am making that needs to load 30 second m4a files from a couch server. I am able to receive the files but can not get them to load in a player. The files are uploaded through Fauxton and have been deleted and reuploaded to be sure the issue was not in the upload.
I have also loaded the object url into a link and tried to download the file which can not be played.
I have tried both using the source directly in the audio tag as well as adding the source tag.
I have tested the files in the audio player and they work fine locally.
I think I there is something wrong with the way I am creating the blob or url.
<audio controls id="mediaPlayer"></audio>
var db = new PouchDB('http://user:password#localhost:5984/music');
db.get('9d3f17d01be8283c461eaa01940329b4', { attachments:true } ).then(function (doc){
// Load first file
var media = Object.values(doc._attachments)[0];
// Get Player
var player = document.getElementById('mediaPlayer');
// Create blob from data - media content type is
var blob = new Blob([ media.data ], { type: media.content_type });
// Create url from blob
var afile = URL.createObjectURL(blob);
// Set source and load
player.src = afile;
player.load();
});
I solved my own issue. This was a complete oversight on my end. Fauxton uploads all attachments as Base64 not blobs. I had to simply decode the data before converting it to a blob. I am using node so I used buffer to decode the string before creating the blob.
If you are using raw vanilla js you should be able to use atob(media.data) in place of the buffer, but I did not test it.
import { Buffer } from 'buffer';
var db = new PouchDB('http://user:password#localhost:5984/music');
db.get('9d3f17d01be8283c461eaa01940329b4', { attachments:true } ).then(function (doc){
// Load first file
var media = Object.values(doc._attachments)[0];
// Get Player
var player = document.getElementById('mediaPlayer');
// Remove Encoding
var raw = Buffer.from(media.data, 'base64');
// Create blob from data
var blob = new Blob([ raw ], { type: media.content_type });
// Create url from blob
var afile = URL.createObjectURL(blob);
// Set source and load
player.src = afile;
player.load();
});
I want the user of my website to be able to upload a potentially large video file to it using HTML‘s file input. The video should than be processed and played locally in the user‘s browser.
let fileInput = document.createElement("INPUT");
fileInput.setAttribute("type", "file");
fileInput.onChange = onFileSelected;
To read the video file uploaded by the user, I wanted to use a File Reader like this:
function onFileSelected(e) {
// The file uploaded by the user:
let file = e.target.files[0];
// Create a file reader:
let reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function(e) {
video.src = e.target.result;
}
}
However, when I uploaded really large video files (≈300 MB), e.target.result was not a URI to the video file, like I expected, but an empty string.
How can I read very large video files using File Reader in JavaScript?
The FileReader class in JavaScript contains multiple methods to read files:
readAsText(): This reads a file and returns its content as text. Suitable for small text files.
readAsBinaryString(): This reads a file and returns its content as a binary string. Suitable for small files of any type.
readAsDataURL(): This reads a file and returns a Data URL referencing it. This is inefficient for large files as the file is loaded into memory as a whole before being processed.
readAsArrayBuffer(): This reads a file and returns an ArrayBuffer containing the input file 'chopped up in smaller pieces'. This works for very large files, too.
In the question, the readAsDataURL() method is used as it is usually most convenient. However, for very large video files (and very large files in general) it does not work for the reason described above leading to an empty result. Instead, you should use readAsArrayBuffer():
let reader = new FileReader();
reader.readAsArrayBuffer(file);
Now, the file reader returns an ArrayBuffer after loading the file. In order to be able to show the video in HTML, we have to convert this buffer to a blob, that can then give us a URL to the video file:
reader.onload = function(e) {
// The file reader gives us an ArrayBuffer:
let buffer = e.target.result;
// We have to convert the buffer to a blob:
let videoBlob = new Blob([new Uint8Array(buffer)], { type: 'video/mp4' });
// The blob gives us a URL to the video file:
let url = window.URL.createObjectURL(videoBlob);
video.src = url;
}
I am trying to work with the Google Cloud Speech API to transcribe the audio to text. I have a working prototype where I have a mp3/wav (prerecorded) file that is correct and accepted by the API to do the request when it is sent as base64 format. However the problem I am having now is, that in an other prototype where I capture the sound from the user (client-side) and save it as mp3/wav, the base64 doesn't correspond with the file-type (it sees it as video/webm instead of audio/mp3 / audio/x-wav).
Sidenote: The audio recordings are fine and playable.
Tried saving the blob file as mp3
Tried recorder.js
const mime = ['audio/wav', 'audio/mpeg', 'audio/webm', 'audio/ogg']
.filter(MediaRecorder.isTypeSupported)[0];
const mediaRecorder = new MediaRecorder(mediaStreamObj, {
mimeType: mime
});
//the stop event
mediaRecorder.onstop = (ev)=>{
let blob = new Blob(chunks, { type : 'audio/mp3;' });
chunks = [];
let audioURL = window.URL.createObjectURL(blob);
audioSave.src = audioURL;
}
I expect to have a file with the filetype/mimetype audio/mp3 and not video/webm
I'm using the getUserMedia API to allow a user to record a short Audio clip on the client. After finishing the recording, I initialize a FileReader, create a Blob from all the Audio chunks, and read the reader of the blob as a DataURL. That gets appended as Text to a webform that's then sent to a Rails5 API, where I'm having a very difficult time converting the Binary Audio into a working .mp3 file.
Here is what the code looks like:
When the recorder goes inactive, the chunks are collected and used to instantiate a new Blob with the type 'audio/mpeg'.
var chunks = [];
if (recorder.state == 'inactive') {
var blob = new Blob(chunks, { type: 'audio/mpeg' });
App.mediaStream.encodeBase64(blob);
}
The Blob is then passed to a function that creates a base64 encoded DataURL.
encodeBase64: function(blob) {
var reader = new FileReader();
reader.onloadend = function() {
App.mediaStream.appendToForm(reader.result);
};
reader.readAsDataURL(blob);
},
The result from the reader is a dataURL that follows this pattern, data:[type];base64,[data] - so it's a String that looks like:
"data:audio/mpeg;base64,GkXfo59ChoEBQveBAULygQRC84EIQoKEd2VibUKHgQRChYECGFOAZwH/////////FUmpZpkq17GDD0JATYCGQ2hyb21lV0GGQ2hyb21lFlSua7uuudeBAXPFh+bmBbc......."
I'm appending this DataURL to a form, that sends it to my Rails 5 API along with some other data. Here is where I'm running into trouble. On the server side, I have a ruby method that parses the dataURL, and writes it to a file as so:
def binary_to_audio_file(dataURL)
data = dataURL.split(',').last
filename = SecureRandom.hex
File.open("public/#{filename}.mp3", 'wb') do |f|
f.write Base64.decode64(data)
end
end
This is successfully creating a new file in the specified directory that has the decoded audio binary written to the file. That file can be opened by QuickTime, Itunes, or any other media play. It even plays for the same duration that the recording lasted. HOWEVER, there is NO sound.
I promise my speakers are not turned off... any hints?
I am developing an application using phone gap. I capture image/audio/video and store its path in local storage. I need to fetch base64 of captured file and store it in the database and then sync it with server. Is that possible using javascript ?
I tried using FileReader API that phone gap provides but the function reader.onloadend() does not get executed.
Could manage to get base64 of image using a canvas but is it possible to get base64 for audio and video using canvas?
Thanks.
Yes It's possible to get the base64 of a media file
reader.onloadend() is not being called because you might have missed this line reader.readAsDataURL(file).
// here i have a file input and i am using the FileReader Api to read the content on it's change event ( i have no idea what is the event for capturing a media in phonegap
$("#file").change(function(e){
var file = e.currentTarget.files[0];
var FR = new FileReader();
FR.onload = function (encodedFile) {
//alert("onload is called.");
}
FR.onloadend = function (encodedFile) {
var src = encodedFile.target.result;
src = src.split("base64,");
// This is the base64 encoded string of that media file which you will be interested to store in the database(post to the server
var contentAsBase64EncodedString = src[1];
}
reader.readAsDataURL(file);
}