I'm trying to build a web app that fetches a sound of a bird from an API, plays it and gets a new bird once the old one has stopped playing. As of now it works in Safari & Firefox, but the script stops in Chrome.
function init() {
console.log('init');
var container = document.getElementById("container");
container.innerHTML = ("Machines & Birds");
fetchBirdAPI();
}
function fetchBirdAPI() {
fetch(url)
.then(function(response) {
return response.json();
}).then(function(response) {
console.log(response)
getAudio(response);
});
}
function getAudio(response) {
if (response.numRecordings !== 0) {
var birdSrc = (response.recordings[0].file);
var audio = document.createElement('AUDIO');
audio.src = birdSrc;
audio.addEventListener('loadedmetadata', function() {
console.log(audio.duration);
});
audio.play();
audio.onended = function() {
console.log('Audio Ended');
init();
}
}
else {
init();
}
}
So basically the audio.onended doesn't work. Also tried to initiate the audio with audio = new Audio() without any luck.
Really flabbergasted here, so any input would be appreciated.
Related
I have a portfolio page made in WordPress and on the page I have 5 videos that need to be played when in viewport and stopped when out of viewport.
I have used the following script that works only on the first video on the page.
const video = document.querySelector("video");
let playState = null;
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (!entry.isIntersecting) {
video.pause();
playState = false;
} else {
video.play();
playState = true;
}
});
}, {});
observer.observe(video);
const onVisibilityChange = () => {
if (document.hidden || !playState) {
video.pause();
} else {
video.play();
}
};
document.addEventListener("visibilitychange", onVisibilityChange);
querySelector("video");
And here is the link to the page:
http://wemedia.co.rs/portfolio-2/
So what I want to achieve is to play and pause every video when in or out of viewport.
Thank you.
You are only selecting one video to use throughout your whole js script.
You need to remember that video represents only a single video and if you want to control multiple, you need to reference them in every function that you call.
I also don't see a purpose in using playState since the way you have it, it is basically an indicator of whether the first video is on screen or not.
const videos = document.querySelectorAll("video"); // Select ALL the Videos
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (!entry.isIntersecting) {
entry.target.pause(); // Pause the TARGET video
} else {
entry.target.play(); // Play the TARGET video
}
});
}, {});
for (const video of videos) observer.observe(video); // Observe EACH video
const onVisibilityChange = () => {
if (document.hidden) {
for (const video of videos) video.pause(); // Pause EACH video
} else {
for (const video of videos) video.play(); // Play EACH video
}
};
document.addEventListener("visibilitychange", onVisibilityChange);
function playSound(buffer) {
aSoundSource = audioContext.createBufferSource(); source.
aSoundSource.buffer = buffer;
aSoundSource.connect(gainNode);
gainNode.connect(analyser);
var volX = volControl();
//gainNode.gain.value = 0.1;
gainNode.gain.value = volX;
analyser.connect(audioContext.destination);
aSoundSource.start(0);
document.title = document.getElementById("files").value;
playing = true;
requestAnimFrame(drawVisualisation);
}
///////////////////////////////////////
function play(){
var audio = new Audio('test.mp3');
audio.play();
}
second function is working perfectly its i have called particular audio to play its working for button here i want to input a song and play
Havent tested but this is the rough idea
document.getElementById("inputFile").onchange = loadMusic
function loadMusic(e) {
console.log(e.target.value)
var audio = new Audio(e.target.value)
audio.play();
}
<input type="file" id="inputFile">
I have two functions in JavaScript. Its working fine on Windows 7 Chrome but loadedAudio_chrome function is not being fired on IPAD.
function preloadAudio_chrome(url)
{
try
{
var audio = new Audio();
audio.addEventListener('canplaythrough', loadedAudio_chrome, false);
//audio.src = filePath;
} catch (e) {
alert(e.message);
}
}
function loadedAudio_chrome()
{
//alert('not firing this alert on IPAD');
}
You seem to be missing audio.load() from your snippet, try adding that as shown below and it should work.
function preloadAudio_chrome(url)
{
try
{
var audio = new Audio();
audio.addEventListener('canplaythrough', loadedAudio_chrome, false);
// EDIT HERE ADD audio.load();
audio.load();
} catch (e) {
alert(e.message);
}
}
I have 6 videos in a page which are created using SWFOBJECT API.
The requirement is to pause a video when another video is played.
for ex: swfobject for video is
<DIV id=ytcontainer></DIV>
<SCRIPT>
swfobject.embedSWF("http://www.youtube.com/v/erDxb4IkgjM?version=3&f=user_uploads&app=youtube_gdatafs=1&rel=0&enablejsapi=1&playerapiid=myytplayer", "ytcontainer", "660", "394", "8", null, null, {allowscriptaccess:"always",allowfullscreen:"true",wmode:"opaque"}, {id:"myytplayer"});
</SCRIPT>
like this way, i have 6 videos in a single page
below is the code for pausing video
<script>
swfobject.addLoadEvent(onYouTubePlayerReady);
var status;
var videostate2=0; var videostate1=0;
function onYouTubePlayerReady(playerId)
{
var myPlayer1 = document.getElementById('myytplayer');
var myPlayer2 = document.getElementById('qualityvideotrack');
myPlayer1.addEventListener("onStateChange", "onytplayerStateChange1");
myPlayer2.addEventListener("onStateChange", "onytplayerStateChange2");
}
function onytplayerStateChange1(newState)
{
if(newState1==1)
{
videostate1=1;
pause();
}
else
videostate1=0;
return videostate1;
}
function pause()
{
var state;
console.log("pause");
var myPlayer2 = document.getElementById('qualityvideotrack');
var myPlayer1 = document.getElementById('myytplayer');
if(videostate2==1)
{
state=onytplayerStateChange2(videostate2);
console.log("Player's new state:2 before pause "+state);
if(state==1)
myPlayer2.pauseVideo();
}
if(videostate1==1)
{
state=onytplayerStateChange1(videostate1);
console.log("Player's new state:1 before pause "+state);
if(state==1)
myPlayer1.pauseVideo();
}
}
function onytplayerStateChange2(newState2)
{
if(newState2==1)
{
videostate2=1;
pause();
}
else
videostate2=0;
return videostate2;
}
</script>
the above mentioned code won't work properly. However, if i write the code to stop one video while other is playing it works but vice versa not. Kindly suggest me.
I am trying to play sounds with a .keydown() event in jQuery. I would like the sounds to play quickly, but there seems to be a lag time when I perform the keydown event faster than about 3 times per second.
Here is a jsFiddle of my sample code: http://jsfiddle.net/pfrater/FRudg/3/
I am using the audio html tags for the sound and playing:
<audio controls id="sound" preload="auto">
<source src="http://www.wavlist.com/soundfx/011/duck-baby.wav" type="audio/wav"/>
</audio>
<audio controls id="sound2" preload="auto">
<source src="http://rezound.sourceforge.net/examples/chirp.wav" type="audio/wav"/>
</audio>
<audio controls id="sound3" preload="auto">
<source src="http://www.all-birds.com/Sound/downychirp.wav" type="audio/wav"/>
</audio>
and here's my jQuery:
$(document).ready( function() {
var playing;
$(document).bind("keydown", function(key) {
playing = undefined;
switch(parseInt(key.which, 10)) {
case 65:
playing = $("#sound").get(0);
break;
case 83:
playing = $("#sound2").get(0);
break;
case 68:
playing = $("#sound3").get(0);
break;
};
if (playing) {
playing.play();
}
}).on("keyup", function() {
if(playing){
playing.pause();
playing.currentTime=50;
playing = undefined;
}
});
});
Does anyone know of a way to get rid of this lag? Also, the actual files that I'll be playing are mpegs. The ones above are just an example.
Thanks for any help,
Paul
You won't be able to do this with the audio element. This is because the cost setting up and filling the buffers will take too much time.
The good news though is that you can do it using the Web Audio API instead.
I made you an example based on this code from HTML5 rocks (which you should check out for more details) and your original fiddle.
Currently this API is supported in Chrome, Firefox, Safari and Opera will be able to use this:
Fiddle demo
window.AudioContext = window.AudioContext || window.webkitAudioContext;
/// custom buffer loader
/// see http://www.html5rocks.com/en/tutorials/webaudio/intro/
function BufferLoader(context, urlList, callback) {
this.context = context;
this.urlList = urlList;
this.onload = callback;
this.bufferList = new Array();
this.loadCount = 0;
}
BufferLoader.prototype.loadBuffer = function (url, index) {
var request = new XMLHttpRequest();
request.open("GET", url, true);
request.responseType = "arraybuffer";
var loader = this;
request.onload = function () {
// Asynchronously decode the audio file data in request.response
loader.context.decodeAudioData(
request.response,
function (buffer) {
if (!buffer) {
alert('error decoding file data: ' + url);
return;
}
loader.bufferList[index] = buffer;
if (++loader.loadCount == loader.urlList.length)
loader.onload(loader.bufferList);
},
function (error) {
console.error('decodeAudioData error', error);
});
}
request.onerror = function (e) {
alert('BufferLoader: XHR error');
}
request.send();
}
BufferLoader.prototype.load = function () {
for (var i = 0; i < this.urlList.length; ++i)
this.loadBuffer(this.urlList[i], i);
}
The main code:
/// setup audio context and start loading samples
var actx = new AudioContext(),
blst,
bLoader = new BufferLoader(
actx, [
'duck-baby.wav', 'chirp.wav', 'downychirp.wav'],
done),
isReady = false;
/// start loading the samples
bLoader.load();
function done(bl) {
blst = bl; /// buffer list
isReady = true; /// enable keys
$('#status').html('Ready!'); /// update statusw
}
/// this sets up chain so we can play audio
function play(i) {
var src = actx.createBufferSource(); /// prepare sample
src.buffer = blst[i]; /// set buffer from loader
src.connect(actx.destination); /// connect to speakers
src.start(0); /// play sample now
}
/// check keys
$(window).bind("keydown", function (key) {
if (!isReady) return;
switch (parseInt(key.which, 10)) {
case 65:
play(0);
return;
case 83:
play(1);
return;
case 68:
play(2);
return;
}
})
NOTE: When using external samples you must make sure they can be used cross-origin or else loading will fail (I used my DropBox to enable the samples to be loaded with fiddle).