Changing source in videos-js eating memory until leak - javascript

i'm using video-js media player with flash fallback to dynamically play and change mp4-videos (h.264 - only source available) on a site i'm working on.
My problem is, every time i'm changing the video/source, the browser eats more and more memory until it is out of memory and crashes.
the problem occurs on every browser, flash player hardware acceleration enabled and disabled.
Player is initialized like this:
_V_.options.flash.swf = "../Scripts/ThirdParty/video-js.swf";
_V_.options.flash.iFrameMode = true; //false didn't help
_V_.players = {};
_V_("main_video", { "techOrder": ["flash", "html5"] }).ready(function () {
$.b4dvideo.videoPlayer = this;
if (!$.b4dvideo.contentInitialised) {
$.b4dvideo.contentInitialised = true;
$.b4dvideo._loadContent();
}
this.on("pause", function () {
this.posterImage.show()
});
this.on("ended", function () {
$.b4dvideo.videoPlayer.pause();
$.b4dvideo.videoPlayer.currentTime(0);
$.b4dvideo.videoPlayer.pause();
this.posterImage.show()
});
});
And changing the source of the player
if (!$.b4dvideo.videoPlayer.paused()) {
$.b4dvideo.videoPlayer.pause();
}
$.b4dvideo.videoPlayer.currentTime(0);
$.b4dvideo.videoPlayer.pause();
$.b4dvideo.videoPlayer.src(videoPath);
$.b4dvideo.videoPlayer.play();
It looks like the flash player is keeping the whole video in memory and never releasing it.
Any ideas on that?
I have even tried using jwplayer - same problem :-(
Update 1:
I also created a js-fiddle demonstrating this issue... just press play several times and watch your memory
http://jsfiddle.net/fwcJh/2/

Related

Facebook Instant Games stuck at 0% loading

I have a super simple HTML5 game that I'm trying to test within facebook embedded player, but the game always stuck at 0% loading and it doesn't log the word "test" that I have at the beginning meaning that it's not even initialized. why is that?
https://www.facebook.com/embed/instantgames/YOUR_GAME_ID/player?game_url=https://localhost:8080
I have replaced the GAME_ID with mine
index.html
<script>
FBInstant.initializeAsync().then(function() {
console.log("test");
var progress = 0;
var interval = setInterval(function () {
progress+=3;
FBInstant.setLoadingProgress(progress);
} , 100);
FBInstant.startGameAsync()
.then(function() {
// Retrieving context and player information can only be done
// once startGameAsync() resolves
var playerName = FBInstant.player.getName();
var playerPic = FBInstant.player.getPhoto();
var playerId = FBInstant.player.getID();
// Once startGameAsync() resolves it also means the loading view has
// been removed and the user can see the game viewport
game.start();
});
});
</script>
Facebook Instant game will work on HTTPS, one of your chrome browser tab should open below the localhost URL
https://localhost:8080
Then in the next tab, you should run the below URL, now it will work fine.
https://www.facebook.com/embed/instantgames/YOUR_GAME_ID/player?game_url=https://localhost:8080
it seems to have problem with the variable "game." I do not find where it is initiated. When I temporally disable commands with "game" and it no longer stucks at 0%. Try debugging that variable, you may resolve the problem.

Embed.ly API: player.js not working with youku.com

I have a problem with embedded video. I use "Embed.ly API" and "player.js":
https://docs.embed.ly/docs/oembed
https://docs.embed.ly/docs/playerjs
I'm trying to embed a video from "youku.com" on my site. The "youku.com" is a content provider, as stated here: https://embed.ly/providers
Video is added but player's methods (play, pause and others) does not work for video. But if I changing video service from "youku.com" to "youtube.com" and use video from "youtube.com", then methods works well.
I also tried to connect the "platform.js" instead of the player. The result is the same.
Maybe the "player.js" worked before, I guess that the "youku.com" has changed its API, but the "player.js" did not track changes.
Does the player.js really work with "youku.com" now? Perhaps something should be added to my code for solve the problem? I am not in China, can it have any effect due to the fact that "youku.com" is a Chinese service?
Thanks.
My code js: (And another question: are there any errors in the code?)
var obj_json = $.getJSON('https://api.embedly.com/1/oembed?' + $.param({
url: :url, // for example: https://v.youku.com/v_show/id_XMzg2MjgwNzA0OA==.html
key: :key // my_API_key
})).done(function () {
$('.embeded').html(obj_json.responseJSON.html).find('iframe.embedly-embed').each(function () {
// initialize the player.
var player = new playerjs.Player(this);
player.on('ready', function () {
player.setLoop(true); // it is not work
player.play(); // it is not work
//..................................
// There are also special buttons on the page, clicking on which the video should start or stop:
$('.button_play').click(function () {
player.play(); // pressing occurs, but player it is not work
});
$('.button_pause').click(function () {
player.pause(); // pressing occurs, but player it is not work
});
//.........................................
});
});
});

Set videoElement.currentTime in Hulu video player doesn't work, and breaks the player

I have a Chrome extension in which I'm trying to jump forward or backward (based on a user command) to a specific time in the video by setting the currentTime property of the video object. Before trying to set currentTime, a variety of operations work just fine. For example:
document.getElementsByTagName("video")[1].play(); // works fine
document.getElementsByTagName("video")[1].pause(); // works fine
document.getElementsByTagName("video")[1].muted = true; // works fine
document.getElementsByTagName("video")[1].muted = false; // works fine
BUT as soon as I try to jump to a specific point in the video by doing something like this:
document.getElementsByTagName("video")[1].currentTime = 500; // doesn't work
No errors are thrown, the video pauses, and any attempted actions after this point do nothing. So the items shown above (play/pause/mute/unmute) no longer work after attempting to set currentTime. If I read the value of currentTime after setting it, it correctly displays the new time that I just set it to. Yet nothing I do will make it play, and in fact even trying to make the video play by clicking the built-in toolbar no longer works. So, apparently setting currentTime wreaks all kinds of havoc in the video player. Yet if I reload the video, all works as before as long as I don't try to set currentTime.
I can easily jump to various times (backward or forward) by sliding the slider on the toolbar, so there must be some way internally to do that. Is there some way I can discover what code does a successful time jump? Because it's a Chrome extension I can inject custom js into the executing Hulu js, but I don't know what command I would send.
Any ideas?
Okay I fiddled around with it for a little while to see how I could reproduce the click event on the player and came up with the following solution:
handleViewer = function(){
var thumbnailMarker = $('.thumbnail-marker'),
progressBarTotal = thumbnailMarker.parent(),
controlsBar = $('.controls-bar'),
videoPlayer = $('#content-video-player');
var init = function(){
thumbnailMarker = $('.thumbnail-marker');
progressBarTotal = thumbnailMarker.parent();
controlsBar = $('.controls-bar');
videoPlayer = $('#content-video-player');
},
check = function(){
if(!thumbnailMarker || !thumbnailMarker.length){
init();
}
},
show = function(){
thumbnailMarker.show();
progressBarTotal.show();
controlsBar.show();
},
hide = function(){
controlsBar.hide();
},
getProgressBarWidth = function(){
return progressBarTotal[0].offsetWidth;
};
return {
goToTime: function(time){
var seekPercentage,
duration;
check();
duration = videoPlayer[0].duration;
if(time > 0 && time < duration){
seekPercentage = time/duration;
this.jumpToPercentage(seekPercentage);
}
},
jumpToPercentage: function(percentage){
check();
if(percentage >= 1 && percentage <= 100){
percentage = percentage/100;
}
if(percentage >= 0 && percentage < 1){
show();
thumbnailMarker[0].style.left = (getProgressBarWidth()*percentage)+"px";
thumbnailMarker[0].click();
hide();
}
}
}
}();
Once that code is initialized you can do the following:
handleViewer.goToTime(500);
Alternatively
handleViewer.jumpToPercentage(50);
I've tested this in chrome on a MacBook pro. Let me know if you run into any issues.
Rather than try to find the javascript responsible for changing the time, why not try to simulate the user events that cause the time to change?
Figure out the exact sequence of mouse events that trigger the time change.
This is probably some combination of mouseover, mousedown, mouseup, and click.
Then recreate those events synthetically and dispatch them to the appropriate elements.
This is the approach taken by extensions like Stream Keys and Vimium.
The video should be ready to play before setting the currentTime.
Try adding this line before setting currentTime?
document.getElementsByTagName("video")[1].play();
document.getElementsByTagName("video")[1].currentTime = 500;
Looks like it works if you first pause, then set currentTime, then play again.
document.getElementsByTagName("video")[1].pause()
document.getElementsByTagName("video")[1].currentTime = 800.000000
document.getElementsByTagName("video")[1].play()
Probably would need to hook into some event like onseeked to put in the play command to make it more robust.

Game slows down on click

I'm currently working on a game in node using socket.io and drawing onto canvas. I'm noticing that when I click during the game, character movement slows to a crawl. I would ideally like to maintain the draw rate that the game begins at and determine what's causing these memory issues. I'm looking to find out how I can debug this in a deterministic way
For context: I'm updating x,y coordinates in the game loop according to which keys are active (dictated by keyup and keydown events). I'm sending player information to the server via sockets about ~60 times a second.
To get more specific, here's a recording of the page's memory timeline:
The steep increase happens right around the time of the click event. The original jump (before the 6 extra listeners are added) is happening once the game starts. As you can see it's going a little wild on that click.
I have no handlers bound to the click event but the JS Heap grows rapidly and listeners seem to be added which confuses me. Here's a link to my repo, below is a chunk from game.js that has to do with keypresses and may be somehow involved:
var sendKey = function (activeK) {
player.xSpeed = 0;
player.ySpeed = 0;
if (activeK[KEY_W]) {
player.ySpeed = -SPEED;
}
if (activeK[KEY_A]) {
player.xSpeed = -SPEED;
}
if (activeK[KEY_S]) {
player.ySpeed = SPEED;
}
if (activeK[KEY_D]) {
player.xSpeed = SPEED;
}
if (activeK[SPACE]) {
activate(player)
}
}
document.onkeydown = function(e) {
if (activeKeys.hasOwnProperty(e.keyCode)) {
activeKeys[e.keyCode] = true;
sendKey(activeKeys)
}
}
document.onkeyup = function(e) {
if (activeKeys.hasOwnProperty(e.keyCode)) {
activeKeys[e.keyCode] = false;
sendKey(activeKeys)
}
}
Thanks!
Note: I originally started from scratch to try to learn a bunch but will likely switch to a game making framework.

Get audio duration on Chrome for Android

I'm getting the audio/video duration of a file without appending it to the screen. "Using the same code", when I try to get the video duration on both sides it works as expected. But when using audio files it says that the duration is 0 on Android, but it works on a desktop computer.
// Only working on Desktop
var audio = new Audio(url);
// Hide audio player
// player.appendChild(audio);
audio.addEventListener('loadedmetadata', function() {
alert(audio.duration);
});
And the below code is working:
// Working on Desktop and Android
var video = document.createElement('video');
video.src = url;
// Hide video
// player.appendChild(video);
video.addEventListener('loadedmetadata', function() {
alert(video.duration);
});
There is a different approach you can try but, if duration doesn't work with your device (which IMO is a bug) then it's likely this doesn't either; worth a shot though:
audio.seekable.end(audio.seekable.length-1);
or even
audio.buffered.end(audio.buffered.length-1);
though the latter is dependent on content being loaded which in this case probably then won't help.
EDIT: Using the durationchange event is much easier. First the 0 is being output, but as soon as the file is loaded (that's where loadedmetadata fails I guess) the updated and real duration will be output.
audio.addEventListener('durationchange', function(e) {
console.log(e.target.duration); //FIRST 0, THEN REAL DURATION
});
OLD WAY (ABOVE IS MUCH FASTER)
Looks like this "bug" (if this is actually a real bug) is still around. Chrome (40) for Android still outputs 0 as the audio files duration. Researching the web didn't get me a solution but I found out the bug also occurs on iOS. I figured I should post my fix here for you guys.
While audio.duration outputs 0, logging audio outputs the object and you can see that the duration is displayed just right there. All this is happening in the loadedmetadata event.
audio.addEventListener('loadedmetadata', function(e) {
console.log(e.target.duration); //0
});
If you log audio.duration in the timeupdate event though, the real duration is being output. To only output it once you could do something like:
var fix = true;
audio.addEventListener('timeupdate', function(e) {
if(fix === true) {
console.log(e.target.duration); //REAL DURATION
fix = false;
}
console.log(e.target.currentTime); //UPDATED TIME POSITION
});
I'm not sure why all this is happening. But let's be happy it's nothing serious.

Categories