Google chrome sends an ogg file as webm - google-chrome

im using mediaStreamRecorder to record a ogg file and send it to my API via Websocket and it is not compatible with WebM, it works fine in other browsers, but in chrome, my api says that the file is a webM, and throws an error.
this is part of my recorder.js file:
mediaRecorder.onstop = function(e) {
if (audioarray.length>=2){
var blob = new Blob(audioarray, { 'type' : 'audio/ogg; codecs=opus' });
var blobURL = URL.createObjectURL(blob);
blobsize = blob.size;
reader.readAsDataURL(blob);
reader.onload = function(event){
codedaudio = reader.result;
console.log("File size: "+blobsize);
audiourl = event.target.result;
//cut Base64 code to the last ","
audiomsg = codedaudio.substring(codedaudio.lastIndexOf(",")+1,codedaudio.length);
console.log("Audio length: "+audioarray.length);
sendMessage(audiomsg,'right','audio',blobURL);
console.log("MediaStreamrecorder stopped");
audioarray = [];
};
}else{
// ToDo in short audio case
console.log("audio is too short, it will not be sent")
console.log("Audio length: "+audioarray.length);
audioarray = [];
};
}
here part of code that sends the ogg:
sendMessage = function (text,side,type,filepath) {
webmessage = {
message:text,
type: type
}
message_side = side;
//output debug
if(text!=""){
ws.send(JSON.stringify(webmessage));
if (output==true){
console.log(webmessage);
}
}
};
¿is there any way to send it as ogg on chrome?.

Unlike Firefox and possibly some other browsers, Chrome doesn't support recording audio-only in an ogg container.
You can test the support with:
MediaRecorder.isTypeSupported("audio/ogg")

Related

How to release memory using Web Audio API?

var context = new window.AudioContext()
var request = cc.loader.getXMLHttpRequest();
request.open("GET", 'res/raw-assets/resources/audio/bgm.mp3', true);
request.responseType = "arraybuffer";
request.onload = function () {
context["decodeAudioData"](request.response, function(buffer){
//success
cc.log('success')
window.buffer = buffer
playBgm()
}, function(){
//error
});
};
request.onerror = function(){
//error
};
request.send();
function playBgm(){
var audio = context["createBufferSource"]();
audio.buffer = buffer;
var _volume = context['createGain']();
_volume['gain'].value = 1;
_volume['connect'](context['destination']);
audio["connect"](_volume);
audio.start(0)
}
in my code I load a mp3 file and decode it into AudioBuffer(window.buffer)
then I play it successful
but it cost a lot memory about 100MB
How to release them?
I tried like this
audio.stop()
audio = null
window.buffer = null
//context.close()
//context = null
chrome memory view
in the chrome memory view
sometimes the memory release in about 10second
sometimes release in about 1min
sometimes seems never release
I want to know if my code is the right way to release audiobuffer?
Do I need to close AudioContext?

In chrome App, video file is not saved with its original data/size

In appCtrl.js, for saving video file -
$('#save_file').click(function(e) {
var config = {type: 'saveFile', suggestedName: chosenEntry.name};
chrome.fileSystem.chooseEntry(config, function(writableEntry) {
//blob content is the DataUrl
var blob = new Blob([$scope.blobContent], {type: 'video/mp4'});
$scope.writeFileEntry(writableEntry, blob, function(e) {
console.log('Write complete :)');
});
});
});
$scope.writeFileEntry = function(writableEntry, opt_blob, callback) {
if (!writableEntry) {
console.log('Nothing selected.');
return;
}
writableEntry.createWriter(function(writer) {
writer.onerror = $scope.errorHandler;
writer.onwriteend = callback;
// If we have data, write it to the file. Otherwise, just use the file we
// loaded.
if (opt_blob) {
writer.truncate(opt_blob.size);
$scope.waitForIO(writer, function() {
writer.seek(0);
writer.write(opt_blob);
});
}
else {
chosenEntry.file(function(file) {
writer.truncate(file.fileSize);
waitForIO(writer, function() {
writer.seek(0);
writer.write(file);
});
});
}
}, $scope.errorHandler);
}
$scope.waitForIO = function(writer, callback) {
// set a watchdog to avoid eventual locking:
var start = Date.now();
// wait for a few seconds
var reentrant = function() {
if (writer.readyState===writer.WRITING && Date.now()-start<4000) {
setTimeout(reentrant, 100);
return;
}
if (writer.readyState===writer.WRITING) {
console.error("Write operation taking too long, aborting!"+
" (current writer readyState is "+writer.readyState+")");
writer.abort();
}
else {
callback();
}
};
setTimeout(reentrant, 100);
};
In above code the video file is saved but when i tried to play that saved file in Window Media Player or VLC player , it prompt me as Window media player cannot play the file.The player might not support the file type or might not support the codec that was used to compress the file.
Can u please guide me where m getting wrong, as its my first chrome app.
Thanks in advance.
Change the method to store blob like this.
function dataURItoBlob(dataURI, callback) {
// convert base64 to raw binary data held in a string
// doesn't handle URLEncoded DataURIs
var byteString = atob(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]
// write the bytes of the string to an ArrayBuffer
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ab], {type: 'video/mp4'});
};
To handle click.
$('#save_file').click(function(e) {
var config = {type: 'saveFile', suggestedName: chosenEntry.name};
chrome.fileSystem.chooseEntry(config, function(writableEntry) {
var blob = dataURItoBlob($scope.blobContent);
$scope.writeFileEntry(writableEntry, blob, function(e) {
console.log('Write complete :)');
});
});
});

How to get media stream object form HTML5 video element in javascript

all
I'm in peer to peer communication using webRTC , we have media stream object from the getUserMedia which is given as input stream to peerconnection. Here I need video stream from the selected video file from the local drive which is playing using Video element of HTML5.
Is it possible to create mediastream object from the video tag?
thanks,
suri
For now you can't add a media stream from a video tag, but it should be possible in the future, as it is explained on MDN
MediaStream objects have a single input and a single output. A MediaStream object generated by getUserMedia() is called local, and has as its source input one of the user's cameras or microphones. A non-local MediaStream may be representing to a media element, like or , a stream originating over the network, and obtained via the WebRTC PeerConnection API, or a stream created using the Web Audio API MediaStreamAudioSourceNode.
But you can use Media Source Extensions API to do what yo want : you have to put the local file into a stream and append in in a MediaSource object. You can learn more about MSE here : http://www.w3.org/TR/media-source/
And you can find a demo and source of the method above here
2021 update: It is now possible using MediaRecorder interface: https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder
Example from same page:
if (navigator.mediaDevices) {
console.log('getUserMedia supported.');
var constraints = { audio: true };
var chunks = [];
navigator.mediaDevices.getUserMedia(constraints)
.then(function(stream) {
var mediaRecorder = new MediaRecorder(stream);
visualize(stream);
record.onclick = function() {
mediaRecorder.start();
console.log(mediaRecorder.state);
console.log("recorder started");
record.style.background = "red";
record.style.color = "black";
}
stop.onclick = function() {
mediaRecorder.stop();
console.log(mediaRecorder.state);
console.log("recorder stopped");
record.style.background = "";
record.style.color = "";
}
mediaRecorder.onstop = function(e) {
console.log("data available after MediaRecorder.stop() called.");
var clipName = prompt('Enter a name for your sound clip');
var clipContainer = document.createElement('article');
var clipLabel = document.createElement('p');
var audio = document.createElement('audio');
var deleteButton = document.createElement('button');
clipContainer.classList.add('clip');
audio.setAttribute('controls', '');
deleteButton.innerHTML = "Delete";
clipLabel.innerHTML = clipName;
clipContainer.appendChild(audio);
clipContainer.appendChild(clipLabel);
clipContainer.appendChild(deleteButton);
soundClips.appendChild(clipContainer);
audio.controls = true;
var blob = new Blob(chunks, { 'type' : 'audio/ogg; codecs=opus' });
chunks = [];
var audioURL = URL.createObjectURL(blob);
audio.src = audioURL;
console.log("recorder stopped");
deleteButton.onclick = function(e) {
evtTgt = e.target;
evtTgt.parentNode.parentNode.removeChild(evtTgt.parentNode);
}
}
mediaRecorder.ondataavailable = function(e) {
chunks.push(e.data);
}
})
.catch(function(err) {
console.log('The following error occurred: ' + err);
})
}
MDN also has a detailed mini tutorial: https://developer.mozilla.org/en-US/docs/Web/API/MediaStream_Recording_API/Recording_a_media_element

Download attribute on A tag not working in IE

From the following code I'm creating a dynamic anchor tag which downloads a file. This code works well in Chrome but not in IE. How can I get this working
<div id="divContainer">
<h3>Sample title</h3>
</div>
<button onclick="clicker()">Click me</button>
<script type="text/javascript">
function clicker() {
var anchorTag = document.createElement('a');
anchorTag.href = "http://cdn1.dailymirror.lk/media/images/finance.jpg";
anchorTag.download = "download";
anchorTag.click();
var element = document.getElementById('divContainer');
element.appendChild(anchorTag);
}
</script>
Internet Explorer does not presently support the Download attribute on A tags.
See http://caniuse.com/download and http://status.modern.ie/adownloadattribute; the latter indicates that the feature is "Under consideration" for IE12.
In my case, since there's a requirement to support the usage of IE 11 (version 11.0.9600.18665), I ended up using the solution provided by #Henners on his comment:
// IE10+ : (has Blob, but not a[download] or URL)
if (navigator.msSaveBlob) {
return navigator.msSaveBlob(blob, fileName);
}
It's quite simple and practical.
Apparently, this solution was found on the Javascript download function created by dandavis.
Old question, but thought I'd add our solution. Here is the code I used on my last project. It's not perfect, but it passed QA in all browsers and IE9+.
downloadCSV(data,fileName){
var blob = new Blob([data], {type: "text/plain;charset=utf-8;"});
var anchor = angular.element('<a/>');
if (window.navigator.msSaveBlob) { // IE
window.navigator.msSaveOrOpenBlob(blob, fileName)
} else if (navigator.userAgent.search("Firefox") !== -1) { // Firefox
anchor.css({display: 'none'});
angular.element(document.body).append(anchor);
anchor.attr({
href: 'data:attachment/csv;charset=utf-8,' + encodeURIComponent(data),
target: '_blank',
download: fileName
})[0].click();
anchor.remove();
} else { // Chrome
anchor.attr({
href: URL.createObjectURL(blob),
target: '_blank',
download: fileName
})[0].click();
}
}
Using the ms specific API worked best for us in IE. Also note that some browsers require the anchor to actually be in the DOM for the download attribute to work, whereas Chrome, for example, does not. Also, we found some inconsistencies with how Blobs work in various browsers. Some browsers also have an export limit. This allows the largest possible CSV export in each browser afaik.
As of build 10547+, the Microsoft Edge browser is now supporting the download attribute on a tags.
Download Image
Edge features update: https://dev.windows.com/en-us/microsoft-edge/platform/changelog/desktop/10547/
a[download] standard: http://www.w3.org/html/wg/drafts/html/master/links.html#attr-hyperlink-download
This code fragment allows saving blob in the file in IE, Edge and other modern browsers.
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (request.readyState === 4 && request.status === 200) {
// Extract filename form response using regex
var filename = "";
var disposition = request.getResponseHeader('Content-Disposition');
if (disposition && disposition.indexOf('attachment') !== -1) {
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
}
if (window.navigator.msSaveOrOpenBlob) { // for IE and Edge
window.navigator.msSaveBlob(request.response, filename);
} else {
// for modern browsers
var a = document.createElement('a');
a.href = window.URL.createObjectURL(request.response);
a.download = filename;
a.style.display = 'none';
document.body.appendChild(a);
a.click();
}
}
button.disabled = false;
dragArea.removeAttribute('spinner-visible');
// spinner.style.display = "none";
};
request.open("POST", "download");
request.responseType = 'blob';
request.send(formData);
For IE and Edge use: msSaveBlob
Use my function
It bind your atag to download file in IE
function MS_bindDownload(el) {
if(el === undefined){
throw Error('I need element parameter.');
}
if(el.href === ''){
throw Error('The element has no href value.');
}
var filename = el.getAttribute('download');
if (filename === null || filename === ''){
var tmp = el.href.split('/');
filename = tmp[tmp.length-1];
}
el.addEventListener('click', function (evt) {
evt.preventDefault();
var xhr = new XMLHttpRequest();
xhr.onloadstart = function () {
xhr.responseType = 'blob';
};
xhr.onload = function () {
navigator.msSaveOrOpenBlob(xhr.response, filename);
};
xhr.open("GET", el.href, true);
xhr.send();
})
}
Append child first and then click
Or you can use window.location= 'url' ;
As mentioned in earlier answer , download attribute is not supported in IE . As a work around, you can use iFrames to download the file . Here is a sample code snippet.
function downloadFile(url){
var oIframe = window.document.createElement('iframe');
var $body = jQuery(document.body);
var $oIframe = jQuery(oIframe).attr({
src: url,
style: 'display:none'
});
$body.append($oIframe);
}
I copied the code from here and updated it for ES6 and ESLint and added it to my project.
You can save the code to download.js and use it in your project like this:
import Download from './download'
Download('/somefile.png', 'somefile.png')
Note that it supports dataURLs (from canvas objects), and more... see https://github.com/rndme for details.

Use other source of sound effect when using firefox beside mp3

I'm trying to make a menu with sound after user clicks it. It works well in Chrome, safari, and even IE, but not Mozilla Firefox. I use mp3 file for the sound which can't run on firefox. Here's the code
function loadSound (src) {
var sound = document.createElement("audio");
if ("src" in sound) {
sound.autoPlay = false;
}
else {
sound = document.createElement("bgsound");
sound.volume = -10000;
sound.play = function () {
this.src = src;
this.volume = 0;
}
}
sound.src = src;
document.body.appendChild(sound);
return sound;
}
$(document).ready(function () {
var sound = loadSound("<?=base_url()?>sound/testing.mp3"); // preload
$(".main_nav a").click(function(){
var ids = $(this).attr("id").split("-");
var url = ids[2];
sound.play();
setTimeout (function(){window.location = url;}, 2000);
return false;
});
});
What type of audio file works in firefox? How do I change the source file when a user use firefox?
Ok, I understand your problem and I have a solution.
You could use this function that I make:
function getSupportedAudio(){
var testEl = document.createElement( "audio" ), mp3, ogg;
if ( testEl.canPlayType ) {
mp3 = "" !== testEl.canPlayType( 'audio/mpeg;' );
ogg = "" !== testEl.canPlayType( 'audio/ogg' );
}
if(mp3){
return ".mp3";
}
else{
return ".ogg";
}
}
In your function loadSound(src) use this:
sound.src = src+getSupportedAudio();
document.body.appendChild(sound);
And when you call the loadSound function, don't send the audio format in the parameter (but you need to have both files, ogg and mp3, in the same folder and with the same name):
var sound = loadSound("<?=base_url()?>sound/testing"); // preload