MEDIA_ERR_DECODE on HTML5 video in iOS UIWebView after many plays
After a discussion with Apple Support, the problem has been fixed. The problem has to do with the hardware H264 decoder. Basically, I was never removing the videos from the hardware decoder buffer by never releasing the video resources (which I thought javascript would do itself).
So I was setting the source like this:
$(vid).src = "some source file";
$(vid).play();
... some other stuff happens ...
$(vid).remove();
Doing it this way never removed the video from the decoder buffer, which meant that eventually it not be able to decode any more videos.
To fix this, this is how you must remove the video from the DOM:
$(vid).src = "some source file";
$(vid).play();
... some other stuff happens ...
$(vid).remove();
$(vid).src = "";
$(vid).load();
Now I realize that this doesn't make a ton of sense because after .remove()
is called, I would have assumed that the control has been removed from the DOM and any garbage collection would do the rest automatically. However, it doesn't work like that. I hope this helps other people.
Video fails on iOS after multiple page loads
I found a solution that worked here: MEDIA_ERR_DECODE on HTML5 video in iOS UIWebView after many plays
The hardware decoder buffer didn't remove the videos after the page was unloaded, you have to do it manually.
Ionic solution:
ionViewWillUnload() {
// Clear the videos from the decoder buffer.
// Buffer fills up on iOS when multiple videos are loaded
const elements = document.getElementsByTagName("video")
for (let i = 0; i < elements.length; i++) {
elements[i].src = ""
elements[i].load()
}
}
HTML5 video MEDIA_ERR_DECODE occurs randomly
Definitions for MEDIA_ERR_DECODE
HTML5 spec for for media error codes
An error of some description occurred while decoding the media resource, after the resource was established to be usable.
Mozilla MediaError documentation
Despite having previously been determined to be usable, an error occurred while trying to decode the media resource, resulting in an error.
Firefox error message (as in this support ticket)
The video playback was aborted due to a corruption problem or because the video used features your browser did not support.
Common reasons for firing
The video is encrypted, but you failed to decrypt it. This can be due to various reasons:
1) Encrypting a video with multiple DRM schemes (rather than just one) can cause decryption to fail on some browsers;
2) You neglected to decrypt the video before it started playing (perhaps it's accidentally set to auto-play before you've completed the license request);
3) There are insufficient resources to decode the video because several video buffers (even if they're not encrypted videos) have been used up already.
Your browser doesn't support the particular media format (eg. DASH). This may be remediable with a plugin, depending on the media type.
You have set the wrong MIME type on your
<source>
element; note that certain browsers prefer different MIME types to be declared in order to decode certain video formats.Too many video buffers have been used up without being cleared.
Diagnosis in your case
As the error fires fairly indeterminately, it seems like a resources issue rather than any of the other possibilities. You have six audio and video elements playing one-after-another, so you should clear each one out each time they have delivered their media. You should also not load all six side-by-side.
var video = document.getElementById('myVideo');
var nextVideo = document.getElementById('nextVideo');
video.addEventListener('ended', (event)=>{
video.src = ""; // or the src attribute of the active <source> element.
video.load();
// If you aren't going to re-use this video element, you should also
// remove all eventListeners from it and then remove it from the DOM.
nextVideo.preload = "auto"; // I'm assuming the src has already been set.
nextVideo.autoplay = true;
// Second video should start playing now due to autoplay. If not, call load() again.
});
video.preload = "auto";
nextVideo.preload = "metadata";
video.src = "video.mp4";
nextVideo.src = "nextVideo.mp4";
video.autoplay = true;
nextVideo.load(); // I believe load() might not be necessary for preload = "metadata".
video.load(); // I believe load() is necessary for preload = "auto".
// First video should start playing now due to autoplay.
It's a similar case to this answer related to iOS.
Too many https requsets when web Rqeusting just a single MP4 Video
I think this is due to the browser loading the video over time versus all at one time. This is typically done for performance reasons and it doesn't seem like chrome likes people working around it. Here is a link to another post about the same thing.
React Video re-rendering issue in iOS
The solution was deleting video before unmount
import React, {Component} from "react";
import PropTypes from "prop-types";
import LoadingPoster from "assets/images/loading_video_poster.jpg";
export default class Video extends Component {
static propTypes = {
videoUrl: PropTypes.string.isRequired
};
componentWillUnmount() {
this.refs.video.src = '';
this.refs.video.load();
}
render = () => {
return (
<video
key={this.props.videoUrl}
autoPlay
muted
loop
playsInline
preload="auto"
className="workout_page__exercise__video"
poster={LoadingPoster}
src={this.props.videoUrl}
ref={'video'}
>
Videos are not supported
</video>
);
}
}
Related Topics
How to Detect If My Device Is an iPhone x in Swift 4
How to Open Application Using Url
iOS 8 [Uiapplication Sharedapplication].Scheduledlocalnotifications Empty
Sprite Kit Collision Detection
Swift: Iboutlets Are Nil in Custom Cell
Perform "Use Photo" Button on Custom Image Picker Overlay
In What Format Is This Date String
Insert a Floating Action Button on Uitableview in Swift
Remove Duplicate Structs in Array Based on Struct Property in Swift
How to Programmatically Delete My Own iOS App
iOS - Running Background Task for Update User Location Using Swift
Dynamic Cell Height with Sdwebimage
iOS Google Maps Sdk Gmsmarker Positioning
Can't Build an App for Distribution After Joining Existing Enterprise Developer Program
Uiactivityviewcontroller => Launchservices: Invalidationhandler Called
How to Request Photo Gallery Permissions in iOS a Second Time