I built a simple matching game and added audio files for several cards like this:
cardList.map((cardItem) => {
var card = document.createElement("li");
card.classList.add("card");
var img = document.createElement("img");
img.src = [cardItem.img]
card.appendChild(img);
//audio starting here
audio = new Audio(cardItem.sound);
card.appendChild(audio);
audio.id += ' ' + cardItem.card;
deck.append(card);
card.className += ' ' + cardItem.name;
});
}
And in my startGame() function I added an eventListener to add audio.play(); on click.
So now, when I open dev tools, I can see audio elements for my cards but when I try and click on them, I'm only ever getting one audio file for all cards and not the audios I actually added to that specific element.
That's my GitHub file: https://github.com/cMikolai/guitar-colour-system-game/blob/master/js/app.js
Could anybody try and help me figure out how I could play the sound I added to the card I am clicking on?
I downloaded your code and played around. The code for playing audio is in the function startGame() in your app.js file.
app.js:
audio = []; // local variable declaration
...
...
// some code
function startGame() {
// some code
for (var i = 0; i < clickedCard.length; i++) {
clickedCard[i].addEventListener("click", function( event ) {
this.classList.add("open", "show");
openCards.push(this.getAttribute("class"));
audio.load();
audio.play(); // this is the line playing the audio
matchCards();
starRating();
}, false);
}
}
As you can see, you are not playing audio from the selected card but from the local variable audio.
So, you have to identify the selected card and play its respective audio instead of playing audio from the local variable.
Related
I have an embedded playlist of video links from different websites like Dailymotion, YouTube, Vimeo, etc., that I would like to play back to back on a personal website that I am working on. I found a script on the internet that plays embedded videos from multiple websites, but it only plays one video randomly. I would like the script to play each video back to back once one video is finished playing, but since I have no skills whatsoever in javascript, I don't know how to adapt this script to meet my needs. Does anyone know how I can accomplish this? I would greatly appreciate any kind of help. Thanks! Here is the script:
<div id="random_player"></div>
<script>
var videos = ["https://www.dailymotion.com/embed/video/x7raxfh?queue-enable=false","https://ok.ru/videoembed/3188453542586","https://www.youtube.com/embed/X3wV5ydVewY" ];
window.onload = function () {
var playerDiv = document.getElementById("random_player");
var player = document.createElement("IFRAME");
var randomVideoUrl = videos[Math.floor(Math.random() * videos.length)];
player.setAttribute('width', '640');
player.setAttribute('height', '390');
player.setAttribute('src', randomVideoUrl);
playerDiv.appendChild(player);
};
</script>
Follow the step by step code below-
Step 1
Copy paste the below code in html file by replacing url to your desired one!-
<iframe src="url" id="videoPlayer" height="200"">
Step 2
Javascript file should look like this-
let videoSource = new Array();
videoSource[0] = 'https://www.dailymotion.com/embed/video/x7raxfh?queue-enable=false","https://ok.ru/videoembed/3188453542586';
videoSource[1] = 'https://www.youtube.com/embed/X3wV5ydVewY4';
let i = 0; // global
const videoCount = videoSource.length;
const element = document.getElementById("videoPlayer");
function videoPlay(videoNum) {
element.setAttribute("src", videoSource[videoNum]);
element.autoplay = true;
element.load();
element.play();
}
document.getElementById('videoPlayer').addEventListener('ended', myHandler, false);
videoPlay(0); // play the video
function myHandler() {
i++;
if (i == videoCount) {
i = 0;
videoPlay(i);
} else {
videoPlay(i);
}
}
Step 3
Save the file and call the javascript file on html file. Open the html file in browser and it will run according to your asked question!
I want to play a random song in a website. The tunes are short (max a few seconds, they don't need preload or buffering).
This part works, the number of songs may be unlimited, because tunes.length automatically counts all songs.
document.write displays the URL of a random song URL on the screen
tunes = new Array(
'"http://example.net/abcd.ogg"',
'"http://example.net/efgh.ogg"',
'"http://example.net/ijkl.ogg"'
)
var audiopath = (tunes[Math.floor(Math.random() * tunes.length)])
document.write (audiopath)
This part works too, when the URL is defined as a constant.
var song = new audio('http://example.net/abcd.ogg');
song.play();
When I try to replace the constant URL with the variable audiopath, it fails to play.
May it be anything wrong with the syntax?
I tried to run it with and without single quotes in the URL '"http://example.net/ijkl.ogg"' or "http://example.net/ijkl.ogg"
var song = new audio(audiopath);
song.play();
It might be better to handle starting playback once the song has fully loaded. Something like this:
let loaded = false;
const song = new Audio();
song.addEventListener('loadeddata', function()
{
loaded = true;
song.play();
}, false);
song.addEventListener('error' , function()
{
alert('error loading audio');
}, false);
song.src = tunes[Math.floor(Math.random() * tunes.length)];
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I'm trying to make my little project like AI, what I mean is I have a some audio files as an array. And I use annyang API as a voice command to start running the program. After the first audio file is done playing. The program pauses. And I will say some sentenses until the program detects no voice from me for 3 seconds(or even longer). It will play the second audio file and then pause again. This program will loop until all audio files have played. Is there anyway to do this?
Here is my code so far.
<script>
if (annyang)
{
var commands = {
'1': function()
{
var playList = ["1_hello", "2_how_old", "3_what_did_you_make"]
var dir = "sound/";
var extention = ".wav";
var index = 1;
var count = 4;
var agent = navigator.userAgent.toLowerCase();
if(agent.indexOf('firefox') != -1 || agent.indexOf('opera') != -1)
{
extention = ".wav";
}
audio = new Audio();
audio.src = dir + playList[0] + extention;
audio.load();
setTimeout(function(){audio.play();}, 1000);
audio.onended = function()
{
if(index < playList.length)
{
audio.src = dir + playList[index] + extention;
audio.load();
setTimeout(function(){audio.play();}, 1000);
index++;
}
}
audio.loop = false;
}
};
annyang.debug(true);
annyang.addCommands(commands);
}
</script>
I have found a visualizing sound that might do it, but I'm not sure how.
I have been struggling with this for a week. And Can't really find solutions for this. I'm open to jQuery as well. Thank you in advance.
You can use annyang.addCallback and annyang.addRemoveback to add or remove callbacks for events annyang fires.
According to the API documentation the event we are probably intested in is soundstart https://github.com/TalAter/annyang/blob/master/docs/README.md
soundstart - Fired as soon as any sound (possibly speech) has been
detected. This will fire once per Speech Recognition starting.
We can add or remove call backs to fire when this event is fired.
When can track when these events were fired and execute logic to play a song if more than 3 seconds has elapsed.
Here is some baseline psuedo code. I don't have a microphone so I can test.
var monitorId=0;
function monitorSound()
{
if(monitorId&& monitorId>0) return;
monitorId=window.setInterval(trackSound,1000);
}
var lastSound= new Date();
function trackSound() {
var now = new Date();
if (now-lastSound)>3000)
{
stopListening();
playNextAudio();
return;
}
}
function startListening() {
annyang.addCallback('startsound', onSoundHeard);
}
function stopListening()
{
// stop the loop tracking when the last sound was heard.
window.clearInterval(monitorId);
monitorId=0;
// Remove onSoundHeard from being called on start:
annyang.removeCallback('startsound', onSoundHeard);
}
var playList = ['mydir/mysong1.wav','mydir/mysong2.wav','mydir/mysong2.wav'];
var audioIndex=0;
function playNextAudio(){
if(index==playList.length-1) return; -- we have played all audio
// play the next audio
audio = new Audio();
audio.src = playList[index++];
audio.load();
setTimeout(function(){audio.play();}, 1000);
audio.onended = startListening
}
function onSoundHeard() {
lastSound= new Date();
}
Note: Exactly this has been asked before here, and here, without satisfactory answers.
I'll try to explain the problem better here, and you can also read TLDR below. Here's a simple fiddle I created using Soundcloud JS sdk v3. I define global variables playerGlobal and playingId. During the first play, both of them are null, and clicking one of play or playNext buttons initializes those variables. Suppose, we click play first, the related track starts playing. When we click pause button soon after, pause() fires and uses the globalPlayer to pause the currently playing track. This works as expected.
When I click playNext, both global variables are updated as they should. The problem arises when I click play again. For some strange reasons, the track associated with play button plays from time starting at when I clicked pause above. When I click pauseagain, nothing happens.
TLDR: Click play -> pause -> playNext(works fine till here) -> play(strange remembering of last position happens) -> pause(nothing happens).
I'm including the snippet here as well.
SC.initialize({
client_id: 'MmZKx4l7fDwXdlL3KJZBiJZ8fLonINga'
});
//Get player
function getPlayer(url) {
return new Promise(function(resolve, reject) {
SC.stream(url)
.then(player => {
if (player.options.protocols[0] === 'rtmp')
player.options.protocols.splice(0, 1);
resolve(player);
});
});
}
//Global players and id to track current playing track
var playerGlobal = null;
var playingId = null;
function play() {
var id = '1';
//Resume playing if the same song is hit
if (playerGlobal !== null && id === playingId) {
console.log("-- using old player");
playerGlobal.play();
return;
}
//New player on a new song
var url = '/tracks/309689093';
getPlayer(url)
.then(player => {
if (playerGlobal) playerGlobal = null;
playerGlobal = player;
console.log("-- new player created");
playerGlobal.play();
playingId = id;
});
}
function pause() {
playerGlobal.pause();
}
function playNext() {
var id = '2';
//Resume playing if the same song is hit
if (playerGlobal !== null && id === playingId) {
console.log("-- using old player");
playerGlobal.play();
return;
}
//New player on a new song
var url = "/tracks/309689082";
getPlayer(url)
.then(player => {
if (playerGlobal) playerGlobal = null;
playerGlobal = player;
console.log("-- new player created");
playerGlobal.play();
playingId = '2';
});
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<button onClick="play()">play</button>
<button onClick="pause()">pause</button>
<button onClick="playNext()">playNext</button>
<script src="https://connect.soundcloud.com/sdk/sdk-3.1.2.js"></script>
</body>
</html>
I'm not sure why this wouldn't work. One of the ways I was able to make this work was by defining separate player, pause and id variables for both tracks. And then when a track is played after another, I set seek to position 0. Here's it. The problem of course is, this is just for reference, my use case involves many more tracks, and I didn't want to define separate variables for them all, until I'm sure why above code doesn't work and that it is the only way. Any hints are appreciated.
I have this javascript function:
var currentPlayer;
function EvalSound(soundobj) {
var thissound = document.getElementById(soundobj);
if (currentPlayer && currentPlayer != thissound) {
currentPlayer.pause();
}
if (thissound.paused) {
thissound.play();
} else {
thissound.pause();
}
thissound.currentTime = 0;
currentPlayer = thissound;
}
And this html5 audio player repeating in a loop inside a Gridview widget in Yii2 (it creates many players each of them with a different song):
'value'=> function ($data){
return "<audio controls>
<source src='" . $data->ficheiro . "' type='audio/mp3' />
</audio>";
},
The problem is when I have an audio tag playing and click on the play button of another it doesn't stop the previous playing audio tag and starts the new one. Both audio tags play at the same time. I'm trying to adapt the javascript function but it doesn´t work.
I also tried declaring var thisound = $('audio');
It also does not work.
Do I need to put an ID in the audio tag?
Do I need to associate an onClick='EvalSound' event to the audio tag?
Ok, here is how I solved it:
The addEventListener grabs the audio beginning to play and the for loop pauses all other audio tags.
document.addEventListener('play', function(e) {
var audios = document.getElementsByTagName('audio');
for (var i = 0, len = audios.length; i < len; i++) {
if (audios[i] != e.target) {
audios[i].pause();
}
}
}, true);
You don't have a unique way of identifying the <audio> tags. And using a generic $("audio") seelctor makes the issue worse. Use id for all the tags and make it work that way.