Detect the when the youtube video starts playing - javascript

How Can using the youtube api and javascript detect the time it takes for the first image of the video to play after clicking the play. Therefore I can measure the time it takes and the amount it prebuffers before it can play

There are event handlers in the API itself as documented here :
https://developers.google.com/youtube/js_api_reference?hl=en#Events
Notably : onYouTubePlayerReady(playerid)
Therefore you could try something like :
function onYouTubePlayerReady(playerId) {
player = document.getElementById("playerID");
player.addEventListener("onStateChange", "callMeWhenStateChange");
}
The callMeWhenStateChange is then fired on the state change, so you want to listen for state 1 I believe.. Again refer to documentation.
function callMeWhenStateChange(state) {
if(state == 1)
console.log("Current state is playing : " + state);
}
Hope that answers your question.

Related

How to listen volume changes of youtube iframe?

Here I found an example how I can listen Play\Pause button of youtube iframe.
player.addEventListener('onStateChange', function(e) {
console.log('State is:', e.data);
});
Now I need to listen the volume changes.
In the youtube documentation and here I found a method player.getVolume(), but I have no idea how this method can be implemented if I want to be informed about volume changes from iframe side, instead of ask iframe from my side.
On YouTube Player Demo page such functionality exists (when I change the volume of a player, I see appropriate changes in the row Volume, (0-100) [current level: **]), but neither in the doc nor in internet I can not find how to implement it.
I also tried to use the above mentioned code with onApiChange event (it is not clear for me what this event actually does), like:
player.addEventListener('onApiChange', function(e) {
console.log('onApiChange is:', e.data);
});
but console shows nothing new.
player.getOptions(); shows Promise {<resolved>: Array(0)}.
Could anyone show an example?
See this question.
You can listen to postMessage events emitted by the IFrame and react only to the volume change ones:
// Instantiate the Player.
function onYouTubeIframeAPIReady() {
var player = new YT.Player("player", {
height: "390",
width: "640",
videoId: "dQw4w9WgXcQ"
});
// This is the source "window" that will emit the events.
var iframeWindow = player.getIframe().contentWindow;
// Listen to events triggered by postMessage.
window.addEventListener("message", function(event) {
// Check that the event was sent from the YouTube IFrame.
if (event.source === iframeWindow) {
var data = JSON.parse(event.data);
// The "infoDelivery" event is used by YT to transmit any
// kind of information change in the player,
// such as the current time or a volume change.
if (
data.event === "infoDelivery" &&
data.info &&
data.info.volume
) {
console.log(data.info.volume); // there's also data.info.muted (a boolean)
}
}
});
}
See it live.
Note that this relies on a private API that may change at anytime without previous notice.
I inspected the code of YouTube Player Demo page and found that the html line which shows the current YouTube volume (<span id="volume">**</span>) constantly blinking (~ 2 times per 1 sec), so I can assume this demo page uses something like this:
// YouTube returns Promise, but we need actual data
self = this
setInterval(function () { self.player.getVolume().then(data => { self.volumeLv = data }) }, 250)
Possibly not the best method, but it seems there is no other option (I also tried to listen changes in the appropriate style of the volume bar, but no luck due to the cross-origin problem).
So, this let us 'listen' volume changes of youtube.
Just in case, if someone wants to set youtube volume, you need to use [this.]player.setVolume(volume_from_0_to_100)

How to identify volume change in youtube player

I am using 'angualr-youtube-embed' directive to embed youtube player in my angular web app. In that I have to identify play and pause and volume change events. To listen play and pause events I am using the below given code.
$scope.$on('youtube.player.playing', function ($event, player) {
// to do functions when the video is playing.
});
$scope.$on('youtube.player.paused', function ($event, player) {
// to do functions when the video is paused.
});
Now my requirement is, I want to do some works while changing volume in youtube player, I need to identify that volume change event. But I have no idea about how to listen the volume change in youtube player. How can I solve this issue?
Thanks in advance.
Just in case if anyone has the same question, here is my full answer.
For today the code looks like:
setInterval(this.getChangedVolume, 250)
getChangedVolume () {
let currentYoutubeVolume = this.player.getVolume()
// Do some things, for example (will show Promise):
// console.log(currentYoutubeVolume)
// YouTube returns Promise, but we need actual data, so:
// Promise.resolve(currentYoutubeVolume).then(data => { this.volumeLv = data })
}
player.getVolume():Number
Returns the player's current volume, an integer between 0 and 100. Note that getVolume() will return the volume even if the player is muted.
For more Detail check this: YouTube Player Controls

Throttling HTML5 Video currentTime

I have an app that tracks video views and integrates it with other marketing activities. In doing so, I needed to keep track of how long a person watches a html5 video and post it back to my app (via an API). I'm using videojs player, but really this is just a wrapper around the HTML5's api for this attribute. This is in an app with various videos can be loaded based on what page they are watching, so I needed a solution that tracked regardless of video length.
The problem I had, as a video plays the API reports back every ~300MS and I didn't want to hit my API that often. So I needed a solution to keep track of last time I posted. After digging around, I couldn't find an answer, so in case someone else with a similar need, my solution to this problem is below.
We've decided that I wanted to post my video viewing results every 5 seconds, but since we have no guarantee that the currentTime will report back at exactly 5 seconds, so we just need to round to closest whole integer value.
On my video wrapper div, I've added a data attribute called data-last-time-push. I post the rounded time every time I push and check to see if we have exceed the interval before we post again.
HTML
<div id="video-wrapper" data-time-last-push="0">
Javascript
Bind the videojs container to the timeupdate property.
var vid = videojs("video-container", {}, function() {
this.on('timeupdate', videoTracker);
});
function for posting ajax...
var videoTracker = function() {
var player = this;
var last_push, wrapper, current;
wrapper = $('#video-wrapper');
last_push = wrapper.attr("data-time-last-push");
current = Math.round(player.currentTime());
//you could make the 5 here to be a variable or your own interval...
if (current%5 === 0) {
if (current > last_push) {
//do your AJAX post here...
wrapper.attr("data-time-last-push", current);
console.log('currentTime = ' + player.currentTime());
console.log(' duration: ' + player.duration());
}
}
};
Note, I tried to do a jsfiddle to show it working, but ended up running into HTTPS videos because the sample videos don't work through secure connections.

Detecting when variable equals another variable with jQuery ($.when()?)

Currently trying to detect when a YouTube video in a playlist ends so I can play the next one ( Adding event handler to loop through dynamically created playlist (YouTube API) ). I'm now trying to figure out when one variable is equal to another, so I can navigate to the next video in the playlist.
Here is the code to detect when a video has ended and save the video ID to a div (stopID):
function stopCycle(event) {
if (event.data == YT.PlayerState.ENDED) {
var url = event.target.getVideoUrl();
var match = url.match(/[?&]v=([^&]+)/);
var videoId = match[1];
$('#stopID').html(videoId);
}
}
And here is my attempt at detecting (and testing with an alert) when the video ID of the video clicked equals the video ID of the in stopCycle (i.e. when the video ends):
$('#Playlist').on('click', '.playlistYT', function(){
$('#subHistory').click();
videoID = $(this).attr("src").slice(27,38);
$('#infoID').val(videoID);
player.loadVideoById(videoID );
var nextVideo = $(this).parent().next().find('.playlistYT');
$.when($('#stopID').html() == videoID).then(function(){
alert("asd");
});
Currently, I get the alert immediately, i.e. before the stopID div even has a video ID in it. Where am I going wrong with $.when function? Should I be sticking to an if/else statement?
$.when takes in a promise argument. Just use an if conditional to check equality.

Play after seeking currentTime

I'm trying to control html5 video with javascript. What I want is that when the user clicks on a button, the video will jump to another frame and keep playing from there. With my current code the playback always stops after the seek.
function jumpToTime(){
var video = $("video")[0];
video.currentTime = 160;
document.getElementbyId("videoclip").play(); //not working
};
//the following code is probably not really related to the question:
var endtimeoffset = 2000;
video.addEventListener("timeupdate", function() {
if (video.currentTime >= endtimeoffset) {
video.pause();
}
}, false);
I ran into a similar problem, and found a solution by pausing the video, then setting the currentTime, then playing the video. To update your code:
function jumpToTime(){
var video = $("video")[0];
video.pause();
video.currentTime = 160;
video.play();
};
Some things I would try:
in the jumpToTime() function, you have two different references to supposedly the same video (one obtained through jQuery and the other by getElementById()). Are you sure these reference the same video? To be safe, I would just call play() on the 'video' reference that you set the currentTime on.
This is probably a copy and paste issue since the console would complain if this was in the actual code, but you did mispell getElementById() (Need to capitalize the B).
For debugging purposes, I would comment out the 'timeupdate' event code, to make sure this isn't the issue and that this code isn't pausing the video after you update the timehead or call play. It probably isn't, since you are setting the current time to be much less than the offset you are comparing it with. It would, however, be an easy test to eliminate this as a possible cause of the issue.
function jumpToTime(){
document.getElementById("videoclip").currentTime = 160;
document.getElementById("videoclip").play(); //not working
};
getElementbyId --> getElementById -- b --> B
get direct object by id...

Categories