Media_Err_Decode on HTML5 Video in iOS UIwebview After Many Plays

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



Leave a reply



Submit