Javascript audio not playing - javascript

I get a headache trying to understand why my script is not playing the sounds like i want to.
I have a quite simple HTML/Javascript animation with several sounds into it, executed on user's interaction (swipe, click, validate...).
Here is the url if you want to test and see the complete source :
http://artcode.fr/apps/bioprojet/simulation/index.html
The issues are at step 4 & 5 :
Step 4, clicking on the red button makes it disappear, execute an "injection sound", plays "validate sound" and then goes to step 5 where there should be a clock sound executed each second during the countdown to 10.
This regular behavior is ok in desktop browser (Safari/Chrome), but when launched in Safari mobile ou Chrome mobile, the sounds on step 4 are not always played (sometimes even inverted), and the clock sound on step 5 is never played.
I tried a lot of things to make it work, with no success, as :
"currenTime" and "pause()"
"onended" event, but doesn't seem to work on mobile
different sounds, to see if the issue came from this (answer is no)
inverted places
Here is the part of the code where the mess is :
if(e==4){
$("#voir_etape_3").addClass("voir_etape_on");
$("#bouchon_rouge").click(function(){
clic.play();
$("#anim_clic").animate({ top: "110px" }, { duration:50, complete: function(){
var pauseclic = setInterval(function(){
clearInterval(pauseclic);
valide.play();
$(".etape").hide();
$("#etape_5").show();
actions(5);
},2000);
}});
});
}
if(e==5){
$("#voir_etape_4").addClass("voir_etape_on");
var t=0;
var decompte = setInterval(function(){
t++;
if (t<=10){
tic.play();
$("#decompte").text(t);
if (t==10){ $("#decompte").addClass("decompte_on"); }
} else{
$("#decompte").addClass("decompte_on");
if (t==11){
clearInterval(decompte);
tictactic.pause();
//tictactic.currentTime = 0;
valide.play();
$(".etape").hide();
$("#etape_6").show();
actions(6);
}
}
}, 1000);
}
Sounds are defined at the beginning of my javascript script :
var valide = new Audio('./graph/valide.mp3');
var tic = new Audio('./graph/tictac.mp3');
var tictactic = new Audio('./graph/tictactic.mp3');
var clic = new Audio('./graph/clic.mp3');

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.

P5JS sound only plays when I leave the active tab

I'm trying to write a code so that when a rect() reaches a certain point, a song will start playing. I was having trouble with my actual code so I started a new test file to mess around with it and try to get it to work (my actual js file is very long & I wanted something short and simple) but I just ran into the problem again.
The code is supposed to work so if the mouse is pressed, the left square will slide over to the right square, and when it hits the right square, the song will play. If the mouse is clicked again, the song will stop.
I've gotten most of that to work, but the trouble comes in when I add in
if ( backtoblack.isPlaying() ) {
backtoblack.stop();
} else {
backtoblack.play();
}
Here's the complete code for the sketch:
var backtoblack;
var rect1X = 20;
var speed = 1;
var mouseWasPressed;
function preload(){
backtoblack = loadSound('assets/backtoblack.mp3');
}
function setup() {
createCanvas(590,630);
background("#704e34");
}
function draw(){
fill("#fff");
rect(rect1X, 20, 120, 120);
rect(450, 20, 120, 120);
if (mouseWasPressed == true ) {
if(rect1X <= 390){
rect1X += speed;
}
}
if ( backtoblack.isPlaying() ) {
backtoblack.stop();
} else {
backtoblack.play();
}
}
function mousePressed(){
mouseWasPressed = true;
}
The problem is that your if else block that toggles whether the song is playing is inside the draw() function. That means that 60 times per second, you toggle the song! It's like you're constantly hitting the play and stop buttons. Then when you switch tabs, the draw() function is paused, which is why it stops toggling.
To fix your problem, you need to not toggle the song every frame. Perhaps put it inside the mousePressed() function to test things out.
Taking a step back, I'd also encourage you to debug your code (that guide is for Processing, but here is a guide on JavaScript). It's really great that you put together a smaller example program to test things out, but you should also try to step through the code line by line, or add print statements, to figure out what's going on. Stepping through or adding print statements would have helped you realize what was going on.
Anyway, good luck!

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.

Javascript:: audio.currentTime is updated properly only after alert

I think that I found a bug on JavaScript Audio API.
My code is working perfectly like that :
var audio=new Audio();
var lastPause;
var myPlayer=document.querySelector('#player>.button.hand');
var playerStatus=("textContent" in document)?"textContent":"innerText";
myPlayer.addEventListener
(
'click',
function()
{
if(audio.paused)
{
audio.src="Nadav Guedj - Golden Boy (Eurovision 2015 - Israel - Karaoke).mp3";
myPlayer.innerHTML="►";
if(lastPause)
{
alert(lastPause); //If I remove this line it's not working when lastPause is defined!
audio.currentTime=lastPause;
}
audio.play();
}
else
{
myPlayer.innerHTML="||";
lastPause=audio.currentTime;
audio.pause();
}
}
);
BUT
If I remove or remark the alert line alert(lastPause); the audio stuck when lastPause is defined or iow... The second time the user press play (after pause).
I am assuming this question is related to this question my answer there is applicable for this also,
repeated setting audio.src is your problem. you have two ways of fixing this:
get rid of audio.src line, bunch of other redundant code could also be removed with it.
the reason it works when you use alert is, when alert is triggered, the next few lines are not executed till you dismiss it, in these precious few seconds/ milliseconds, the audio element whose source has been changed has enough time to load the new metadata, only then can the current time can be set. so you can modify the code to trigger setting of audio on metadata loading:
...
myPlayer.innerHTML="►";
audio.play();
audio.onloadedmetadata = function(){
if(lastPause){
audio.currentTime = lastPause;
}
};
fiddle demo

Replaying an Audio element in chrome

sounds["foo"]= new Audio("foo.ogg");
function playSound(id){
var snd = this.sounds[id];
if(snd.currentTime>snd.duration*0.99999){
snd.pause();
snd.currentTime=0;
//snd.seekable.start(); //doesnt work
//snd.load(); does the trick but with the cost re-downloading the clip every single time
snd.play();
}
if(snd.currentTime==0)
snd.play();
}
For some reason playSound('foo'); works on the first time, but fails after that on Chrome (works just fine on Firefox). Adding snd.load() seemed to fix this, but now it downloads the clip from the server every time the clip is played, which is a lot in my use case.
EDIT: Oh, and snd.currentTime seems to get stuck at the end, so snd.currentTime=0 does nothing.
The following script works just fine for me on OSX, Chrome Version 32.0.1700.102 and Firefox 27.0.
If you do not want to loop the file immediately, your script definitely is the right approach.
I couldn't reproduce your issues. I associated the method with an onclick action on a link and used a 5s .ogg file for testing. Clicking the link and re-playing the audio file worked for me all the time.
The only possible issue I noticed is your second if clause. If the first if is matched, the time is set to 0 and the file will be played. Even if it is very unlikely in my opinion, it could be that the second if is also matched and snd.play() is invoked a second time. I therefore would use else if.
Can you give it a try? Even though I suppose it does not solve your problem :/
<script type="text/javascript">
var sounds = [];
sounds["foo"]= new Audio("foo.ogg");
/* First solution, creating a loop */
function playSoundLoop(id){
var snd = this.sounds[id];
snd.play();
snd.addEventListener('ended', function(){
this.currentTime = 0;
this.play();
}, false);
}
/* Use else if instead of if */
function playSound(id){
var snd = this.sounds[id];
if(snd.currentTime>snd.duration*0.99999){
snd.pause();
snd.currentTime=0;
snd.play();
} else if(snd.currentTime==0) {
snd.play();
}
}
</script>

Categories