Javascript: Microphone audio to download link? - javascript

I'm trying to record audio from the microphone and then add a download link for it.
This is my current code:
<!DOCTYPE html>
<html>
<head>
<title>Weird Problem</title>
<script>
function microphone() {
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia({ audio: true, video: false }).then(function(stream) {
var recorder = new MediaRecorder(stream);
var chunks = [];
recorder.ondataavailable = function(e) {
chunks.push(e.data);
}
recorder.onstop = function() {
stream.getTracks()[0].stop();
var blob = new Blob(chunks, { type: "audio/ogg; codecs=opus" });
var url = window.URL.createObjectURL(blob);
document.getElementById("player").src = url;
document.getElementById("upload").href = url;
document.getElementById("upload").download = "test.ogg";
}
recorder.start();
setTimeout(function() {
recorder.stop();
}, 5000);
}).catch(function(error) {
console.log(error);
});
}
}
</script>
</head>
<body>
<input type="button" value="Record Microphone" onclick="microphone();">
<br>
<audio controls id="player"></audio>
<br>
<a id="upload">Download Microphone Recording</a>
</body>
</html>
I'm on Chrome, and for me it plays the microphone audio correctly, but when I try to download it, the file won't play or even open.
I get various errors that the file contains data in an unknown format, so I think it's something to do with the audio headers.
Any help would be highly appreciated!

It turns out this issue is a bit more complicated than I expected.
I'm now adapting code from Recorder.js.
The online demo does exactly what I need.

Related

getUserMedia while in AR freezes browser

In XRViewer on iOS, I'm trying to set up a basic A-Frame scene in AR and a stream from getUserMedia.
I only have a video element and an a-scene. On enter-vr, I attempt to start a stream from getUserMedia.
On pressing the "AR" button, as expected, it prompts me to allow camera access. But when I allow it, I get a pop-up that an "AR Interuption Occured" and everything freezes.
Is getUserMedia expected to work while in AR? Is there another way to access the passthrough stream? getUserMedia does work as expected if I don't enter AR.
Here is my code:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script src="https://cdn.jsdelivr.net/gh/aframevr/aframe#54022b80c60b12dc755f4f4a71a779b410dd23d0/dist/aframe-master.min.js"></script>
<script>
function start() {
const videoElement = document.querySelector("#video");
videoElement.setAttribute("autoplay", "");
videoElement.setAttribute("muted", "");
videoElement.setAttribute("playsinline", "");
videoElement.style.position = "absolute";
videoElement.style.top = "0px";
videoElement.style.left = "0px";
videoElement.style.zIndex = "-2";
videoElement.style.display = "none";
navigator.mediaDevices
.getUserMedia({
audio: false,
video: {
facingMode: { exact: "user" },
},
})
.then((stream) => {
videoElement.addEventListener("loadedmetadata", () => {
videoElement.setAttribute("width", videoElement.videoWidth);
videoElement.setAttribute("height", videoElement.videoHeight);
});
videoElement.srcObject = stream;
})
.catch((err) => {
console.error("no video" + err);
});
}
document.addEventListener("DOMContentLoaded", function () {
document
.querySelector("#scene")
.addEventListener("enter-vr", function () {
start();
});
});
</script>
</head>
<body>
<a-scene
id="scene"
device-orientation-permission-ui="enabled: false"
stats
></a-scene>
<video id="video"></video>
</body>
</html>

Request permission to automatically play an audio file

I have a function in js that checks a variable date, and if it is present it starts an audio file.
Since with the new privacy it is not possible to start an audio file automatically, in fact in my case it is blocked.
I would like to have the broswer box appear to give consent to the reproduction of the audio file.
But, I do not know how can I do it.
Can you help me?
var audio = new Audio('/sound/file-one.mp3');
setInterval(function() {
$.ajax({
url: '/check_data.php',
type: 'post',
data: {
'check_data' : 1
},
success: function(response){
if (response != "false") {
audio.addEventListener('ended', function () {
audio.play();
}, false);
audio.play();
}
}
});
}, 5000);
User must start Audio, after Audio is started by a user action, you can change source whenever you want.
const audio = document.getElementById("au");
let bt = document.getElementById("bt");
console.log(audio);
bt.addEventListener("click", ()=>{
audio.play();
});
const startPlaying = ()=>{
audio.removeEventListener('playing', startPlaying);
bt.classList.add("hide");
audio.src = 'https://freesound.org/data/previews/475/475736_4397472-lq.mp3';
audio.play();
}
audio.addEventListener('playing', startPlaying);
audio.addEventListener('error', ()=>{
console.log("error");
});
.hide{
display:none;
}
<input id="bt" type="button" value="Accept">
<audio id="au" preload="auto" src="https://raw.githubusercontent.com/anars/blank-audio/master/500-milliseconds-of-silence.mp3"></audio>

How to play a video in a Seamless loop using media source extensions

I am working on media source extension to play the video in a seamless loop without any delay. I have done an extensive r&d about it and also done different things. Now i am working on this code
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
</head>
<body>
<video controls></video>
<script>
var video = document.querySelector('video');
var assetURL = 'test1.mp4';
// Need to be specific for Blink regarding codecs
// ./mp4info frag_bunny.mp4 | grep Codec
var mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
if ('MediaSource' in window && MediaSource.isTypeSupported(mimeCodec)) {
var mediaSource = new MediaSource;
//console.log(mediaSource.readyState); // closed
video.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener('sourceopen', sourceOpen);
} else {
console.error('Unsupported MIME type or codec: ', mimeCodec);
}
function sourceOpen (_) {
//console.log(this.readyState); // open
var mediaSource = this;
var sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
fetchAB(assetURL, function (buf) {
sourceBuffer.addEventListener('updateend', function (_) {
mediaSource.endOfStream();
video.play();
//console.log(mediaSource.readyState); // ended
});
sourceBuffer.appendBuffer(buf);
});
};
function fetchAB (url, cb) {
console.log(url);
var xhr = new XMLHttpRequest;
xhr.open('get', url);
xhr.responseType = 'arraybuffer';
xhr.onload = function () {
cb(xhr.response);
};
xhr.send();
};
</script>
</body>
</html>
It is working fine but the video is playing again with a slight delay. I want to play the video without any delay and I know that it is possible with media source extensions but after spending a lot of time still didn't get any idea that how to do it. Any help would be really appreciated. Thanks
Setting the mode value to sequence worked for me, it ensures continuous media playback, no matter if the media segment timestamps were discontinuous.
sourceBuffer.mode = 'sequence';
May be this code solve Your Problem ....play the video in a seamless loop without any delay
for (let chunk of media) {
await new Promise(resolve => {
sourceBuffer.appendBuffer(chunk.mediaBuffer);
sourceBuffer.onupdateend = e => {
sourceBuffer.onupdateend = null;
sourceBuffer.timestampOffset += chunk.mediaDuration;
console.log(mediaSource.duration);
resolve()
}
})
}
if you need more information visit this link.....
http://www.esjay.org/2020/01/01/videos-play-without-buffering-in-javascript/
You can't really do that because it really depends on how fast your PC runs. Its delay should only be there if you have a slow PC but if not it shouldn't have a noticeable delay. Maybe the video that you have is big or it just delays inside the video because only thing I could tell you is autoplay loop inside the videos element as a attribute unless you find a way to replay the video before the video ends but even if it doesn't delay for you it may delay big or just play over the video for others
#CoolOppo
The simplest thing to do is to just rewind the video when it reaches it's end time (duration).
See demo here: https://vc-lut.000webhostapp.com/demos/public/mse_loop_example1.html
(to play video just click the picture part, since no controls for looping background)
The code:
<!DOCTYPE html>
<html>
<head> <meta charset="utf-8"/> </head>
<body>
<div>
<video id="video_mse" > </video>
</div>
<script>
var assetURL = "testloop.mp4";
//# use correct mime/codecs or else Error is "source not open"...
var mimeCodec = 'video/mp4; codecs="avc1.42C01E"';
var mediaSource; var sourceBuffer;
var video = document.getElementById( "video_mse" );
video.onclick = vid_togglePlay; //# for playing/pausing
video.ontimeupdate = vid_checkTime; //# for looping
//# handle play/pause (because controls are hidden)
function vid_togglePlay()
{
if( video.paused == true ) { video.play(); }
else { video.pause(); }
}
//# handle looping...
function vid_checkTime()
{
if( video.currentTime == video.duration)
{
video.currentTime = 0;
video.play();
}
}
if ( 'MediaSource' in window && MediaSource.isTypeSupported(mimeCodec) )
{
mediaSource = new MediaSource;
video.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener('sourceopen', sourceOpen);
}
else
{ console.error('Unsupported MIME type or codec: ', mimeCodec); }
function sourceOpen()
{
//console.log(this.readyState); // open
var mediaSource = this;
sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
fetchAB(assetURL, function (buf) {
sourceBuffer.addEventListener('updateend', function() {
mediaSource.endOfStream();
video.play();
});
sourceBuffer.appendBuffer(buf);
});
};
function fetchAB (url, callbackfunc )
{
console.log("loading file: " + url);
var xhr = new XMLHttpRequest;
xhr.open('get', url);
xhr.responseType = 'arraybuffer';
xhr.onload = function() { callbackfunc( xhr.response ); }
xhr.send();
}
</script>
</body>
</html>

Javascript mediaSource element

I am trying to play a video using javascript mediasource to hide video URL from the users. But I get an error as,
Uncaught InvalidStateError: Failed to execute 'endOfStream' on 'MediaSource': The MediaSource's readyState is not 'open'. And it would also be helpful if the video type and codes to be passed dynamically.
Below is my code,
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
</head>
<body>
<video controls></video>
<script>
var video = document.querySelector('video');
var assetURL = 'adsss.mp4';
// Need to be specific for Blink regarding codecs
// ./mp4info frag_bunny.mp4 | grep Codec
var mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
if ('MediaSource' in window && MediaSource.isTypeSupported(mimeCodec)) {
var mediaSource = new MediaSource;
//console.log(mediaSource.readyState); // closed
video.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener('sourceopen', sourceOpen);
} else {
console.error('Unsupported MIME type or codec: ', mimeCodec);
}
function sourceOpen (_) {
console.log(this.readyState); // open
var mediaSource = this;
console.log(mediaSource);
var sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
console.log(sourceBuffer);
fetchAB(assetURL, function (buf) {
sourceBuffer.addEventListener('updateend', function (_) {
mediaSource.endOfStream();
video.play();
console.log(mediaSource.readyState); // ended
});
sourceBuffer.appendBuffer(buf);
});
};
function fetchAB (url, cb) {
console.log(url);
var xhr = new XMLHttpRequest;
xhr.open('get', url);
console.log(xhr);
xhr.responseType = 'arraybuffer';
xhr.onload = function () {
cb(xhr.response);
console.log(xhr.response);
};
xhr.send();
};
</script>
The reason why the above code was not working is that, only fragmented mp4 videos with moov(movie header box) moved at the beginning will be played using the Media source.
Refer the below links,
1) Unable to get MediaSource working with mp4 format in chrome
2) What exactly is Fragmented mp4(fMP4)? How is it different from normal mp4?
You can fragment your videos using MP4box tool with the following command,
MP4Box -dash 1000 -rap -frag-rap test.mp4

MediaRecorder videos longer than a few seconds don't play back

I'd like to record a video in the browser and then play it back for the user. I'm currently using the MediaRecorder API (only available in Firefox for now) to do this. It works fine for videos shorter than a few seconds, but otherwise the video doesn't show up at all.
There are no errors in the console or similar, and I couldn't find anything about any file size limitations in the documentation.
Here's the code I'm using (Firefox only):
index.html:
<!DOCTYPE html>
<html>
<body>
<button id="start">Start</button>
<button id="stop">Stop</button>
<video id="player" src="" width="300" height="300" autoplay></video>
<script src="script.js"></script>
</body>
</html>
script.js:
var record = document.getElementById('start');
var stop = document.getElementById('stop');
var video = document.getElementById('player');
var constraints = {video: true};
var onSuccess = function(stream) {
var mediaRecorder = new MediaRecorder(stream);
record.onclick = function() {
mediaRecorder.start();
}
stop.onclick = function() {
mediaRecorder.stop();
}
mediaRecorder.ondataavailable = function(e) {
video.src = window.URL.createObjectURL(e.data);
}
};
var onError = function(err) {
console.log('The following error occured: ' + err);
}
navigator.mozGetUserMedia(constraints, onSuccess, onError);
On Codepen: http://codepen.io/anon/pen/xGqKgE
Is this a bug/browser issue? Are there any limitations to this API that I'm not aware of?

Categories