mediaElementjs: how to get instance of the player - javascript

I'm stuck with a little problem with MediaElement.js player.
To get the instance of the player, I do this (works with html5 compatible browser):
// Get player
this.playerId = $('div#shotlist-player video').attr('id');
this.player = window[this.playerId];
But it's not working as soon as it fallback in flash. In fact, it's not working because I'm not calling an instance of MediaElement itself. But I don't see how I can call it.
The player is created with
$('video').mediaelementplayer({....});
How can I get the mediaelement object?
------------EDIT----------------
Ok I finally found how to make it works:
// Get player
mePlayer = $('div#shotlist-player video.video-js')[0];
this.player = new MediaElementPlayer(mePlayer);
Now I can user mediaElement instance correctly.

This post is a lot of speculation, but may be correct. Docs are lacking (;
The answer by sidonaldson is perfectly acceptable if you wish to create a new MediaElement instance and get a handle on it. If there's one already present, it seems to try to reinitialize another instance on that element and freaks out.
I am pretty sure mediaelement.js augments the builtin HTML5 controls by providing a JavaScript API to manipulate Flash/Silverlight players via those elements. I may be wrong, but other advice I've seen on this issue in multiple places is to do something like:
$playButton.click(function() {
$('video, audio').each(function() {
$(this)[0].player.play();
});
});
To create a play button as an external DOM element which will fire off all players on the page. This indicates to me that the implementation is something like I've described.

Try:
var player = $('video').mediaelementplayer({
success: function (me) {
me.play();
}
});
// then you can use player.id to return the id
// or player.play();

Related

Trouble updating API object once instantiated in Javascript

I'm instantiating a new Vimeo object when clicked. This allows me to use the event target to grab the videoUrl depending on which element is clicked. Then the vimeo api automagically creates an iframe with the video embed. The problem is that once the Vimeo player is created, I can't destroy it and recreate it with another videoUrl. It stays stuck on the first element I clicked. If I refresh and click another element, it works with the new videoUrl, so it means that it works on any element I choose but only the first click. I'm guessing this is a JS issue that I'm not familiar with. I'm used to C++ where we can use pointers to address this kind of thing. I would appreciate any suggestions.
function openModal(e) {
var modal = document.getElementById('Modal');
var videoUrl = e.target.dataset.videoLink;
//JS Player Code
alert(e.target.dataset.videoLink);
var options = {
url: videoUrl,
width: 640,
loop: false
};
var player = new Vimeo.Player('Modal', options);
modal.style.display = "block";
//Doesn't seem to do anything
delete player;
}
Unlike C++, JavaScript has a garbage collector in which you don't have to manage your memory. The delete operator in JS is completely different than the one you have in C++. Instead of pointers, JS uses "references" which you can't destroy manually.
Now, I don't quite understand what you expect to happen when you do delete player. But I assume you want to remove the iframe (which doesn't really make any sense.)
But anyway, you have two choices. You either
Hide it with CSS via display: none
Replace the element with a new one.
By the way, the delete operator in JS is equivalent to the std::map::erase method in C++.

Howler js pause/resume trouble

I'm using the Howler js library to set a player in an app running through Electron. First everything seemed to work well, but after a few weeks using the app, a bug occurs repeatedly, but not constantly : the pause() function doesn't work. Here's some piece of code :
Initialization :
var is_paused = true;
var currentTrack = "track1";
var tracks = {"track1" : new Howl({urls: ['path/to/track1.mp3']}),
"track2" : new Howl({urls: ['path/to/track2.mp3']}),
"track3" : new Howl({urls: ['path/to/track3.mp3']})
};
Then I have a few buttons for play/resume, pause, stop, and play a specific track :
$('#playS').click(function(){
if (is_paused){
tracks[currentTrack].play();
is_paused = false;
}
});
$('#pauseS').click(function(){
tracks[currentTrack].pause();
is_paused = true;
});
$('.trackBtn').click(function(){
tracks[currentTrack].stop();
currentTrack = $(this).attr('id');
tracks[currentTrack].play();
is_paused = false;
});
The problem is that sometimes (generally after 40-45 min of a track playing), the pause() function just do nothing, which is really annoying cause I need to pause the track and play another 30 sec file and then resume the current track. I checked the console while the bug occurs, it says absolutely nothing. I have no idea where the bug comes from, there's not a lot of information about how works the library. I really need some help here, thank's in advance.
EDIT : one more thing, when pause() doesn't work, if I click play() the track plays from the begining, and I have control on this second instance of the track. It's like the first instance has reached end, but still playing.
Without knowing what version of Howler you're using, or what other code might be messing things up, there is one thing I think might help: You don't need to track the paused state. The "playing" method takes care of that. I've made it work using something like this:
// If it's paused, it's not playing, so...
paused = !myHowlInstance.playing();
Another thing I noticed is that you have currentTrack = $(this).attr('id'); in your (I think it's a) stop button. Unfortunately I don't know JQuery well enough to know if there's anything wrong with that (I'm more of a Dojo fan myself). But it looks like currentTrack may be set to some value not in your list (which would break tracks[currentTrack]). You might want to go into the console and type tracks["track1"], currentTrack etc. to see their values. You can even do tracks[currentTrack].play(); and see what happens. I wasn't sure if you knew you could do that (it was a huge help to me when I found out about it).
And as far as the "un-pausing" starting from the beginning, I'm currently struggling with it myself; at this time there's no clear way to do this (no resume(), pause(false) etc.), and I've seen a few more questions on the subject on Google and SO, so you're not alone. I've experimented with the seek method, but with no luck. I'll post a comment if/when I reach a breakthrough on that. :)
EDIT: I figured out the play-from-beginning thing. It does involve "seek", and also the whole "instance ID" concept (which I never really understood the importance of from the documentation).
Here's an example from a project I'm working on (also a game); it doesn't involve JQuery (sorry), but it should give you the gist of how to fix the problem.
var myBgMusic = new Howl(...);
var myMusicID = myBgMusic.play(); // The docs say play() returns an ID, and I'll be passing that to "seek" later.
var paused = false;
var saveSeek;
function TogglePause() {
if (paused) {
myBgMusic.play(myMusicID);
myBgMusic.seek(saveSeek, myMusicID);
} else {
myBgMusic.pause();
saveSeek = myBgMusic.seek(myMusicID);
}
};

Createjs pause timeline sound in Flash CC

Is there anyway to control sound file added to timeline layer
like to pause and resume the sound with timeline
Or is there anyway to detect what sound is being played in the browser with creatjs
Thanks
Have a look at the exported lib code. There is a frame script that will have a playSound() call.
The frame script probably looks something like this:
this.frame_12 = function() {
playSound("sound_id");
}
You can store off the result of this call, and control it.
this.frame_12 = function() {
// Store the result as part of the current object.
this.mySound = playSound("sound_id");
}
To control it, you need to know where it resides. If it is on your main timeline, it will be part of your exportRoot:
exportRoot.mySound.stop();
I would need to know more about your setup to help more than that.

Phonegap - Android 4.4 - html5 audio wrong length (javascript and media plugin)

I want to play a single audio file (mp3) and my only problem is media length.
It works just fine on Android 5.0.1, but on 4.4.2/4.4.4 it doesn't work!
With native implementation I get a value but it's incorrect and if I use the Media plugin API (from Phonegap) the media.duration is undefined and media.getDuration() returns -1.
I'm trying to get duration only after loadedmetadata event is fired, so this could not be the problem.
The native implementation is done through js with new Audio(), no DOM element involved.
The file is stored on sdcard, and src looks like file:///storage/sdcard/audio.mp3. Everything else regarding html5 audio api works, but duration.
Are there any solutions to fix this?
Thanks to #tawpie's answer I figured out a workaround for this issue I'm having.
That setInterval made me thing about my custom seekbar been updated (correctly) while the audio is playing and in calculating the width of it I was using audio duration value and from that results that the duration is working after media file play method is fired.
The problem is that loadedmetadata event doesn't return the correct duration value (in some browsers like android webView), but after audio played for at least 1s the duration is updated and you can use it.
So you can forget about loadedmetadata event and jump straight to canplay event and from there you can make something like this:
var myAudio = new Audio();
myAudio.src = 'file://mnt/sdcard/audio.mp3';
myAudio.load();
myAudio.correctDuration = null;
myAudio.addEventListener('canplay', function(){
myAudio.play();
myAudio.muted = true;
setTimeout(function(){
myAudio.pause();
myAudio.currentTime = 0;
myAudio.muted = false;
myAudio.correctDuration = myAudio.duration;
},1000);
});
...of course, you can use volume = 0.0/1.0 instead of mute.
Another method would be to create a helper function (in my case - a AngularJS service) which takes your src value and uses the code above and returns the correctDuration. This one is preferred if you have listeners to audio timeUpdate which changes the DOM.
The Media plugin works exactly the same way - if the audio haven't played for at least 1s you cannot use getDuration() method or duration property inside a interval/timeout wrapper to get the correct duration.
I think the video element behaves similarly. I'll test it these days.
Hope this workaround helps!
Try Media.node.duration. That works on windows... For what it's worth, as long as getDuration is called in an interval, I don't have any problems on Android 4.4. But I'm using just the media plugin new Media(src, onSuccess, onError, playbackStatus) and not the HTML5 player.
Hardcoded values. It's a pain, but you can do this if the files are local.
I ran into an issue where chrome was reporting different duration values than other browsers, and this is where we landed. I know it's not really a solution, but it works.
OR... you can use some external process to generate a json of duration times, and reference those values at runtime.
For the sake of reference:
audio.addEventListener('durationchange', function(e) {
console.log(e.target.duration); //FIRST 0, THEN REAL DURATION
});
worked for me.
Credit: this stackowerflow question

VideoJS - unable to destroy and initialize

On VideoJS website you state that support was moved to StackOverflow, so let's try it here. I've got the following code:
var player = _V_('the_id', {}, function(){
jQuery('.remove').on('click.destroyvideojs', function(){
player.destroy();
jQuery(this).unbind('click.destroyvideojs');
});
});
It initializes video at first and it destroys it.
But when I want to initialize it again using the same exact piece of code, it doesn't work. It doesn't initialize the script on the same element ID (when it was removed from DOM and added again with correct initialization call after it's been added). I'm wondering why this might be happening?
Another try today:
var the_id = 'my_id';
var player = _V_(the_id, {}, function(){
player.destroy();
_V_(the_id, {}, function(){
alert('reinit');
});
});
So, re-initialization of VideoJS simply doesn't work. Furthermore, it removed controls from the video now.
In case this helps anyone, it looks like it's dispose in Version 4:
var player = videojs('my-video');
player.dispose();
Having looked at the source for Video.js 5.0.0. #l:17236 You can just do the following:
if(videojs.getPlayers()[id]) {
delete videojs.getPlayers()[id];
}
It seems that player hasn't been defined when the callback executes.
Take a look at this js fiddle http://jsfiddle.net/gaboesquivel/BA8Pm/
destroy(); works for me. this how the function looks like
destroy: function () {
this.stopTrackingProgress();
this.stopTrackingCurrentTime();
_V_.players[this.id] = null;
delete _V_.players[this.id];
this.tech.destroy();
this.el.parentNode.removeChild(this.el)
}
check this solution too
http://help.videojs.com/discussions/problems/861-how-to-destroy-a-video-js-object#comment_13544514
I pulled some of My hare from My head, very hard to find response fore such questions...
So here is My solution, with JQuery... the solution was born from the question how to destroy uninitialised player objects, you guys save my day in the end, cos We can destroy only players that are shown, and even if I clean the HTML and reinitialise dynamically playerJs the flash fall back will not work for unshowed undestroyed media-player.
so here is the solution:
$.each(_V_.players, function (key, player) {
if (player.isReady) { player.destroy(); }
else { delete _V_.players[player.id]; }
});
a little messy but will do just fine.
cheers!
The api reference your looking for is .dispose(); however it does not remove settings from the dom. If you have third party plugins other items may litter your DOM after the dispose is run. To run dispose and clean up your dom use a code like this
dispose = function() {
if (settings.debug) {
console.info('place.videojs_element.dispose()');
} /*Target the Player Element*/
var player = videojs(settings.element.id + '_player'); /*Pause Video*/
player.pause(); /*Wait for third party scripts to stop listening!!! <-- Important*/
setTimeout(function() { /*Dispose of the player*/
player.dispose();
/*I have a new video element waiting to be placed ( this code is proprietary )*/
var epi = new EPI();
epi.place.videojs_element(settings, data); /*Wait time 600ms*/
}, 600); /*Destroy the old video element <--- Important */
$('#' + settings.element.id).empty();
}
See a working example in action: http://codepen.io/JaminQuimby/pen/yNaOwz/
The above will give you a clean DOM and completely remove the video player.

Categories