HTML5 Video: Force abort of buffering

VideoHtml

Video Problem Overview


How does one force an abort event on an HTML5 video? I have an overlay, where, when I close it, the video should pause playing and then stop buffering. However, my internet connection continues to go nuts. Oh, I'm using Chrome 7.0.5 on Mac OS X 10.6.

I've tried a couple of things -- none of them have worked:

(For those unfamiliar with XUI, x$ is like the jQuery wrapping function)

First, dispatching an abort HTML Event:

var videoEl = x$('#video_el')[0];
videoEl.pause();
var evObj = document.createEvent('HTMLEvents');
evObj.initEvent('abort', false, false);
videoEl.dispatchEvent(evObj);

Next, changing the src and then forcing a load:

var videoEl = x$('#video_el')[0];
videoEl.pause();
videoEl.src = "";
videoEl.load(); //tried with and without this step

EDIT: My video element looks something like this:

<video id="video_el" src="<video_url>" preload="none" controls="controls" />

Again, none of these work. Anyone ran into this problem before? Any suggestions?

In summary, I am trying to force an HTML5 video element to stop buffering.

Thanks!

Video Solutions


Solution 1 - Video

Ok, so for the last few day's I've really been struggling with this issue.
Here is my analysis and solution:

In short the problem I tried to solve:
I noticed that the HTML5 player does not stop downloading when the player is paused (at all, not even after a reasonable amount of time). Working with a 24/7 audio stream and developing a mobile website I realized that this is far from optimal for my visitors considering the high data usage if they leave the site open - although I do think I would make some telco's very happy by "overlooking" this issue...
Just to clarify, I don't really care about files with a fixed length. Downloading the complete file is most of the time a functionality required for viewing online resources (think slow connection) so not something I tried to prevent.

Analysis:
The HTML5 audio element does not have a stop() function, nor does it have an option where you can set the amount of data that it is allowed to buffer, or a way of saying you want the element to stop buffering - Don't confuse this with the 'preload' function, this only applies to the element before the play button is clicked.
I have no clue why this is and why this functionality is not available. If anyone can explain to me why these crucial functions are not implemented in a standard that should make web development for mobile phones better and more standardized I would love to know.

Solution:
The only working solution I found to implement a (sort of) stop function in your audio element is as follows:

  1. Pause the current player - you can hook the pause event on the player via audio.addEventListener('pause', yourFunction);
  2. Set the source to empty - audio.src = "";
  3. Load the src - audio.load();
  4. Remove the whole audio element
  5. Insert a new HTML5 audio element without the source defined
  6. Set the source (the source that was there in the first place) - audio.src = "old source url
  7. Rehook the pause event - audio.addEventListener('pause', current-function);

Completely injecting a new HTML5 audio player is necessary for iOS. Simply resetting the src and then loading it causes the player to 'autoplay' in my case...

For the lazy people (includes jQuery):

var audio = $("audio").get(0);
audio.pause(0);
var tmp = audio.src;
audio.src = "";
audio.load();
$("audio").remove();

$("#audio-player").html("<audio controls preload='none'></audio>");<br>
audio = $("audio").get(0);
audio.src = tmp;
audio.addEventListener('pause', current-function);

Pressing pause will cause your visitor to lose there current location in the audio/video file and it will start again. I have no solution for this issue. Then again, if you are dealing with a live stream this solution should be fine.

Hope this helps.

Solution 2 - Video

With preload="none", This is how I force aborted the buffering after pausing the video, and then resumed playback at the paused location using jQuery.

<video id="video_el" src="<video_url>" preload="none" controls="controls" />    

<script>
jQuery(function() {

  var video = jQuery('video').get(0);

  video.addEventListener('pause',function(){
     var tmp_src = video.src;
     var playtime = video.currentTime;
     video.src = '';
     video.load();
     video.src = tmp_src;
     video.currentTime = playtime;
  });

});
</script>

Solution 3 - Video

The key step seems to be to not set src to a blank value before calling load(). I've had success doing it like this:

var wasPlaying = !audioPlayer.paused;
audioPlayer.currentTime = 0.0; // Optional -- can be left out for pause
audioPlayer.pause();

if (wasPlaying) { // This prevents the browser from trying to load the entire source
    audioPlayer.load();
}

In both Chrome and Firefox on Win10, this fires an abort event. In my specific case this was required to close the sockets that would otherwise remain open indefinitely, which led to hitting the six connections per server limit with multiple players being used on the same page.

Solution 4 - Video

Actually you can do the same thing by setting the src attribute as a php/aspx file with some params to read the file content and retrieve the data as the equivalent type(e.g., Content-Type: video/mp4). BUT it does't work in IE 11 (what a surprise :D), then you'll need to do the trick above just for this gorgeous browser.

Use this...

<video id="v1" preload="none">
  <source src="video.php?id=24" type="video/mp4">
</video>

Instead of this...

<video id="v2" preload="none">
  <source src="video-24.mp4" type="video/mp4">
</video>

As a drawback you won't be able to determine the full length of the video, but to solve this problem, that's not soo big, you could store this value in your database or just make another little trick.

I've tested using Chrome 32, Firefox 26, Opera 18 and IE 11 the following script

setInterval(function() {
    var r = [];
    
    try {
        r.push(v1.buffered.end(0));
    } catch(e) {
        r.push('nahh');
    };
    
    try {
        r.push(v2.buffered.end(0));
    } catch(e) {
        r.push('second nahh');
    };
    
    console.log(r.join(', '));
}, 500);

In my localhosts tests...

Firefox 26 After you had pressed play, it ALWAYS buffered the full file.

IE 11 (considering src="video-24.mp4", cuz the other don't work) After you had pressed play, it ALWAYS buffered the file chunk by chunk even if it was paused and completly ignores the preload="none" attribute.

Chrome 32 Works perfectly (same for Opera 18).

Solution 5 - Video

You could also change the src to a mp3 that contains one second of silence. Than call the play function with the new src. As the new mp3 is loaded the buffering of the stream stops.

var audio = document.getElementById("audioradio");
audio.src = "/sound/pause.mp3";
audio.play();

<audio style="display: none;" id="audioradio" src="/sound/pause.mp3" preload="none"></audio>

Testet in Firefox only!

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBrad SwerdfegerView Question on Stackoverflow
Solution 1 - VideoRubenView Answer on Stackoverflow
Solution 2 - VideoEric LeroyView Answer on Stackoverflow
Solution 3 - VideoDinfinityView Answer on Stackoverflow
Solution 4 - Videouser2434658View Answer on Stackoverflow
Solution 5 - VideoIchEbenView Answer on Stackoverflow