1

I'm developing a reference player application using node.js, javascript & HTML5. I have a player that successfully loads a single video & produces the diagnostic data from that. What I'm aiming for is to produce a player that loads a video & begins buffering the next video 10 seconds before the current one ends. I attempted duplicating the video tag which is able to produce another video object but just displays it alongside the existing on. Can anyone provide some advice on how to achieve this please. Thank you in advance.

HTML5 :

<div id="player" class="video"> <video width=1280 height=720 autoplay data-dashjs-player controls id="video" src="{{{ src }}}"></video> // main video object that takes the src variable </div>
<script type="text/javascript">
// media events
var server_log, server_glob, videoArray = [{
    "MediaState": []
}];
// joins the media events into a 'glob' that can be sent every few seconds
server_glob = function(t, v) {
    console.log(t, v);
    videoArray[0]["MediaState"][t] = v;
}
server_log = function() {
    var out = "";
    // Serialize videoArray
    for (var i = 0; i < Object.values(videoArray[0]["MediaState"]).length; i++) {
        var key = Object.keys(videoArray[0]["MediaState"])[i];
        var value = JSON.stringify(videoArray[0]["MediaState"][key]);
        out += key + "=" + value + "&";
    }
    // send a xhr/ajax POST request with the serialized media events
    var xhttp = new XMLHttpRequest();
    xhttp.open("POST", "/tel", true);
    xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); // this is my favourite format of POST request, looks alot like JSON
    xhttp.send(out);
}
</script>
m87
  • 4,445
  • 3
  • 16
  • 31
T.Doe
  • 1,969
  • 8
  • 27
  • 46
  • you could either load the new video.src when the HTML Video `ended` event fires, but that won't pre-buffer. an alternative would be to get the duration of the current video and at length-10s load a new video element that is hidden, but has preload set to auto and when the ended fires on the current element swap them (hide one, show the other) – Offbeatmammal Mar 21 '17 at 15:08
  • @Offbeatmammal that sounds great! do you have a coded example to illustrate this? – T.Doe Mar 21 '17 at 15:09
  • which option? both are pretty simple... I'll be able to knock something together later today. Probably won't be 100% seamless unless you do something like load whole video via XHR but that opens up a new can of worms! – Offbeatmammal Mar 21 '17 at 15:36
  • Right now, just queuing up multiple video objects would be fine with me. I tried implementing this method (http://stackoverflow.com/questions/31201252/playing-two-videos-in-queue) but it doesn't work at all. Anything you could piece together will be greatly appreciated. – T.Doe Mar 21 '17 at 15:39
  • see suggested answer which just steps through the array of videos. if the gap is too long let me know and I'll play with preloading/swapping a second element (adds a bunch of complexities!). Does assume the `dashjs` player is wrapping a standard ` – Offbeatmammal Mar 21 '17 at 18:27

1 Answers1

2

This will cycle through a number of videos in order (you can load the array any way you like, hard-coded or via an ajax call for instance). At the end of a video it will move to the next and continue to loop around the array.

It's all native JS so should be applicable to your node.js/dashjs setup as long as you know the ID of the <video> element.

my usual preference is to dump the handling logic in <head> and keep as little in the body as possible, but should work in other configurations....

I wasn't sure from the question how you are catching the media events you want to report back to the server, I am assuming an addEventListenter on the <video> object, so that should be able to follow the same format as used for the catch-all error handler...

<head>
....
<script>
var videos = new Array("BigBuck.m4v","Video.mp4","BigBuck.m4v","Video2.mp4");
var currentVideo = 0;

function nextVideo() {
    // get the element
    videoPlayer = document.getElementById("video")
    // remove the event listener, if there is one
    videoPlayer.removeEventListener('ended',nextVideo,false);

    // update the source with the currentVideo from the videos array
    videoPlayer.src = videos[currentVideo];
    // play the video
    videoPlayer.play()

    // increment the currentVideo, looping at the end of the array
    currentVideo = (currentVideo + 1) % videos.length

    // add an event listener so when the video ends it will call the nextVideo function again
    videoPlayer.addEventListener('ended', nextVideo,false);
}

function ooops() {
    console.log("Error: " + document.getElementById("video").error.code)
}
</script>
</head>

<body> 

<div id="player" class="video">
    <video id="video" width="588" height="318" controls autobuffer muted>
    Your browser does not support the video tag.
    </video>    <!--end video container -->
</div>  

<script>
// add error handler for the video element, just to catch any other issues
document.getElementById("video").addEventListener('error', ooops,false);

// initialize and play the first video
nextVideo();

</script>
Offbeatmammal
  • 7,970
  • 2
  • 33
  • 52
  • this looks great! And logically seems sound but unfortunately, it isn't working. I copied your code as is, replacing "Video.mp4" with the path name of a video I have put on my desktop but unfortunately, nothing happens. Another video doesn't play sequentially. Is there something I'm doing incorrectly? – T.Doe Mar 22 '17 at 10:44
  • do you get any errors in the browsers console log or network tools? can you substitute the videos in the array with a known good source (eg http://html5demos.com/assets/dizzy.mp4)? are you opening the webpage as http:// (in which case can it see your desktop) or file:// ? – Offbeatmammal Mar 22 '17 at 14:27
  • :) phew! hoped it wasn't going to be one of those "works for me!" problems. – Offbeatmammal Mar 22 '17 at 16:32