How to detect HTML5 audio MP3 support? - html

I know how to check in Javascript if HTML5 audio playback is available. But how do I specifically check if MP3 audio playback is available, as IE9 and Chrome support it, while Firefox and Opera do not.

You could either check the User-Agent and see what browser is being used or you could test support with Javascript.
var a = document.createElement('audio');
return !!(a.canPlayType && a.canPlayType('audio/mpeg;').replace(/no/, ''));
I got the above code from this page.
return !!(a.canPlayType) is better because (some recent versions of)Firefox not supports mp3 and a.canPlayType('audio/mpeg;') will be false

Modernizr is a library for feature detection. You can use it to do the work for you.
According to the documentation:
If audio support is detected, Modernizr assesses which formats the current browser will play. Currently, Modernizr tests ogg, mp3, wav and m4a.
Important: The values of these properties are not true booleans. Instead, Modernizr matches the HTML5 spec in returning a string representing the browser's level of confidence that it can handle that codec. These return values are an empty string (negative response), "maybe" and "probably". The empty string is falsy, in other words: Modernizr.audio.ogg == '' and '' == false

var test_audio= document.createElement("audio") //try and create sample audio element
var test_video= document.createElement("video") //try and create sample video element
var mediasupport={audio: (test_audio.play)? true : false, video: (test_video.play)? true : false}
alert("Audio Element support: " + mediasupport.audio + "\n"
+ "Video Element support: " + mediasupport.video
)

Related

MediaRecorder does not produce a valid WebM file

MediaRecorder.isTypeSupported() returns true for 'video/webm', 'video/webm;codecs=avc1', and 'video/webm;codecs=vp9'.
However, only mimeType='video/webm;codecs=vp9' results in a valid webm file ('video/webm;codecs=vp9,opus').
Setting mimeType to either 'video/webm' and 'video/webm;codecs=avc1' results in 'video/x-matroska;codecs=avc1,opus' file, which is not a valid webm video.
Is this a MediaRecorder bug, Chrome bug or am I missing something?\
Software: Chrome 85, MacOS 10.15. I have not tried this on Windows or Linux.
Reproduction:
const wantMimeType = 'video/webm;codecs=h264,opus';
if (MediaRecorder.isTypeSupported(wantMimeType)) {
let mediaRecorder = new MediaRecorder(stream, {
mimeType: wantMimeType,
});
// ...drive the recorder
mediaRecorder.onstop = (event) => {
try {
// returns 'video/x-matroska;codecs=avc1,opus' in Chrome,
// and the binary file content also says Matroska instead of WebM
let mimetype = mediaRecorder.mimeType;
if (!mimeType.startsWith('video/webm')) {
throw new Error(`We requested "${wantMimeType},
but the browser gave us "${mediaRecorder.mimeType}"`);
}
let blob = new Blob(chunks, { type: mimeType });
// ...convert to data: URL
// ...play it in <video src="data:..."> // won't work, if Matroska
} catch (ex) {
alert(ex);
}
};
}
Observations:
Chrome responds true to isTypeSupported('video/webm;codecs=h264,opus'), but Chrome actually does not support this combination, i.e. the response is factually incorrect and defeats the entire purpose of isTypeSupported().
Chrome ignores the mimetype that we pass in the MediaRecorder constructor, and instead returns video/x-matroska;codecs=avc1,opus. Which then doesn't work, because <video> won't play the Matroska mimetype.
2 solutions:
Hacky: After recording, just change the mimetype back to video/webm;codecs=h264,opus. The file content will still say "Matroska", but <video> on Chrome will play it. It's a bad solution, because we're passing in the wrong mimetype, it doesn't match the content. Other software - or Chrome in later versions - might break over it.
Proper: Don't use H.264, but VP9 or VP8. Chrome supports both, and Firefox supports VP8, and they work properly. As a bonus, they are open, while H.264 is riddled with software patents. Depending on the hardware encoder implementation, VP8/9 also may give better image quality results.
However, only mimeType='video/webm;codecs=vp9' results in a valid webm file.
Is this a MediaRecorder bug, Chrome bug or am I missing something?
WebM is the correct a/v media container for the VP8 and VP9 video codecs.
AVC1 video codec belongs into an MPEG container (.mp4, .m4v).
This video codec can also be contained inside an MKV media file (Matroska .mkv).

Cannot replay MP3 in Firefox using MediaSource even though it works in Chrome

I have implemented a simple audio player in my web application and noticed that it is not working in Firefox (let me just ... 🎉).
What I get is an error:
ERROR DOMException: MediaSource.addSourceBuffer: Type not supported in MediaSource
This is followed by a warning:
Cannot play media. No decoders for requested formats: audio/mpeg
This is the implementation for the sourceopen event handler:
private onSourceOpen = (e) => {
this.logger.debug('onSourceOpen');
if (!this.sourceBuffer) {
this.sourceBuffer = this.mediaSource.addSourceBuffer('audio/mpeg');
}
this.mediaSource.removeEventListener('sourceopen', this.onSourceOpen);
this.fetchRange(this.trackPlayUrl, 0, this.segmentLength, (chunk) => this.appendSegment(chunk));
}
Where
// Create the media source object
this.mediaSource = new MediaSource();
this.mediaSource.addEventListener('sourceopen', this.onSourceOpen);
Why does it hate me?
Before you try to create a SourceBuffer, you should always call MediaSource.isTypeSupported to determine whether it is likely to play. If that returns false, the user agent is telling you it definitely won't work.
On the latest Firefox:
>> MediaSource.isTypeSupported('audio/mpeg')
<- false
It hates you because Firefox's MediaSource implementation can't play content with that MIME type, whereas Chrome's can.
AAC in ISOBMFF has very broad support, though this would require transcoding and repackaging your audio - try:
MediaSource.isTypeSupported('audio/mp4; codecs="mp4a.40.2"')

Video recording with Edge using HTML5

I am trying to record video using HTML5 API. I want this solution to be cross platform and it should atleast work on Chrome, Firefox and Edge browser. I tried with following code
navigator.mediaDevices.getUserMedia({
audio: true,
video: true
}).then((mediaStream) => {
const video = document.querySelector('video');
const url = window.URL.createObjectURL(mediaStream);
video.src = url;
});
Above code displays video in Chrome and Edge. When I try to capture bytes using MediaRecorder API, it only works in Chrome and not in Edge. Please suggest what can be done.
const recorder = new MediaRecorder(mediaStream);
recorder.ondataavailable = onDataAvailable
...
function onDataAvailable(d){
//d.data is populated in Chrome but not in Edge.
}
Please suggest, how can I capture bytes so that it can be saved on server.
I tried MediaStreamRecorder but that too didn't work with Edge.
Update : I found few approaches which indicate use of Canvas as an option to render frames and capture the bytes. Then use requestAnimationFrame to continue capturing video. While this might work, I am still open to any other better suggestions.
The MediaRecorder API seem to be only implemented in FireFox & Chrome
https://caniuse.com/#search=MediaRecorder
I'd always check caniuse.com for browser support for new APIs!

Handling Html5 Video + Mp4 source ONLY in Old Browsers

How to error handle html5 video + only mp4 source under old browsers.
Most of the browsers have support for html5 but not mp4. How to detect this and output an error for the user?
Keep in mind these things:
The client will use only mp4
The video element will be used multiple videos all mp4
Convertion mp4 to webmm/ogg is not a solution in this case
I need only a way to generate error for browsers that won't play the video. How to do this? Thanks!
You can use HTMLMediaElement.canPlayType() and get the value if your browser support mp4 or not.
var video = document.createElement('video');
console.log(video.canPlayType('video/mp4')); // "maybe"
Possible answers are:
'probably': The specified media type appears to be playable.
'maybe': Cannot tell if the media type is playable without playing it.
'' (empty string): The specified media type definitely cannot be played.
Hi you can handle it as below.
var videoSource1 = '<source src="//anc.com/video1.webm" type="video/webm"/>';
var videoSource2 = '<source src ="//abc.com/video2.mp4" type = "video/mp4"/>';
var videoSource = videoSource1 + videoSource2;
$('.video-container').append(videoSource);
The above code will detect any one of file on the basis of browser support.

Fallback solution for HTML <audio> and legacy browsers

I am working on creating a sound board with various audio clips.
Rather than using the standard HTML5 audio controls, I want to style each button with some title text, so that when a user presses a button, the associated clip plays.
Everything is working fine in HTML 5 browsers (Chrome, Firefox, Safari, and IE9+), using the following code:
<script type="text/javascript" charset="utf-8">
$(function() {
$("audio").removeAttr("controls").each(function(i, audioElement) {
var audio = $(this);
var that = this; //closure to keep reference to current audio tag
$("#doc").append($('<button>'+audio.attr("title")+'</button>').click(function() {
that.play();
}));
});
});
</script>
<!-- Sample Audio Clip -->
<audio controls preload="auto" autobuffer title="Sounds of Laughter">
<source src="assets/clips/1.mp3" />
<source src="assets/clips/1.ogg" />
</audio>
However, this solution is not supported on non-HTML 5 compliant browsers like Internet Explorer 8.
I am looking for some sort of workaround solution that will allow me to either (a) detect if a browser doesn't support the HTML 5 tag and redirect to an alternate version of the sound board or (b) use a fallback (flash, etc.) with custom styling on the button if support is not present.
You should use both Modernizr as Garret said and jPlayer
Check Garrett's answer on how to check for compatibility. Though I don't see why it would be useful if your only goal is to seamlessly play HTML5 or Flash based on compatibility. jPlayer does it automatically.
You just have to instantiate it:
$("#music").jPlayer({
ready: function (event) {
$(this).jPlayer("setMedia", {
mp3:"music.mp3",
oga:"music.ogg"
});
},
swfPath: "js",
supplied: "mp3, oga"
});
The following depends on the interface you want to use. jPlayer has some skins, but you can modify them to your will or just create a whole interface from scratch like I do and use jPlayer methids
You should take a look at the Modernizr script library. This will allow you to perform conditional logic based on what HTML5 features are supported by the browser. For example, you could do something like this:
var audio = new Audio();
audio.src = Modernizr.audio.ogg ? 'background.ogg' :
Modernizr.audio.mp3 ? 'background.mp3' :
'background.m4a';
audio.play();
Documentation can be found here: http://modernizr.com/docs/#features-html5.
I found another example which I have slightly modified for MP3 to OGG fallback. It uses the canPlayType method:
var audiofile = 'example.mp3';
var audioTag = document.createElement('audio');
if (!(!!(audioTag.canPlayType) && ("no" != audioTag.canPlayType("audio/mpeg"))
&& ("" != audioTag.canPlayType("audio/mpeg")))) {
audiofile = audiofile.replace('.mp3','.ogg');
}