I'm attempting to display a video in Firefox. The video has to be in MP4, converting the video isn't an option. However this will only work in some situations as Firefox relies on OS level support for MP4, rather than built in support.
It's ok that it won't always work, but I want to be able to detect when it will fail.
I've tried several existing solutions on StackOverflow ( How to check if the browser can play mp4 via html5 video tag? )
My current testing code reads:
var mp4Supported = (!!document.createElement('video').canPlayType('video/mp4; codecs=avc1.42E01E,mp4a.40.2'));
if (!mp4Supported) { console.log("MP4 not supported") } else { console.log("MP4 supported") };
However since Firefox now does (technically) support MP4, this seems to always return true, whether the video can be decoded or not.
Console output from the above on Firefox where there's no native support for MP4:
"MP4 supported"
Media resource <My resource URL> could not be decoded.
Does anyone know of a reliable way to detect successful running now that Firefox has partial support?
Related
Problem
I am recording the webm chunks by MediaRecorder at Chrome 83 in Windows 10 and sending these to other computer. These chunks are playing on another Chrome by using Media Source Extension(MSE).
sourceBuffer.appendBuffer(webmChunkData);
Everything works fine between 1 to 1.20 seconds. But after that, the audio/video syncing problem starts. The gap between audio and video is minimal at the moment, but as time increases, the gap also rises.
The weird thing is that we can see the different behaviour on different browsers, let me show this by
Chrome's version is 83+ in almost all operating systems.
Camera can be the problem ?
I think Camera is not the problem as I have dual operating systems Fedora and Windows in the same machine. And webm chunks play fine with the Fedora.
Sample rate can be the problem ?
I doubt this. But when I compare the sample rate used by browsers while playing. chrome://media-internals shows 48000 for both with and without a syncing problem.
Warning message from Chrome
Chrome which has sync problem also shows the below message on chrome://media-internals
Question:
Why there is an audio/video syncing problem when both recording and playing are performed on Chrome browser in Windows 10?
How can I eliminate this syncing problem?
I believe I have a workaround for you. The problem seems specific to Chrome + MediaRecorder + VP8, and has nothing to do with MSE or the platform. I have the same issues on Chrome 98 on Mac 12.2.1. Additionally, if you decrease the .start(timeslice) argument, the issue will appear more rapidly and more severely.
However... when I use VP9 the problem does not manifest!
I'm using code like this:
function supportedMimeTypes(): string[] {
// From least desirable to most desirable
return [
// most compatible, but chrome creates bad chunks
'video/webm;codecs=vp8,opus',
// works in chrome, firefox falls back to vp8
'video/webm;codecs=vp9,opus'
].filter(
(m) => MediaRecorder.isTypeSupported(m)
);
}
const mimeType = supportedMimeTypes().pop();
if (!mimeType) throw new Error("Could not find a supported mime-type");
const recorder = new MediaRecorder(stream, {
// be sure to use a mimeType with a specific `codecs=` as otherwise
// chrome completely ignores it and uses video/x-matroska!
// https://stackoverflow.com/questions/64233494/mediarecorder-does-not-produce-a-valid-webm-file
mimeType,
});
recorder.start(1000)
The resulting VP9 appears to play in Firefox, and a VP8 recorded in Firefox plays well in Chrome too.
I have an issue with the MediaRecorder API. It works fine on Chrome and used to work on earlier versions of Firefox (Mac), but since version 53.0.2, I get the following in the dev console:
--> MediaRecorder.isTypeSupported('audio/webm')
false
--> MediaRecorder.isTypeSupported('video/webm')
true
Did Firefox stop supporting audio recording through the MediaRecorder API?
Firefox did implement MediaRecorder.isTypeSupported() in FF47. I did an mozRegression loop between now and 47 to check when it did change as you said.
Result : It never reported true for audio/webm in any version tried (on osX).
But, Firefox does support audio/ogg mimeType, (which I guess is the default for audio only). And since both Firefox and Chrome do record audio encoded with an Opus codec, the more common mimeType for the container is indeed audio/ogg.
Note that Chrome doesn't return true for audio/ogg.
Looking forward for this API.
I have this javascript audio player which plays mp3 files. On FF v23.0.1 (Mac) it doesn't work (the reason for this is explained everywhere and here)
What I don't understand is, if I point the URL directly to the mp3 file FF shows its own player and the song plays just fine. But when using the javascript Audio API
var audio = new Audio('/my-song.mp3') ; // --> HTTP “Content-Type” van “audio/mpeg” not supported
audio.autoplay = true ;
it doesn't work. Can someone explain to me why this is ?
Thnx
The error is (note that I've translated it to english): HTTP “Content-Type” of “audio/mpeg” is not supported.
Your Firefox build does not seem to support MP3 yet.
The player that is shown when directly browsing the .mp3 might be just some plugin handling the Content-Type, such as QuickTime, VLC, etc... That won't fly when using that file in an <audio> element, though.
See the "Media formats supported..." article for information on what codecs are supported by what version of Firefox on what platform.
Neither Safari or Firefox are able to process audio data from a MediaElementSource using the Web Audio API.
var audioContext, audioProcess, audioSource,
result = document.createElement('h3'),
output = document.createElement('span'),
mp3 = '//www.jonathancoulton.com/wp-content/uploads/encodes/Smoking_Monkey/mp3/09_First_of_May_mp3_3a69021.mp3',
ogg = '//upload.wikimedia.org/wikipedia/en/4/45/ACDC_-_Back_In_Black-sample.ogg',
gotData = false, data, audio = new Audio();
function connect() {
audioContext = window.AudioContext ? new AudioContext() : new webkitAudioContext(),
audioSource = audioContext.createMediaElementSource( audio ),
audioScript = audioContext.createScriptProcessor( 2048 );
audioSource.connect( audioScript );
audioSource.connect( audioContext.destination );
audioScript.connect( audioContext.destination );
audioScript.addEventListener('audioprocess', function(e){
if ((data = e.inputBuffer.getChannelData(0)[0]*3)) {
output.innerHTML = Math.abs(data).toFixed(3);
if (!gotData) gotData = true;
}
}, false);
}
(function setup(){
audio.volume = 1/3;
audio.controls = true;
audio.autoplay = true;
audio.src = audio.canPlayType('audio/mpeg') ? mp3 : ogg;
audio.addEventListener('canplay', connect);
result.innerHTML = 'Channel Data: ';
output.innerHTML = '0.000';
document.body.appendChild(result).appendChild(output);
document.body.appendChild(audio);
})();
Are there any plans to patch this in the near future? Or is there some work-around that would still provide the audio controls to the user?
For Apple, this something that could be fixed in the WebKit Nightlies or will we have to wait until Safari 8.0 release to get HTML5 <audio> playing nicely with the Web Audio API? The Web Audio API has existed in Safari since at least version 6.0 and I initially posted this question long before Safari 7.0 was released. Is there a reason this wasn't fixed already? Will it ever be fixed?
For Mozilla, I know you're still in the process of switching over from the old Audio Data API, but is this a known issue with your Web Audio implementation and is it going to be fixed before the next release of Firefox?
This answer is quoted almost exactly from my answer to a related question: Firefox 25 and AudioContext createJavaScriptNote not a function
Firefox does support MediaElementSource if the media adheres to the Same-Origin Policy, however there is no error produced by Firefox when attempting to use media from a remote origin.
The specification is not really specific about it (pun intended), but I've been told that this is an intended behavior, and the issue is actually with Chrome… It's the Blink implementations (Chrome, Opera) that need to be updated to require CORS.
MediaElementSource Node and Cross-Origin Media Resources:
From: Robert O'Callahan <robert#ocallahan.org>
Date: Tue, 23 Jul 2013 16:30:00 +1200
To: "public-audio#w3.org" <public-audio#w3.org>
HTML media elements can play media resources from any origin. When an
element plays a media resource from an origin different from the page's
origin, we must prevent page script from being able to read the contents of
the media (e.g. extract video frames or audio samples). In particular we
should prevent ScriptProcessorNodes from getting access to the media's
audio samples. We should also information about samples leaking in other
ways (e.g. timing channel attacks). Currently the Web Audio spec says
nothing about this.
I think we should solve this by preventing any non-same-origin data from
entering Web Audio. That will minimize the attack surface and the impact on
Web Audio.
My proposal is to make MediaElementAudioSourceNode convert data coming from
a non-same origin stream to silence.
If this proposal makes it into spec it will be nearly impossible for a developer to even realize why his MediaElementSource is not working. As it stands right now, calling createMediaElementSource() on an <audio> element in Firefox 26 actually stops the <audio> controls from working at all and throws no errors.
What dangerous things can you do with the audio/video data from a remote origin? The general idea is that without applying the Same-Origin Policy to a MediaElementSource node, some malicious javascript could access media that only the user should have access to (session, vpn, local server, network drives) and send its contents—or some representation of it—to an attacker.
The HTML5 media elements don't have these restrictions by default. You can include remote media across all browsers by using the <audio>, <img>, or <video> elements. It's only when you want to manipulate or extract the data from these remote resources that the Same-Origin Policy comes into play.
[It's] for the same reason that you cannot dump image data cross-origin via <canvas>: media may contain sensitive information and therefore allowing rogue sites to dump and re-route content is a security issue. - #nmaier
createMediaElementSource() does not work properly in Safari 8.0.5 (and possibly earlier) but is fixed in Webkit Nightly as of 10600.5.17, r183978
I've got a page which uses Flash with animations (These are not crucial but additional).
Everything works fine, if I'm not using Opera with activated Turbo. Then the Flash Movie is shown as a big ugly arrow in a circle the size of the flash movie which is intended to act as a play button for the flash.
I'm using SWFobject, so I easily could turn of the animation if I knew if Opera's turbo mechanism is used, but how do I do this in JavaScript (or maybe CSS if this goes)
How to reproduce?
Surf this page with Opera (or any other page which uses flash)
http://www.adobe.com/software/flash/about/
Without Opera Turbo you see a flash animation and flash version information
With Opera Turbo you see two white arrows in gray circles
edit 1
I'm quite sure now, that there is not a pure JS solution and not a PHP solution. The best guess is a combined AS/JS solution.
Client side detection:
There is no way to access that through javascript. Client side detection for opera turbo is not possible currently, maybe it will be supported in the future but who knows?
Server side detection:
When opera turbo is enabled all requests from client are done to opera servers, the opera servers are going to access your application (do compressions) and forward the processed content to the final client (user's computer).
With that in mind, let's do some network sniffing and see where are your connection going:
~$ nslookup opera10beta-turbo.opera-mini.net
>Server: 189.40.226.80
>Address: 189.40.226.80#53
>Non-authoritative answer:
>opera10beta-turbo.opera-mini.net canonical name = global-turbo-1.opera-mini.net.
>Name: global-turbo-1.opera-mini.net
>Address: 141.0.11.252
~$ nslookup 64.255.180.252
>Server: 192.168.1.254
>Address: 192.168.1.254#53
>Non-authoritative answer:
>252.180.255.64.in-addr.arpa canonical name = 252.0-24.180.255.64.in-addr.arpa.
>252.0-24.180.255.64.in-addr.arpa name = global-turbo-1-lvs-usa.opera-mini.net.
As you can see the name and canonical name from opera servers can be used to detect if you application is being accessed through opera servers intermediation. I think server side coding could handle that (not sure what language are you using on your server).
It's good to remember that Opera Turbo will not intermediate your requests if you're accessing something in your local server.
Hope it helps.
You can try to check if the flash object is loaded with some javascript. This code works on my computer with Opera 11:
<html>
<head>
<script language=JavaScript>
function isFlashBlocked(){
var blocked;
try {
// Can test this on any flash object on the page
window.document.myFlash.SetVariable("dummy", "dummy");
// Flash not blocked
blocked = false;
}
catch(err) {
// Flash blocked
blocked = true;
}
return blocked;
}
function removeBlockedFlash() {
if (isFlashBlocked()) {
// Hide all flash objects
window.document.myFlash.setAttribute("style", "display: none");
// ...
// Display replacement content
window.document.myImage.setAttribute("style", "display: inline");
// ...
}
}
</script>
</head>
<body onload="removeBlockedFlash()">
<object type="application/x-shockwave-flash" data="HelloWorld.swf"
width="100" height="100" id="myFlash">
</object>
<img src="image.jpg" style="display: none" id="myImage" />
</body>
</html>
If you detect that flash is blocked, you hide every flash object and display what you want.
Edit: This code doesn't work with Firefox, you probably need to detect the browser before using this function.
I believe that the answer to the speed issue is that the Flash content is not downloaded initially. You have to manually click on the icon to download it. Same for animated GIFs. This is part of the strategy to boost the speed. (cf., this Opera Desktop Team post.)
Which is why you want to know how to check for Opera Turbo, and not just Opera. From my local tests, I cannot tell the difference using PHP's _SERVER["HTTP_USER_AGENT"] variable. I think this is similar to what Opera lists as the user agent string, as shown here and here.
It seems that, rather notifying the website of the browser condition, Opera silently manages the request results differently.