Why the sound not working when the page is loaded? - javascript

I tried to play sound when the page is loaded, but it's not working never but when I click on button the sound is working.
JavaScript
<script>
$( document ).ready(function() {
let audio = new Audio('sounds/sound.mp3');
let is_play = true;
let btn = document.getElementById("sound_btn");
audio.play();
$("#" + btn.getAttribute("id")).click(function () {
if (is_play) {
btn.innerText = "Play Sound";
is_play = false
audio.pause();
} else {
btn.innerText = "Pause Sound";
is_play = true;
audio.play();
}
});
});
</script>

You’re probably using Google chrome which prevents playing audio files upon loading, you can check your log for such an error.
Audio files has to has to be played after a user’s event (as clicking).

Related

Chrome Extension: Background script only functioning correctly for the first time

I am working on a chrome extension that receives the audio from the microphone and the current tab. It is working fine for the first time but the script is not running correctly (It works but not as expected) in the subsequent runs.
Here is the code for my background(not persistent) script:
const audioContext = new AudioContext();
const destination = audioContext.createMediaStreamDestination();
const body = document.getElementsByTagName('body')[0];
let chunks = [],
tabStream,
micStream,
tabAudio,
micAudio,
output,
audioConfig,
text = '',
micable = true,
paused = false;
const constraints = {
audio: true,
};
function getTabAudio() {
chrome.tabCapture.capture(constraints, (_stream) => {
// keep playing the audio in the background
const audio = new Audio();
audio.srcObject = _stream;
audio.play();
tabStream = _stream;
tabAudio = audioContext.createMediaStreamSource(tabStream);
tabAudio.connect(destination);
output = new MediaStream();
output.addTrack(destination.stream.getAudioTracks()[0]);
recorder = new MediaRecorder(output);
recorder.start();
recorder.ondataavailable = (e) => {
chunks.push(e.data);
// call download when recorder state is inactive
if (recorder.state == 'inactive') download();
};
});
}
// get mic audio
function getMicAudio() {
navigator.mediaDevices.getUserMedia(constraints).then((mic) => {
micStream = mic;
micAudio = audioContext.createMediaStreamSource(micStream);
micAudio.connect(destination);
// get tab audio
getTabAudio();
});
}
// start recording the stream
function startRecord() {
getMicAudio();
}
// stop record -> stop all the tracks
function stopRecord() {
recorder.stop();
micStream.getTracks().forEach((t) => t.stop());
tabStream.getTracks().forEach((t) => t.stop());
output.getTracks().forEach((t) => t.stop());
micable = true;
chunks = [];
}
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
switch (request.type) {
case 'record':
startRecord();
break;
case 'stop':
stopRecord();
break;
case 'pause':
pauseResumeRecord();
break;
case 'mute':
muteMic();
break;
default:
break;
}
});
To make it work again, I have to refresh the current tab and extension from the chrome://extenions page.
I am not using any onInstalled listeners.
Any help is highly appreciated! Thanks in advance.
Please review the background page console logs.... Probably there are errors there that you to solve...
To do it
Write click your extension icon at the top corner of chrome... Manage extensions... Enable developer mode at the top right corner... Open inspect views background page
Okay, so I solved it finally!
The answer is to reload the background script each time the recorder was stopped. This way the background script variables will be reset to their default values and the script will work as expected.
Here is the code to reset the background script:
chrome.extension.getBackgroundPage().window.location.reload();

Run function after audio is loaded

I want to run a function after checking if an audio file is downloaded.
My js:
// https://freesound.org/people/jefftbyrd/sounds/486445/
var audioFile = "https://raw.githubusercontent.com/hitoribot/my-room/master/audio/test/test.mp3";
var audioElem = document.querySelector("audio");
var startElem = document.querySelector("button");
var resultScreen = document.querySelector("p");
function checkAudio() {
audioElem.setAttribute("src", audioFile);
if (audioElem.complete) {
resultScreen.innerHTML = "loaded audio";
}
}
startElem.addEventListener("click", function(){
checkAudio();
});
Codepen: https://codepen.io/carpenumidium/pen/KKPjRLR?editors=0011
I want the "loaded audio" text to be displayed, after the audio file has completed downloading. The code to check if the file has completed downloading might be utter bs so please go easy on me.
Thanks for your help!
You are not using the correct even to check the loaded status. See below a snippet that will do that.
You need to use the canplaythrough event that means
The browser estimates it can play the media up to its end without
stopping for content buffering.
The event you are using complete is actually triggered when
The rendering of an OfflineAudioContext is terminated.
// https://freesound.org/people/jefftbyrd/sounds/486445/
var audioFile = "https://raw.githubusercontent.com/hitoribot/my-room/master/audio/test/test.mp3";
var audioElem = document.querySelector("audio");
var startElem = document.querySelector("button");
var resultScreen = document.querySelector("p");
function checkAudio() {
audioElem.setAttribute("src", audioFile);
audioElem.addEventListener('canplaythrough', (event) => {
resultScreen.innerHTML = "loaded audio";
});
}
startElem.addEventListener("click", function() {
checkAudio();
});
<audio controls="controls" src=""></audio>
<button>load audio</button>
<div class="result">
<h1>Audio file status:</h1>
<p></p>
</div>
For more on audio elements refer MDN Docs
Hope this helps :)
You can use the onload event to get notified when the full audio is loaded:
function checkAudio() {
audioElem.setAttribute("src", audioFile);
audioElem.onload= ()=>{
resultScreen.innerHTML = "loaded audio";
}
}
startElem.addEventListener("click", function(){
checkAudio();
});

Reset button text after audio plays

I have a button that plays an audio file when you click playAudio with the text "PLAY VOICE AUDIO", and the text is changed to "PAUSE VOICE". It pauses if you click playAudio again(now with the text "PAUSE VOICE") when playing.
I would like the button text to go back to the "PLAY VOICE AUDIO" once the audio file has finished playing.
Thanks for any help in advance!
<div class="center">
<button id="playAudio">PLAY VOICE AUDIO</button>
</div>
<audio id="testAudio" hidden src="testaudioagainmp3.mp3" type="audio/mpeg"></audio>
<!-- Play/pause audio script -->
<script>
document.getElementById("playAudio").addEventListener("click", function() {
var audio = document.getElementById('testAudio');
if(this.className == 'is-playing') {
this.className = "";
this.innerHTML = "PLAY VOICE AUDIO"
audio.pause();
} else {
this.className = "is-playing";
this.innerHTML = "PAUSE VOICE";
audio.play();
}
});
</script>
var audio = document.getElementById('testAudio');
var btn = document.getElementById("playAudio");
audio.addEventListener('ended', function() {
btn.innerHTML = "PLAY VOICE AUDIO";
btn.className = "";
});
You are currently only have an event listener for clicks on your button playAudio. You need a second event listener for when the audio has ended playing. In this case it is simply the ended event, which you need to attach to your audio variable with addEventListener.
Below is the the code I would use.
// This part is just a refactored version of your current code.
var audio = document.getElementById('testAudio');
var playButton = document.getElementById('playAudio');
playButton.addEventListener('click', function() {
if(this.className == 'is-playing') {
this.className = "";
this.innerHTML = "PLAY VOICE AUDIO"
audio.pause();
} else {
this.className = "is-playing";
this.innerHTML = "PAUSE VOICE";
audio.play();
}
});
// This runs when the audio ends and will change the `playButton`'s text to be "PLAY VOICE AUDIO"
audio.addEventListener('ended', function() {
playButton.innerHTML = 'PLAY VOICE AUDIO';
playButton.className = '';
}
I would also suggest learning some ES6(the newest JavaScript version), but I have left the code as is.

A-Frame - playing / pausing sound with a custom ('a-sound') source

Edit 2: Here is the working code. Many thanks to Piotr for his help I couldn't have done it so effortlessly without you guys.
sceneEl.querySelector('a-sound').setAttribute('sound', {src:url3});
let playing = false;
var el = document.querySelector('a-box');
let audioEl = document.querySelector("a-sound");
var audio = audioEl.components.sound;
el.addEventListener('click', () => {
if (!playing) {
audio.playSound();
} else {
audio.stopSound();
}
playing = !playing;
})
} );
request.send( null );
}
});
Edit: I've got the sound playing from a dynamic URL (in my JSON file), but I cant seem to get the event listener function right (for playing / pausing on click).
sceneEl.querySelector('a-sound').setAttribute('sound', {src:url3});
let audioEl = document.querySelector("a-sound");
let audio = audioEl.components.sound;
sceneEl.querySelector('a-box').addEventListener('click', function () {
if(!playing) {
audio.play();
} else {
audio.pause();
audio.currentTime = 0;
}
playing = !playing;
});
} );
request.send( null );
}
});
Original: I'm using this component in A-Frame, but I'm looking to play the sound from the src in the ('a-sound') entity rather than from the asset link. The reason is because I'm loading the sound files dynamically from a JSON array so they don't exist in any list of assets. I've got all my files loading but am having trouble getting this component to hook into my loaded sceneEl.querySelector('a-sound').setAttribute('sound', {src:url3}); code. I'm thinking its just a small syntax issue but I'm not 100% sure. Could someone please look over this for a minute and tell me if its doable? This is the code (same as the link except for the (a-sound) within the querySelector.
AFRAME.registerComponent('audiohandler', {
init:function() {
let playing = false;
let audio = document.querySelector('a-sound');
this.el.addEventListener('click', () => {
if(!playing) {
audio.play();
} else {
audio.pause();
audio.currentTime = 0;
}
playing = !playing;
});
}
})
</script>
Using the <a-sound> You must handle things a bit differently.
playing / stopping the sound should be done within the sound component. You need to access it via yourEntityName.components.sound and use the playSound() and stopSound() methods.
check it out on my glitch. I set the source via the setAttribute(), and make a play / stop button.
My <a-sound> has a geometry to be a button, but You can make a <a-sound> entity, and use it like this:
let audioEl = document.querySelector("a-sound");
audioEl.setAttribute("src", "sourceURL");
let audio = audioEl.components.sound;
// play = audio.playSound();
// stop = audio.stopSound():
Furthermore, there are many issues with the nodes not being fully loaded. Check out this example:
<a-entity component></a-entity>
<a-sound></a-sound>
If the component tries to grab a reference to the document.querySelector("a-sound").components.sound, it may be undefined. If so, You should try to wait until it emits the loaded signal.

stopping new audio to play

I want to play only one audio at a time in response to some mouse event. The situation is onmouse over event on different HTML element plays audio. It becomes noisy when a user moves the mouse fast from one element to another and both the element plays audio. I want to check whether any audio is being played before playing a new audio. I used following code:
var $audioAnno=0;
function audioAnnotation(y){
var audio;
if ($audioAnno==0){
$audioAnno=1;
audio = new Audio(y);
audio.play();
$audioAnno=0;
}
}
It does not stop the 2nd audio to play.
this is how, I would do it, maintain a flag canPlay and on mouse event, if true, then play
canPlay = true;
var es = document.getElementsByTagName('audio'), audios=[];
for(var i=0;i<es.length;i++) audios.push(es[i]);
audios.forEach(function(e){
e.addEventListener('play', function(){
canPlay= false;
});
e.addEventListener('ended', function(){
canPlay= true;
});
});
// later on some mouseEvent based on some condition
function onMouseEvent(audioElement){
if(canPlay){
audioElement.play();
}
};
Edit: fiddle demo.
Edit2:
same thing with just audio object:
var audio = new Audio(), canPlay = true;
audio.src = 'http://upload.wikimedia.org/wikipedia/en/f/f9/Beatles_eleanor_rigby.ogg';
audio.addEventListener('play', function(){
console.log('playing');
canPlay = false;
});
audio.addEventListener('ended', function(){
console.log('stopped');
canPlay = true;
});
audio.play();
//similar mouse event listener changes to
function onMouseEvent(){
if(canPlay){
//audio.src ='...'; // providing new source
audio.play();
}
};
Thanks all.
I could solve the problem. I used following code:
var $audioAnno=0;
function audioAnnotation(x, y){
var audio = new Audio(y);
if ($audioAnno==0){
$audioAnno = 1;
audio.play();
audio.addEventListener("ended", function(){ $audioAnno = 0; });
}
}

Categories

Resources