I use Soundmanager2's mp3 player button to play mp3s links on my website. I used the following modifcation in-order to preload the next mp3 during playing the current mp3.
play: function() {
sm.load('basicMP3Sound'+(1*this._data.oLink.title)+1);
//mycode end
pl.removeClass(this._data.oLink,this._data.className);
this._data.className = pl.css.sPlaying;
pl.addClass(this._data.oLink,this._data.className);
},
In the above example you may notce that the title tag in this._data.oLink.title which I added it to the mp3 link to handle files order in simple way, for example:
/002001.mp3
However, I noticed that the next mp3 link does not preloaded during playing the current mp3. This is because the next mp3 does not being played contiousely or start played after finish playing its previous mp3. In other word, it takes some time or delay to be downloaded.
Is there something wrong in my code? or what are your suggestions?
Notice a life demo of this mp3 layer is found in this link
Edit: Approach to work with the SoundManager inline button player
In your setup params in mp3-player-button.js under config, where playNext : true|false is found (line 39), update it to look like this:
...
this.config = {
// configuration options
playNext: true, // stop after one sound, or play through list until end
autoPlay: false, // start playing the first sound right away
preloadNext : true // preload next sound when previous sound starts to play
};
...
Then, further down under the this.events object (line 96), modify the play function to preload the next sound:
...
this.events = {
// handlers for sound events as they're started/stopped/played
play: function() {
pl.removeClass(this._data.oLink,this._data.className);
this._data.className = pl.css.sPlaying;
pl.addClass(this._data.oLink,this._data.className);
if (pl.config.preloadNext) {
var nextLink = (pl.indexByURL[this._data.oLink.id]+1);
if (nextLink<pl.links.length) {
sm.load(nextLink)
}
}
},
...
In summary, when a song starts, we check to see if there's a next song; if there is, we pull its id from the array of sounds that was created when we instantiated SoundManager. In this case, SoundManager is sm, so we simply pass the id of our next song to the sm.load() function.
Here is a live demo: http://plnkr.co/edit/mpBkfDIrLNduMAWJjRfN.
Try this approach:
Using the onplay and onfinish events of the createSound method, you can chain a series files which delegate each other.
Explicitly telling firstSound: "when you start to play, preload the next sound, and when you finish playing, play that next sound"
JavaScript
var firstSound = soundManager.createSound({
id: 'firstSound',
url: 'path/to/your/firstSound.mp3'
});
var secondSound = soundManager.createSound({
id: 'secondSound',
url: 'path/to/your/secondSound.mp3'
});
// Kickoff first sound
firstSound.load();
// Define the chain of events
firstSound.play({
onplay: function () {
// When `firstSound` starts, preload `secondSound`
secondSound.load();
},
onfinish: function () {
// Repeat, with next sound
secondSound.play({...
})
}
});
Related
I have a website that plays an icecast stream with jPlayer.
I want the play button to always start the stream from the live position (like a radio) instead of picking the stream back up from the last position. Attempted behavior:
play plays the stream live > pause suspends / discards the stream / optionally stops downloading it > play plays the stream from live position / reloads the stream.
There is a way to monitor the current media position with $.jPlayer.event.timeupdate as mentioned in comment on this post, and use that to resume playing from the end of the stream.
Alternatively, there must be a way to discard the stream when pausing and then reloading it when hitting play again. I think it is what is happening on this jPlayer demo. But I don't know how to do that part:
The error event is used with a check for the URL_NOT_SET error type to jPlayer("setMedia",stream) back to the live-stream again and jPlayer("play") it.
I am new to javascript and can't make it work. I can't find another post of someone trying to do that. I tried with the "playhead" at 100 which does not start the stream at all.
Here is the code I am using:
<script type="text/javascript">
//<![CDATA[
$(document).ready(function(){
$("#jquery_jplayer_1").jPlayer({
ready: function () {
$(this).jPlayer("setMedia", {
mp3: "http://realbadradio.ddns.net:21000/mpd.mp3"
})
},
});
});
//]]>
</script>
Here the repo to my website for full code.
I finally found the solution thanks to this answer on a different question related to achieving autoplay in jPlayer.
SOLUTION
$(document).ready(function(){
const stream = {
// stream address
mp3: 'http://realbadradio.ddns.net:21000/mpd.mp3'
};
ready = false;
$("#jquery_jplayer_1").jPlayer({
ready: function () {
ready = true;
$(this).jPlayer("setMedia", stream);
},
pause: function() {
$(this).jPlayer("clearMedia");
},
error: function(event) {
if(ready && event.jPlayer.error.type === $.jPlayer.error.URL_NOT_SET) {
// Setup the media stream again and play it.
$(this).jPlayer("setMedia", stream).jPlayer("play");
}
},
keyEnabled: true,
preload: 'none',
});
});
I'm using plyr plugin to play a video on my website.
I'm trying to restart the player (vimeo) when the video ends but I'm not having much luck. I'm even trying to console log a message and that's not even working. Can anyone see where I'm going wrong?
JSfiddle attached here.
if ($('.main-hero__youtube__video').length) {
console.log("Video player init");
// Define the controls
var plyr_options = {
autoplay: true,
clickToPlay: true,
showPosterOnEnd: true,
controls: ['mute','progress','play']
};
// Create the plyr instances - this defines players[0] as our primary player.
var players = plyr.setup(plyr_options);
players[0].on('ended', function(event) {
console.log("test");
});
}
You were close, you just needed to call the restart() method (or play() if you're looking for an infinite loop) on your player instance:
players[0].on('ended', function(event) {
players[0].restart();
// players[0].play(); // infinite loop
});
https://jsfiddle.net/yunxyfbh/
I have a video module that uses a splash screen and on click, reveals a full screen video for screen sizes 667 +. I would like to have this reverse it's animation after ending the video so it returns to the splash screen. I'm not really sure where to even start or whether this is possible. Any help is appreciated!
$(function(){
var $parent = $('.video-hero'),
$video = $parent.find('iframe'),
$playButton = $(".play"),
$itemsToFadeOut = $(".vid-cap, .ghost"),
f = $video[0],
url = $video.attr('src').split('?')[0],
activeVideoClass = "video-started";
// setup fitVids
$parent.fitVids();
// handle play click
$playButton.click(function(e){
e.preventDefault();
// grab height of video
var videoHeight = $video.height();
// add class to hero when video is triggered
$parent.addClass(activeVideoClass);
// fade out the play button
$(this).fadeOut("fast");
// fade out poster image, overlay, and heading
$itemsToFadeOut.fadeOut();
// toggle accessibility features
$video.attr({
"aria-hidden" : "false",
"tabindex" : "0"
});
// set focus to video for accessibility control
$video.focus();
// set height of hero based on height of video
$parent.css("max-height",videoHeight).height(videoHeight);
// send play command to Vimeo api
runCommand('play');
});
// send play to vimeo api
var runCommand = function(cmd){
var data = {method : cmd};
f.contentWindow.postMessage(JSON.stringify(data), url);
}
// handle resize
$(window).resize(function(){
var videoHeight = $video.height();
if($(".video-started").size() === 1){
$parent.height(videoHeight);
}
});
});
Remember to resize my JSFiddle so you're able to see the animation I am talking about.
Figured it out everyone! I'll explain each chunk of code step by step for anyone's future reference.
I was able to accomplish what I needed to do without the froogaloop cdn, and just using fitvids.js here is a working fiddle of my solutions.
I listed all of my JS below in sections, but for the answer to my question of "reversing my function after video finishes" you will only need to pay attention to my Event Handlers, Connection to the API, and Player State Functions. Once I was able to make the connection and read that the video was ended, I used addClass(); and removeClass(); coupled with CSS Transitions to handle swapping between my play and ready(post finish) states.
I tried to document and explain as much as I could so hopefully this can help someone in the future!
Naming my Vars
Not much to mention here, this is just the preliminary, the main thing to pay attention to is var url it's the only way I could write it to allow me to use my listeners with the Vimeo api.
var parent = $('.video-hero'),
f = $('iframe'),
$playButton = $(".play"),
$itemsToFadeOut = $(".vid-cap, .ghost, .play"),
$video = f[0],
url = f.attr('src').split('?')[0],
activeVideoClass = "video-started", //Class for when video is playing
standardClass = "standard"; //Class for when video is finished/before play
Event Listeners / Handlers
My listeners just wait to receive a message from the api/player of whether the video is ready, paused, finished or playing.
listeners
// Listen for messages from the player
if (window.addEventListener){
window.addEventListener('message', onMessageReceived, false);
}
else {
window.attachEvent('onmessage', onMessageReceived, false);
}
My handlers well... handle when my functions are fired. My functions are located below, this just lets me choose which state (case) I have being sent from the API and how to react to it.
handlers
// Handle messages received from the player
function onMessageReceived(e) {
var data = JSON.parse(e.data);
switch (data.event) {
//Ready case is before play / after finish
case 'ready':
onReady();
break;
case 'pause':
onPause();
break;
case 'finish':
onFinish();
break;
}
}
Connecting to the Vimeo API
This section communicates hand in hand with my html play button and vimeo's api/player, allowing me to run, pause and stop the video
// send play to vimeo api
var runCommand = function(cmd){
var data = {method : cmd};
f[0].contentWindow.postMessage(JSON.stringify(data), url);
}
// Helper function for sending a message to the player
function post(action, value) {
var data = { method: action };
if (value) {
data.value = value;
}
f[0].contentWindow.postMessage(JSON.stringify(data), url);
}
Player State Functions
What will happen based on which state or case the player is in
function onReady() {
post('addEventListener', 'finish');
}
function onPause() {
console.log('paused');
}
function onFinish() {
// add class to hero when video is triggered
parent.removeClass(activeVideoClass);
parent.addClass(standardClass);
// fade out the play button
$(this).fadeIn("slow");
// fade out poster image, overlay, and heading
$itemsToFadeOut.fadeIn();
}
To detect the end of the video, and run JS code, you might need to make use of the Froogaloop library:
https://developer.vimeo.com/player/js-api#universal-with-froogaloop
You can then do something like:
var player = $f(iframe[0]);
player.addEvent('ready', function() {
player.addEvent('finish', function() {
// Animation...
});
});
The different events are here:
https://developer.vimeo.com/player/js-api#events
I do this on a site I built recently in order to close the modal window on video end / finish:
http://billy.fm/
Feel free to examine the JS code there (unminified version):
http://billy.fm/wp-content/themes/billy/js/main.js
Wish I had more time to help you, but this should set you off on the right track.
I'm looking for a simple way to check if SoundManager2 is currently playing a sound. I was hoping for a function like "SoundManager.isSoundPlaying" but I don't see this functionality.
In SoundManager 2 there's a dynamic propierty called "playState" wich returns these values:
Numeric value indicating the current playing state of the sound.
0 = stopped/uninitialised
1 = playing or buffering sound (play has been called, waiting for data etc.)
Note that a 1 may not always guarantee that sound is being heard, given buffering and autoPlay status.
So you can do something like:
var myAudio = soundManager.createSound({
id: 'myAudioId',
url: "/audiofile/url.mp3",
autoPlay: true
});
if (myAudio.playState === 1) {
// audio playing (or buffering)
}
More info in the documentation page of SoundManager2
The main problem of "playState" is that it returns 1 even if the sound is under "pause" status.
A solution could be to check if the duration is not null, because once the sound is loaded the duration has always a value, then also check if the sound has been paused, because the duration value is kept even after you pause the sound.
A solution can be:
// assuming s is the soundmanager object
// playing status
if (s.duration&&!s.paused) {
}
else {
}
I don't think soundmanager has such a variable..
I suggest using a global variable "isPlaying" default it to false, and adding "isPlaying = !isPlaying" in your play/pause click event.
It actually has a way of saying if it's paused. Which is essentially the same thing.
Just do
if(!_audioInstance.paused){
// is playing
}
YouTube's iFrame embed JS player API allows you to add callbacks to certain events. I want to add a callback for when a related video at the end of a video is selected.
To be more specific, when viewing a video in an embed, at the end it displays related videos within the embed. I want to run some code when one of those is selected. How can this be accomplished? I see that there is an onStateChange but none of the states are related to related videos. Do I need to add an onStateChange for YT.PlayerState.PLAYING and then compare the playing video to the original video to see if they're different somehow?
That seems like a reasonable solution to me.
The only point worth mentioning (which you've noted) is that you will be not able to tell if the change in the video is due to the user clicking on a related video, but if you're not interacting with the player dynamically, comparing the previous VideoID should suffice.
Just a heads up, if you're interested in a jQuery plugin that simplifies some of the callback/event handling work check out: https://github.com/nirvanatikku/jQuery-TubePlayer-Plugin
I ended up doing it basically the way I described. Here's the code I used:
started = false;
var onYouTubeIframeAPIReady = function(id) {
var player = new YT.Player('player', {
videoId: id,
events: {
'onStateChange': function (event) {
if (event.data == 1) { // The video started playing
started = true;
}
if (started && event.data == -1) {
// Video had already started playing before and is now in
// "unstarted" state so it must be a new video.
var video_url = event.target.i.videoUrl;
var video_id = video_url.replace('http://www.youtube.com/watch?v=', '').replace('&feature=player_embedded', '');
window.location = '#/view/' + video_id;
}
}
}
});
}
So basically, when a video starts playing, you set a "started" variable to true. Then, if/when the video enters the "unstarted" state, if "started" is true, then you know that it's a new video that just started playing. In that case, grab its video ID from the event.target object and do whatever you want with it.
My full commit is here if anyone wants to see the context and you can see it in action on http://toogl.es.