I am making a chrome extension that needs to know if a YouTube video is being played, paused, had a duration change, and if it is on an ad. I figured out how to do everything except knowing if it is on an advertisement. I found this post which was of some help, however, if I were to put this in my content script it would only run once and I want it to constantly check if there is an ad (since ads can happen in the middle of a video.
I am fairly new to Javascript, but I do understand the concepts of listeners and I would use a listener in this case, however, I do not know how to do that in this case because the div does not emit an event, it either exists or is null. Are there any other ways of doing that?
+1 to looking at YouTube video API events. Here's that page [0].
I haven't tried this myself, but I would start with the onStateChange event, because I suspect that an ad is a separate video from the desired video content itself. So there could be two "video cued" or "5" values fired. But, again, I haven't tried it myself. Good luck!
[0] https://developers.google.com/youtube/iframe_api_reference#Events
You can also use setInterval to detect ads continuously. This is a way without having to looking for API.
// According to the post you provided
function detectAds() {
return !!document.querySelector("div.ad-showing");
}
let timer;
function listen() {
timer = setInterval(function () {
if (detectAds()) { /* do something */ }
}, 1000); // runs every second
}
function unlisten() {
if (timer) clearInterval(timer);
}
Related
I'm working on a music webapp that plays a random sequence of notes, but I ran into this issue: whenever it was the case that I was going to press play for the first time after the page loaded, the sequence would "choke" before getting on track. I thought maybe that was because the resources are not yet loaded when I press play for the very first time. I guess I was right, did some research, found this preload = auto thing, which seemed to solve this problem. At least, if you refresh or visit the page for the first time and press play immediately, it works just fine. However, if you don't do anything for a while, like 2/3 minutes, the same thing happens. There's a delayed start, as if it's loading the file, and then it awkwardly speeds up like it's trying to catch up with the setInterval timer. I wrote this very simplified version of the code just to illustrate:
<button>Play</button>
<audio src="source1.mp3"></audio>
<audio src="source2.mp3"></audio>
<audio src="source3.mp3"></audio>
<script>
let notes = []
document.querySelectorAll("audio").forEach(function(note){
notes.push(note)
})
function play(){
let random_index = Math.floor(Math.random() * 3),
note = notes[random_index]
note.play()
setInterval(function(){
note.pause()
note.currentTime = 0
play()
}, 500)
}
let button = document.querySelector("button")
button.addEventListener("click", function(){
play()
})
</script>
So my question is how do I solve this? Is there anyway to tell the function to hold until it can actually play the first file? Maybe a DOM event that fires when the resource is buffered and ready? I feel like I can't relly let the timer begin until I have a way to check that, otherwise it will go crazy as usual. Any ideas will be greatly appreciated!
The load event is called after the page is fully loaded:
window.addEventListener("load", function(){
// Your code
});
The DOMContentLoaded event is called after the DOM is loaded but before css and img.
document.addEventListener("DOMContentLoaded", function(){
// Your code
});
I need a sound on a mouse over event, I have this way but its problem comes from a delay between the mouse over and the sound playing, which is due (I supposed) the embed sound deal on the code. I would like to know if there is a better way using js/jquery). But not the new html5 audio tag which I don't want to implement in this particular case.
An ajax call loads the file, then I attached to the mouseOver a function named playSound()
function playSound()
{
$setSound = document.getElementById("soundWrapper").innerHTML="<embed id='sound' src='href' type=audio/mpeg hidden=false autostart=true volume=12>";
}
Then to the mouseOut event a function named stopSound()
function stopSound()
{
$stopSound = document.getElementById("soundWrapper").innerHTML="";
}
Nothing fancy but it does work. The problem as a said is the delay to playing the sound. Is there a way to play/stop the already embedded sound, not just embed a new one every time, or something alike?.
Thanks for your time and help.
Greetings.
If you have your AJAX load an audio tag (http://www.w3schools.com/tags/tag_audio.asp) into the desired place, you can play it using the .play() method in JS. Then it becomes really easy
$(YOURMOUSEOVERELEMENT).on('mouseover', function(){$('#sound').play()});
Then if you want to stop the audio when the mouse leaves:
$(YOURMOUSEOVERELEMENT).on('mouseout', function(){$('#sound').stop()});
I want to seek a flowplayer at the page load.
I have tried:
$(document).ready(function() {
$f(0).seek(5);
});
and
$(document).ready(function() {
while(!$f(0).isLoaded()) {
$f(0).seek(5);
}
});
and
$(document).ready(function() {
$f(0).onLoad(function() {
$f(0).seek(5);
});
});
and this one gave result, for a while
$f(0).onLoad(function() {
$f(0).seek(5);
});
The last one moved the pointer to 5 seconds, and back to the start right after.
I want it to stand there.
Any suggestions?
official answer:
http://flowplayer.org/forum/3/101287#post-101528
looks like I was downvoted for just putting a link, and that is understandable as flowplayer has changed their forum URLS!
https://web.archive.org/web/20120629142246/http://flowplayer.org/forum/3/101287
Here is the OP
Found this old question on stack overflow...
http://stackoverflow.com/questions/5034858/seek-in-flowplayer-on-page-load
Wondering what the official answer is? How do you seek on load?
and the response
The onLoad event (of the player) is to early an event to seek a clip.
So you cannot seek onLoad.
You can seek once a clip is loaded and in play or pause state.
Move the seek in the onStart event of the clip - always assuming that you deploy via a streaming server.
I think in some cases it would help to pause the player, jump to the prefered position and the start again. When you have Flowplayer configured to auto buffer it will start playing and pause at the first frame. That could maybe explain the behavior you are seeing (seek to 5, jump to 0 and jump to 5 again. But I think your fix using the load event pretty well solves it, I've used a similar trick to wait for duration to become available.
Solved it!
Used
$f(0).onLoad(function() {
$f(0).seek(5);
setTimeout('$f(0).seek(5)',1000);
}
Then it seeked to 5, jumped back to zero for some reason, and seeked to 5 again.
I'm wondering how to stop the MediaElement.js player at the end of the video. I wondered how to stop the mediaelement.js player at the end of a video. I was hoping to hold on the last frame and not rewind to show the first frame as it does now.
Is it possible to change this behaviour?
I wrote a fix for this problem and John merged in version 2.10.2.
There is now an option "autoRewind" that you can set to false to prevent the player from going back to the beginning.
The eventlistener is not added and there is no more need to remove it.
$('video').mediaelementplayer({
autoRewind: false
});
I believe that the default behavior of the <video> element is to go back to the beginning so you'd just need to override this by listening for the ended event.
var player = $('#myvideo').mediaelementplayer();
player.media.addEventListener('ended', function(e) {
player.media.setCurrentTime(player.media.duration);
}, false);
Hope that helps!
Probably the best solution is not to be afraid and remove the "rewind-to-start-on-video-end" handler from mediaelement source.
If you go into the source code for mediaelement and search for "ended", you'll eventually see, that rewinding after reaching end of the video is actually done deliberately by mediaelement.
If you want to remove that functionality feel free to just remove that handler for "ended" event from mediaelement source. That solves all the problems, including flickering between last and first frame, mentioned in some other answers to this question.
The code in John Dyer's answer didn't really work for me either for some reason. I was however able to get this version working...
var videoPlayer = new MediaElementPlayer('#homepage-player', {
loop: false,
features:[],
enablePluginDebug: false,
plugins: ['flash','silverlight'],
pluginPath: '/js/mediaelement/',
flashName: 'flashmediaelement.swf',
silverlightName: 'silverlightmediaelement.xap',
success: function (mediaElement, domObject) {
// add event listener
mediaElement.addEventListener('ended', function(e) {
mediaElement.pause();
mediaElement.setCurrentTime(mediaElement.duration);
}, false);
},
error: function () {
}
});
videoPlayer.play();
The only problem I'm having - which is very frustrating, is it is flickering between the LAST and FIRST frames in Chrome. Otherwise, it works as expected in Firefox and IE...
This problem i faced when playing audio files
The problem is in the play, when you pause your player the file will stop but before resuming you have to decrease the current time of the player by any value in your case you may decrease it by a frame maybe
after setting your source ,loading your file and pausing, then
myplayer.player.play();
var currentTime = myplayer.player.getCurrentTime();
myplayer.player.setCurrentTime(currentTime-0.1);
myplayer.player.setCurrentRail();
[EDIT: Sorry to those who already answered -- in my sleep-deprived state, I forgot that this particular situation is a YouTube movie, not the JW FLV player. I can see that there is more extensive documentation on interacting with YouTube movies, so I will pursue that, but any more information is also welcome]
I am using embedded YouTube videos in a collection of divs that are being rotated by using the jQuery cycle plugin (http://malsup.com/jquery/cycle/).
I would like the cycle to stop when I click on one of the movies to start it playing, but I can't figure out how to attach a jQuery event handler to the player object.
Here's what my current code looks like (you can't directly select an object tag with jQuery, so I select the parent div and then get the object element as the first child):
$("div.feature-player").children(":first").click(function(event) {
$('#features').cycle('stop');
});
But that doesn't do the trick. I'm not a Flash author, so I'm not really familiar with ActionScript, and I've never set up an interaction between JavaScript and a Flash movie before.
The YouTube player API is pretty straight-forward. You just have to listen to the onStateChange event and control the cycle plugin depending on the state:
Here's a working demo: http://jsbin.com/izolo (Editable via http://jsbin.com/izolo/edit)
And the pertinent code:
function handlePlayerStateChange (state) {
switch (state) {
case 1:
case 3:
// Video has begun playing/buffering
videoContainer.cycle('pause');
break;
case 2:
case 0:
// Video has been paused/ended
videoContainer.cycle('resume');
break;
}
}
function onYouTubePlayerReady(id){
var player = $('#' + id)[0];
if (player.addEventListener) {
player.addEventListener('onStateChange', 'handlePlayerStateChange');
}
else {
player.attachEvent('onStateChange', 'handlePlayerStateChange');
}
}
Flash movies are pretty much black boxes as far as javascript is concerned. If the SWF you're using wasn't written to interact with javascript then you're probably out of luck.
You'll either need to figure out what javascript methods the movie you're using exposes (hopefully it has documentation), find another one that does provide javascript interaction, or write your own SWF to handle it.
What you're looking for is the flash ExternalInterface class, which is used for communication from flash to javascript and from javascript to flash.
If you're embedding the player using swfobject you're going to want to use swfobject.getObjectById to get a reference to the movie. Read the docs to see why you need to do this.
Also you'll need to set {wmode:"transparent"} for the player in order for it to bubble up click events to JavaScript.