HTML5 Video loadeddata event does not work in IOS Safari - javascript

I am trying to trigger an event once a video has loaded the first frame. The code I have used works in desktop browsers that I have tested in but it does not work in mobile safari on IOS. Is there something about the code that is not supported on mobile safari or is there another solution to achieve what I want?
function loadvideo (vidsource){
var vid = document.createElement('video');
vid.src = vidsource;
alert("Video about to load"); //This works fine in mobile safari
vid.addEventListener('loadeddata', function() {
alert("Video Loaded!"); //This does not display in mobile safari
//Will do something else here
}, false);
}

On iOS, it looks like the video doesn't get loaded unless the user hits play, or if the autoplay attribute has been added (which doesn't actually appear to autoplay it).
The following should work for you:
var vid = document.createElement('video');
if (/iPad|iPhone|iPod/.test(navigator.userAgent))
vid.autoplay = true;
vid.addEventListener('loadeddata', function() {[...]}, false);
vid.src = videosource;
Alternatively, you can listen to the progress event instead of loadeddata, which seems to work fine on iOS Safari.

Add preload="metadata" to video tag and then listen to loadedmetadata event. It works in IOS Safari as well

try not to use addEventListener is this case, use older on style, AND set src AFTER you setup an event listener:
...
vid.onloadeddata = function () {
alert("Video Loaded!");
// do something
}
vid.src = vidsource;
...
If an EventListener is added to an EventTarget while it is processing an event, it will not be triggered by the current actions but may be triggered during a later stage of event flow, such as the bubbling phase. - To learn more - https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener

Related

HTML5 video seeking to mid-video on 'ended' on Safari

I'm using a <video> for a background hero video. It starts at 0:00. When it reaches the end of the 0:11 clip, it pops back to :02 and repeats from there. I've accomplished it with:
document.getElementById('bgvid').addEventListener('ended',repeatVid,false);
function repeatVid(e) {
var mediaElement = document.getElementById('bgvid');
mediaElement.currentTime = 2;
mediaElement.play();
}
I'm only concerned with the desktop experience, since it swaps to a fallback image on tablet/mobile. This works with Chrome, Firefox, and even IE. Safari, however, repeats back from 0:00 instead of :02.
Putting the whole function on a button onclick instead of an addeventListener works. Reassigning currentTime doesn't appear to be the problem. I've tried putting the whole thing inside video.oncanplaythrough = function () {. I've tried changing the .addEventListener('ended') to $('video').on('ended',function(){ or video.onended = function () {.
It seems like .play() always sends you back to 0:00, except I can get it to work on('click'), so there's something up. Thanks for your help!
The play() function in Safari seems to reset the currentTime to zero.
If you play() the video and set the currentTime directly after that, it works like expected:
document.getElementById('bgvid').addEventListener('ended',repeatVid,false);
function repeatVid(e) {
var mediaElement = document.getElementById('bgvid');
mediaElement.play();
mediaElement.currentTime = 2;
}

Video play() doesn't work in Safari

On my site arielledubois.com, I cannot get my homepage video to play in Safari only. Here is the JS code that I have set in place:
setTimeout(function(){
document.getElementById("bgvid").play();
}, 3900);
I've read that Apple blocks autoplay so you have to click to activate the video; but does anyone know a workaround for this?
I think you'd better use 'canplaythrough' event.
var video = document.getElementById("bgvid");
video.oncanplaythrough = function() {
video.play();
};
video.src = "your_video_sourse";

Correct way to play <audio> + <video> from Javascript

I'm getting different results i Firefox and Chrome when using <audio> and <video> with preload="none" and then trying to play from Javascript.
Let's say i was using preload="auto" or preload="metadata" :
audio.src = "filename";
audio.play();
That seems to work fine in both Firefox and Chrome but i want to use preload="none" and then Chrome dossent play.
So i'm trying this code with preload="none" :
audio.src = url;
audio.load();
audio.addEventListener('canplay', function(e) {
audio.play(); // For some reason this dossent work in Firefox
}, false);
audio.play(); // Added this so Firefox would play
I don't know if that's the correct way to do it.
I'm using :
Firefox 20.0.1
Chrome 25.0.1364.172 m
I made a demo : http://netkoder.dk/test/test0217.html
Edit :
In the 2nd audio player (on the demo page) it seems that when using preload="none" you have to use load().
But is it correct to just use play() right after load() or is the correct way to use an event to wait for the file to load before playing it ?
In the 3rd audio player it seems Firefox 20.0.1 dossent support the canplay event correctly when used with addEventListener() because it dossent trigger after load(), it triggers after play() and also triggers when scrubbing though the sound which dossent seem to be the way the canplay should work.
Using .oncanplay does work.
So the following code seems to work :
function afspil2(url) {
afspiller2.src = url;
afspiller2.load(); // use load() when <audio> has preload="none"
afspiller2.play();
}
function afspil3(url) {
afspiller3.src = url;
afspiller3.load(); // use load() when <audio> has preload="none"
//afspiller3.addEventListener('canplay', function() { // For some reason this dossent work correctly in Firefox 20.0.1, its triggers after load() and when scrubbing
// afspiller3.play();
//}, false);
afspiller3.oncanplay = afspiller3.play(); // Works in Firefox 20.0.1
}
I updated the demo to include the changes : http://netkoder.dk/test/test0217.html
My way of adding addEventListener inside the afspil3() function dossent seem good because the first time the function is called the code inside addEventListener is called 1 time. The second time the function is called the code inside addEventListener is called 2 time and then 3 times and so on.
It's because your audio tags are missing the required src attribute, or <source> tags. When I added them in your demo, all 3 players immediately began working in both Chrome and FF.
Also, I recently discovered that src cannot be an empty string and subsequently changed with JS. If there's a reason you can't set the src in the HTML, your best alternative, IMO, is to create the audio elements with Javascript:
var audio = new Audio();
audio.src = url;
audio.controls = true;
audio.preload = false;
// and so on
Edit: Ok. It seems that in Chrome, when the HTML is preload="none" it is necessary to call load() before playing when the src is changed. Your second audio doesn't preload, so your function needs to be this:
function afspil2(url) {
afspiller2.src = url;
afspiller2.load(); // add load call
afspiller2.play();
}
Then, it seems that in Firefox, it is necessary to set preload="auto"; when attaching an event to the canplay event, like in the 3rd function.
function afspil3(url) {
afspiller3.src = url;
afspiller3.preload = "auto";
afspiller3.load();
afspiller3.addEventListener('canplay', function(e) {
this.play(); // For some reason this dossent work in Firefox
}, false);
}
That just seems very strange, but I tested it multiple times, and each time it would play if preload="auto" is called, but would not play if it isn't called. Note that it wasn't necessary for the 2nd player, which was also preload="none" in the HTML tag.
Finally, Chrome has some odd behaviors if there are multiple <audio> elements on the page. For all three players, reloading the page and clicking "the big electron" link would play correctly.
Reloading and then clicking "Yoda" on the 2nd or 3rd player won't do anything, but it WILL play for the first player. But, if the top player is played first by any means - play button or either link - then the other two "Yoda" links will suddenly work.
Also, if you click a 2nd or 3rd "Yoda" link first after reload, and then click the top player, the previously clicked "Yoda" (that didn't previously play) will begin to play on its own after the top player stops.
Suffice it to say they have some bugs to work out.
The correct way in my opinion would mean using an existing solution, like http://mediaelementjs.com/
If your really interested in the details on the best way to play audio and video with js then look at the source:
https://github.com/johndyer/mediaelement/tree/master/src/js
https://github.com/johndyer/mediaelement/blob/master/src/js/me-mediaelements.js

HTML5 Audio events not triggering on Chrome

I'm trying to have a load progress bar in my game, and I have a function assigned to the onloadeddata attribute on my audio, but it is not triggering in Chrome. It works in other browsers. I also tried many other events such as oncanplay, oncanplaythrough, onloadedmetadata, etc. None of them trigger.
I think it might have to do with the caching. Tried looking around and there was some reports of this from 2-3 years ago but nothing recent.
Is there any other way I could detect if the audio is loaded, or make these events work?
EDIT: Here's a quick example: http://jsfiddle.net/3vxCu/1/
Works in Opera and Firefox, but not in Chrome. It should give an alert when sound if finished loading.
It seems that the onloadeddata property does not work for some reason. But attaching an event handler through addEventListener (or via jQuery) works: http://jsfiddle.net/3vxCu/4/
bgSound = new Audio();
bgSound.src = "http://www.ehsankia.com/hawkthorne/audio/level.ogg";
bgSound.preload = "auto";
// Standard browsers (not IE before version 9):
// bgSound.addEventListener("loadeddata", testFunction, false);
// jQuery:
$(bgSound).on("loadeddata", testFunction);
function testFunction () {
alert("Data loaded");
}
If the attached jsfiddle is how you have implemented your code then I think I know what is wrong.
Your jsfiddle shows:
bgSound = document.createElement('audio');
bgSound.src = "http://www.ehsankia.com/hawkthorne/audio/level.ogg";
bgSound.onloadeddata = testFunction;
function testFunction(){
alert("Data loaded");
}
It should be like this:
bgSound = document.createElement('audio');
bgSound.onloadeddata = testFunction; // Event listener is attached _before_ loading the resource
bgSound.src = "http://www.ehsankia.com/hawkthorne/audio/level.ogg";
function testFunction(){
alert("Data loaded");
}
Basically, you are attaching the event listener after the src is specified. Specifying the source should be the last thing you do since it sets everything in motion. Chrome is probably already past the point of calling listeners for that event by the time it is attached in your code.

Getting Current YouTube Video Time

I am writing a Browser Plugin and need to find a way to get the current time a YouTube Video playing on YouTube using JavaScript. I have been playing around in the Chrome JavaScript Console and haven't had any luck.
It appears that the chrome API only works with embedded video players not a video that is playing on on youtube.com. One option I looked into is in the share section of a video their is an input box for the "start at:" time that contains the current time of the video. I have tried using .value and .text on this input box and they both return undefined? Does anyone have any ideas?
ytplayer = document.getElementById("movie_player");
ytplayer.getCurrentTime();
See the api
Update: if it didn't work, also try player.playerInfo.currentTime (codepen live example)
Depends on what you want
player.getCurrentTime():Number
Returns the elapsed time in seconds since the video started playing.
player.getDuration():Number
Returns the duration in seconds of the currently playing video. Note
that getDuration() will return 0 until the video's metadata is loaded,
which normally happens just after the video starts playing.
http://code.google.com/apis/youtube/js_api_reference.html
Finally I found how to make it work on iOS (and Android too).
Actually, the whole youtube js api was broken for me if run on mobile browser.
Problem solved by creating player using new YT.Player as described in YouTube IFrame API.
Please note: only creating <iframe> from <div> placeholder works for mobile browsers at the time. If you try to use existing <iframe> in new YT.Player call, as mentioned in IFrame API, this will not work.
After player created, it's possible to use player.getCurrentTime() or player.getDuration() with player instance created.
Note: I had no luck calling this methods on player obtained with
player = document.getElementById(...) (from #JosephMarikle answer).
Only created player instance worked in mobile browsers.
Useful links:
YouTube IFrame API
YouTube JavaScript API
YouTube Player Demo
You can use Html5 Video API on youtube.com
var htmlVideoPlayer = document.getElementsByTagName('video')[0];
htmlVideoPlayer.currentTime
Note: It's not gonna work on Youtube Iframe API because Iframes are isolated. You cannot access the context of a Youtube IFrame .
In 2020, this works:
player.playerInfo.currentTime
full code:
see it live on codepen
Just FYI, There is a new iframe API for the YouTube player:
https://developers.google.com/youtube/iframe_api_reference
document.querySelector('video').currentTime
Stop at specific time youtube video and show notification box in GWD
<script>
var yid = document.getElementById("gwd-youtube_1");
var idBox = document.getElementById("box1");
pausing_function = function(event) {
var aa = setInterval(function() {
if (yid.getCurrentTime() > 8.0 && yid.getCurrentTime() < 8.1) {
yid.pause(yid);
idBox.style.opacity = 1;
console.log(yid.getCurrentTime() + "playing")
clearInterval(aa);
yid.removeEventListener("playing", pausing_function);
}
}, 100)
}
yid.addEventListener("playing", pausing_function);
var pausing_function_1 = function() {
if (yid.getCurrentTime() > 8.1) {
console.log(yid.getCurrentTime() + "pause")
// remove the event listener after you paused the playback
yid.removeEventListener("playing", pausing_function);
}
};
</script>
play video and hide notification
<script type="text/javascript" gwd-events="handlers">
window.gwd = window.gwd || {};
gwd.pauseVideo = function(event) {
var idBox = document.getElementById("box1");
idBox.style.opacity = 0;
};
</script>
<script type="text/javascript" gwd-events="registration">
// Support code for event handling in Google Web Designer
// This script block is auto-generated. Please do not edit!
gwd.actions.events.registerEventHandlers = function(event) {
gwd.actions.events.addHandler('gwd-youtube_1', 'playing', gwd.pauseVideo, false);
};
gwd.actions.events.deregisterEventHandlers = function(event) {
gwd.actions.events.removeHandler('gwd-youtube_1', 'playing', gwd.pauseVideo, false);
};
document.addEventListener("DOMContentLoaded", gwd.actions.events.registerEventHandlers);
document.addEventListener("unload", gwd.actions.events.deregisterEventHandlers);
</script>

Categories

Resources