Youtube API event on a specified time - api

Is it possible through the YouTube API to fire an event when the video reaches a specified time? e.g. when the video reaches 20 sec. fire the event.
Thanks,
Mauro

not sure if you still need an answer to this (as I'm finding it 4 months later) but here's how I accomplished this with youtube's iframe embed api. It's ugly in that it requires a setInterval, but there really isn't any kind of "timeupdate" event in the YouTube API (at least not in the iframe API), so you have to kind of fake it by checking the video time every so often. It seems to run just fine.
Let's say you want to start up your player as shown here with YT.Player(), and you want to implement your own onProgress() function that is called whenever the video time changes:
In HTML:
<div id="myPlayer"></div>
In JS:
// first, load the YouTube Iframe API:
var tag = document.createElement('script');
tag.src = "//www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
// some variables (global here, but they don't have to be)
var player;
var videoId = 'SomeYoutubeIdHere';
var videotime = 0;
var timeupdater = null;
// load your player when the API becomes ready
function onYoutubeIframeAPIReady() {
player = new YT.Player('myPlayer', {
width: '640',
height: '390',
videoId: videoId,
events: {
'onReady': onPlayerReady
}
});
}
// when the player is ready, start checking the current time every 100 ms.
function onPlayerReady() {
function updateTime() {
var oldTime = videotime;
if(player && player.getCurrentTime) {
videotime = player.getCurrentTime();
}
if(videotime !== oldTime) {
onProgress(videotime);
}
}
timeupdater = setInterval(updateTime, 100);
}
// when the time changes, this will be called.
function onProgress(currentTime) {
if(currentTime > 20) {
console.log("the video reached 20 seconds!");
}
}
It's a little sloppy, requiring a few global variables, but you could easily refactor it into a closure and/or make the interval stop and start itself on play/pause by also including the onStateChange event when you initialize the player, and writing an onPlayerStateChange function that checks for play and pause. You'd just need to seperate the updateTime() function from onPlayerReady, and strategically call timeupdater = setInterval(updateTime, 100); and clearInterval(timeupdater); in the right event handlers. See here for more on using events with YouTube.

I think you may have a look at popcorn.js.
It's an interesting mozilla project and it seems to solve your problem.

Not sure if anyone agrees here but I might prefer to use setTimeout() over setInterval() as it avoids using event listeners, eg:
function checkTime(){
setTimeout(function(){
videotime = getVideoTime();
if(videotime !== requiredTime) {
checkTime();//Recursive call.
}else{
//run stuff you want to at a particular time.
//do not call checkTime() again.
}
},100);
}
Its a basic pseudocode but hopefully conveys the idea.

Related

Custom Soundcloud Widget (api) Player

I'm trying to create a custom player for some Soundcloud tracks. The idea is to hide the Iframe and create a few players to play different tracks. The loading and playing all works fine but I have two challenges.
How do I create a progressbar (SC.Widget.Events.PLAY_PROGRESS)
How do I create a download link?
A snippet from the way I'm coding this:
(function(){
var widgetIframe = document.getElementById('sc-widget'),
widget = SC.Widget(widgetIframe);
widget.bind(SC.Widget.Events.READY, function() {
$('#play').click(function(){
widget.play();
});
}); }());
To bad the OPEN API is closed..
If you are trying to stream tracks using a custom player, I recommend you do not use the widget at all. Rather, use the streaming SDK directly. There are methods there that can do everything you need to load, play, pause, seek, get the current time of the song and more.
To initialize the streaming player, you can do something like:
SC.initialize({
client_id: "<client id>"
});
SC.stream("/tracks/" + song_id).then(function (player) {
player.play();
}
To build the actual progress bar, you can do something inside your stream function like the following (this example uses JQuery but you don't need to):
player.on("time", function () {
var current_time = player.currentTime();
var current_duration = player.options.duration;
$(".scrubber .scrubber_fill").css("width", ((current_time / current_duration) * 100) + "%");
});

Ionic 3 infinite-scroll simulate in e2e test jasmine/protractor

If you go here: http://ionicframework.com/docs/api/components/infinite-scroll/InfiniteScroll/
Inspect the demo and click the last item on the list:
Then in the console type: $0.scrollIntoView()
Infinite Scroll is never triggered.
Is there a way to programmatically trigger infinite-scroll in protractor context?
The implementation of the scroll in your example rely on the speed/velocity of the scroll which I guess falls far from the expected range when scrollIntoView is called.
One workaround is to simulates a smooth scroll by emitting multiple scroll events over a reasonable time. The idea is to reproduce as close as possible the behavior of a real user.
Some browsers already provides the option via scrollIntoView (supported by Chrome 62) :
$0.scrollIntoView({behavior: "smooth", block: "end"});
Using the accepted answer, in my case, I used ion-infinite-scroll as the argument.
Complete test to check if more content is loaded in Ionic:
describe('Scroll', () => {
it('should load more when reached end', async () => {
let list = getList();
let currentCount = await list.count();
const refresher = element(by.tagName('ion-infinite-scroll')).getWebElement();
let count = 0;
while(true){
browser.executeScript(`arguments[0].scrollIntoView({behavior: "smooth", block: "end"});`, refresher);
browser.sleep(1000); // wait for data to be loaded from api
list = getList();
let newCount = await list.count();
expect(newCount).toBeGreaterThanOrEqual(currentCount)
expect(newCount).toBeLessThanOrEqual(currentCount * 2)
if(newCount === currentCount){
break;
}
currentCount = newCount;
count++;
}
expect(count).toBeGreaterThan(0);
})
});
function getList() {
return element(by.className(pageId + ' list')).all(by.tagName('ion-item'));
}

Trouble with Youtube iframe API

I currently have a blog that plays background music when you load the page using a youtube iframe:
<iframe id="background-music" width="0" height="0" src="https://www.youtube.com/embed/VOR8reYWvx8?rel=1&autoplay=1&enablejsapi=1" xframeborder="0" allowfullscreen></iframe>
I have imported the youtube iframe api manually as well:
<script src="http://url_to_script/iframe_api.js"></script>
I have other songs on my blog and I want to pause the background song whenever I play one of the other songs on there. I have the following code, per the instructions on https://developers.google.com/youtube/iframe_api_reference#Examples, but it doesn't work at all.
$(".tumblr_audio_player").contents().find('.play_button').click(function()
console.debug(YT);
player = new YT.player("background-music", {
events: {
'onReady': function() { console.log("player is ready") },
'onStateChange': function() { console.log("player has changed state"); }
}
});
player.stopVideo();
I am not sure what I am doing wrong. I don't know if onReady and onStateChange are required (I don't need them), but it doesn't work without the second object parameter so I'm not sure what I'm supposed to do.
Well, I figured out what was going on. The code is mostly correct, however, initializing the YT.Player object takes time which is exactly what the onReady callback is for.
It makes sure that the YT object is initialized before you do anything. If you put the pauseVideo in the onReady callback, it will work properly. So to answer my original question, onReady is absolutely necessary:
player = new YT.Player("background-music",
{ events: {
onReady: function() {
player.stopVideo();
}
}
});

Reset Video.js plugin to initial state

I'm using jquery ui tabs and video.js. I want to stop the video when I go to another tab and reset it when I come back to second tab.
As of VideoJS v4.6 you can do the following to reset the player:
player.pause().currentTime(0).trigger('loadstart');
That loadstart is the key which shows the poster image and rebinds the first play event.
u can use this for show poster or show bigplay button
$( '.backlink' ).click( function() {
// Player (this) is initialized and ready.
var myPlayer = _V_("video9");
myPlayer.currentTime(0); // 2 minutes into the video
myPlayer.pause();
myPlayer.posterImage.el.style.display = 'block';
myPlayer.bigPlayButton.show();
});
It's even easier.
let player = Video(el);
player.on('ended', () => {
player.initChildren();
});
First you need a reference to the video player.
http://videojs.com/docs/api/
var myPlayer = _V_("myVideoID");
Then you can use the API to start/stop/reset the video.
Stop:
myPlayer.pause();
Reset:
myPlayer.currentTime(0);
I'm not sure how the jquery tabs are set up, but you might be able to do:
$('.my-tab-class').click(function(){
myPlayer.pause().currentTime(0);
});
player.reset();
Life is simple.
Get the id of the video.just append _html5_api with the id since videojs appends these letters and then you could use pause and make currentTime equal to 0.
var videoStop = document.getElementById(videoId+"_html5_api");
videoStop.pause();
videoStop.currentTime= 0;
The solution I found was using the videojs api, invoke the reset function followed by initChildren for reconstruct the player structure, i'm using vesion 5.10.7.
videojs('sublime_video', {}, function () {
var videoPlayer = this;
videoPlayer.width(screen.width / 2);
videoPlayer.height(720);
videoPlayer.on("ended", function(){
videoPlayer.reset().initChildren();
});
});
I was looking for a way to reintialize the VideoJS plugin then I found this :-
var player = videojs('my-player');
player.on('ended', function() {
this.dispose();
});
Just dispose off the video and init again.
Source:- https://docs.videojs.com/tutorial-player-workflows.html#dispose

youtube API - setShuffle don't work

I added this script in my site to reproduce video playlist.
<script type="text/javascript" src="swfobject.js"></script>
<div id="ytapiplayer">
You need Flash player 8+ and JavaScript enabled to view this video.
</div>
<script type="text/javascript">
var params = { allowScriptAccess: 'always',
allowFullScreen: 'true' };
var atts = { id: 'myytplayer' };
swfobject.embedSWF("https://www.youtube.com/v/videoseries?listType=playlist&list=PLBA9E733B5C8314DE&autoplay=1&modestbranding=1&enablejsapi=1&playerapiid=ytplayer&version=3", "ytapiplayer", "640", "360", "8", null, null, params, atts);
function onYouTubePlayerReady(myytplayer) {
ytSwfPlayer = document.getElementById( 'myytplayer' );
ytSwfPlayer.setShuffle(1);
}
</script>
the setShuffle function don't work!!!
You can suggest me a solution?
This appears to be a bug in the player. I've reported this bug to the team. In the future you can report bugs at https://code.google.com/p/gdata-issues/issues/entry?template=YouTube%20(Defect%20Report)
As a work around you could use the JS api to shuffle it yourself. When a video ends you can call playVideoAt and pass a random number.
The problem is that if you've loaded a playlist queue in the Youtube player, the next track will automatically start at the end of the current playing one.
So you should bind track ended event (which is event.data = 0) and then make the youtube player make two things:
stop playing
play a new track with a random index by calling playVideoAt method.
A simple solution to avoid repeating the same track more times is to store the played idx in a list. Then, you should have a function, like shuffle that generates a random integer between 0 and the queue length:
function getRandomId() {
var random_id = 0
while(played_idx.indexOf(random_id) != -1) {
random_id = Math.floor(Math.random * playlist.length)
}
return random_id
}
Then, simply call playVideoAt(random_id).
I've noticed that setShuffle does work if you launch the command a little later. Something like this:
function onPlayerReady(event) {
event.target.mute();
setTimeout( function() {
event.target.setShuffle(true);
event.target.setLoop(true);
}, 2000);
}
If you launch it directly, it will definitely not work (I have noticed, to my frustration).