I'm supposed to have 5 animal images on the site, and whenever I hover over an animal, their characteristic sound plays. Is there a more efficient way to do this rather than using switch case?
This is what I have so far (works only for 1 animal):
HTML:
<img src="img/piggy.png" onmouseover="F1(this)">
JS:
function F1(img) {
var audio = document.getElementById("audio");
audio.play();
}
I think this is a really solid base. If it were me I would do almost exactly what you are doing but set up an array with the list of available sound bites. Then, onmouseover pass in a number (0-5) and use that as the selector to choose which soundbyte plays.
var sounds = ["sound1", "sound2", "sound3", "sound4", "sound5"];
function playAudio(track) {
audio.play(sounds[track]);
}
Hopefully that's clear/helpful. Otherwise, let me know and I'll be glad to clarify.
You can have the sound to play embedded in the img tag's dataset :
<img src="img/piggy.png" data-sound='piggy.wav' onmouseover="playSound(this)">
function playSound(element) {
var audio = new Audio(element.dataset.sound);
audio.play();
}
you may want to pre-load all of the audio files on page load
I have a HTML page including Javascript which is intended to allow a video (actually just audio content in this case) to play using HTTP Live Streaming on any browser. In most cases it uses hls.js but, in the case of Apple products, I need to do things differently as Safari has native HLS support.
The full page is reproduced below but the important lines are these:
else if (video.canPlayType('application/vnd.apple.mpegurl')) {
video.src = 'music.m3u8';
video.addEventListener('canplay', startPlaying);
//document.addEventListener('DOMContentLoaded', startPlaying);
}
What should happen is that when the canplay event fires the startPlaying() function is called and this makes visible a button that the user can press to begin playing the video. However, on my friend's iPhone 8plus (iOS 11.3.1), this doesn't work: no button is ever visible. If, instead, I comment out the video.addEventListener() line and replace it with the document.addEventListener() line then it all works fine: the button is made visible and he can play the stream.
Can anyone spot what I'm doing wrong? Could be a rookey mistake as I'm not very experienced with this web/script stuff, gives me nose bleeds... I could, of course, leave it with the DOM load approach but it's not right and I'd rather be right.
<!DOCTYPE html PUBLIC "-//Netscape Comm. Corp.//DTD HTML//EN">
<html>
<script src="hls.js/dist/hls.js"></script>
<head><meta http-equiv="content-type" content="text/html; charset=UTF-8"></head>
<body>
<video id="video"></video>
<button id="play" hidden>Loading</button>
<script>
'use strict';
var video = document.getElementById('video');
var playButton = document.getElementById('play');
function startPlaying() {
// For mobile browsers the start of playing has to
// be performed by a user action otherwise it will
// be ignored
playButton.addEventListener('click', function() {
video.play();
video.muted = false;
video.volume = 1;
playButton.innerHTML = "Playing";
});
playButton.hidden = false;
playButton.innerHTML = "Ready to play";
}
if (Hls.isSupported()) {
var hls = new Hls();
hls.loadSource('music.m3u8');
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED, startPlaying);
}
// hls.js is not supported on platforms that do not have Media Source Extensions (MSE) enabled.
// When the browser has built-in HLS support (check using `canPlayType`), we can provide an HLS manifest (i.e. .m3u8 URL) directly to the video element through the `src` property.
// This is using the built-in support of the plain video element, without using hls.js.
else if (video.canPlayType('application/vnd.apple.mpegurl')) {
video.src = 'music.m3u8';
video.addEventListener('canplay', startPlaying);
//document.addEventListener('DOMContentLoaded', startPlaying);
}
</script>
</body>
</html>
From the investigations in the other question, the workaround is to wait on the event loadedmetadata, so in my case video.addEventListener('loadedmetadata', startPlaying), as this is the last event you're going to get from the HTML5 video element on Safari unless you're in the user-controlled white list. Confirmed that this works on iOS 11.3.1.
I am playing a small audio clip on click of each link in my navigation
HTML Code:
<audio tabindex="0" id="beep-one" controls preload="auto" >
<source src="audio/Output 1-2.mp3">
<source src="audio/Output 1-2.ogg">
</audio>
JS code:
$('#links a').click(function(e) {
e.preventDefault();
var beepOne = $("#beep-one")[0];
beepOne.play();
});
It's working fine so far.
Issue is when a sound clip is already running and i click on any link nothing happens.
I tried to stop the already playing sound on click of link, but there is no direct event for that in HTML5's Audio API
I tried following code but it's not working
$.each($('audio'), function () {
$(this).stop();
});
Any suggestions please?
Instead of stop() you could try with:
sound.pause();
sound.currentTime = 0;
This should have the desired effect.
first you have to set an id for your audio element
in your js :
var ply = document.getElementById('player');
var oldSrc = ply.src;// just to remember the old source
ply.src = "";// to stop the player you have to replace the source with nothing
I was having same issue. A stop should stop the stream and onplay go to live if it is a radio. All solutions I saw had a disadvantage:
player.currentTime = 0 keeps downloading the stream.
player.src = '' raise error event
My solution:
var player = document.getElementById('radio');
player.pause();
player.src = player.src;
And the HTML
<audio src="http://radio-stream" id="radio" class="hidden" preload="none"></audio>
Here is my way of doing stop() method:
Somewhere in code:
audioCh1: document.createElement("audio");
and then in stop():
this.audioCh1.pause()
this.audioCh1.src = 'data:audio/wav;base64,UklGRiQAAABXQVZFZm10IBAAAAABAAEAVFYAAFRWAAABAAgAZGF0YQAAAAA=';
In this way we don`t produce additional request, the old one is cancelled and our audio element is in clean state (tested in Chrome and FF) :>
This method works:
audio.pause();
audio.currentTime = 0;
But if you don't want to have to write these two lines of code every time you stop an audio you could do one of two things. The second I think is the more appropriate one and I'm not sure why the "gods of javascript standards" have not made this standard.
First method: create a function and pass the audio
function stopAudio(audio) {
audio.pause();
audio.currentTime = 0;
}
//then using it:
stopAudio(audio);
Second method (favoured): extend the Audio class:
Audio.prototype.stop = function() {
this.pause();
this.currentTime = 0;
};
I have this in a javascript file I called "AudioPlus.js" which I include in my html before any script that will be dealing with audio.
Then you can call the stop function on audio objects:
audio.stop();
FINALLY CHROME ISSUE WITH "canplaythrough":
I have not tested this in all browsers but this is a problem I came across in Chrome. If you try to set currentTime on an audio that has a "canplaythrough" event listener attached to it then you will trigger that event again which can lead to undesirable results.
So the solution, similar to all cases when you have attached an event listener that you really want to make sure it is not triggered again, is to remove the event listener after the first call. Something like this:
//note using jquery to attach the event. You can use plain javascript as well of course.
$(audio).on("canplaythrough", function() {
$(this).off("canplaythrough");
// rest of the code ...
});
BONUS:
Note that you can add even more custom methods to the Audio class (or any native javascript class for that matter).
For example if you wanted a "restart" method that restarted the audio it could look something like:
Audio.prototype.restart= function() {
this.pause();
this.currentTime = 0;
this.play();
};
It doesn't work sometimes in chrome,
sound.pause();
sound.currentTime = 0;
just change like that,
sound.currentTime = 0;
sound.pause();
From my own javascript function to toggle Play/Pause - since I'm handling a radio stream, I wanted it to clear the buffer so that the listener does not end up coming out of sync with the radio station.
function playStream() {
var player = document.getElementById('player');
(player.paused == true) ? toggle(0) : toggle(1);
}
function toggle(state) {
var player = document.getElementById('player');
var link = document.getElementById('radio-link');
var src = "http://192.81.248.91:8159/;";
switch(state) {
case 0:
player.src = src;
player.load();
player.play();
link.innerHTML = 'Pause';
player_state = 1;
break;
case 1:
player.pause();
player.currentTime = 0;
player.src = '';
link.innerHTML = 'Play';
player_state = 0;
break;
}
}
Turns out, just clearing the currentTime doesn't cut it under Chrome, needed to clear the source too and load it back in. Hope this helps.
As a side note and because I was recently using the stop method provided in the accepted answer, according to this link:
https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Media_events
by setting currentTime manually one may fire the 'canplaythrough' event on the audio element. In the link it mentions Firefox, but I encountered this event firing after setting currentTime manually on Chrome. So if you have behavior attached to this event you might end up in an audio loop.
shamangeorge wrote:
by setting currentTime manually one may fire the 'canplaythrough' event on the audio element.
This is indeed what will happen, and pausing will also trigger the pause event, both of which make this technique unsuitable for use as a "stop" method. Moreover, setting the src as suggested by zaki will make the player try to load the current page's URL as a media file (and fail) if autoplay is enabled - setting src to null is not allowed; it will always be treated as a URL. Short of destroying the player object there seems to be no good way of providing a "stop" method, so I would suggest just dropping the dedicated stop button and providing pause and skip back buttons instead - a stop button wouldn't really add any functionality.
This approach is "brute force", but it works assuming using jQuery is "allowed". Surround your "player" <audio></audio> tags with a div (here with an id of "plHolder").
<div id="plHolder">
<audio controls id="player">
...
</audio>
<div>
Then this javascript should work:
function stopAudio() {
var savePlayer = $('#plHolder').html(); // Save player code
$('#player').remove(); // Remove player from DOM
$('#FlHolder').html(savePlayer); // Restore it
}
I was looking for something similar due to making an application that could be used to layer sounds with each other for focus. What I ended up doing was - when selecting a sound, create the audio element with Javascript:
const audio = document.createElement('audio') as HTMLAudioElement;
audio.src = getSoundURL(clickedTrackId);
audio.id = `${clickedTrackId}-audio`;
console.log(audio.id);
audio.volume = 20/100;
audio.load();
audio.play();
Then, append child to document to actually surface the audio element
document.body.appendChild(audio);
Finally, when unselecting audio, you can stop and remove the audio element altogether - this will also stop streaming.
const audio = document.getElementById(`${clickedTrackId}-audio`) as HTMLAudioElement;
audio.pause();
audio.remove();
If you have several audio players on your site and you like to pause all of them:
$('audio').each( function() {
$(this)[0].pause();
});
I believe it would be good to check if the audio is playing state and reset the currentTime property.
if (sound.currentTime !== 0 && (sound.currentTime > 0 && sound.currentTime < sound.duration) {
sound.currentTime = 0;
}
sound.play();
for me that code working fine. (IE10+)
var Wmp = document.getElementById("MediaPlayer");
Wmp.controls.stop();
<object classid="clsid:6BF52A52-394A-11D3-B153-00C04F79FAA6"
standby="Loading áudio..." style="width: 100%; height: 170px" id="MediaPlayer">...
Hope this help.
What I like to do is completely remove the control using Angular2 then it's reloaded when the next song has an audio path:
<audio id="audioplayer" *ngIf="song?.audio_path">
Then when I want to unload it in code I do this:
this.song = Object.assign({},this.song,{audio_path: null});
When the next song is assigned, the control gets completely recreated from scratch:
this.song = this.songOnDeck;
The simple way to get around this error is to catch the error.
audioElement.play() returns a promise, so the following code with a .catch() should suffice manage this issue:
function playSound(sound) {
sfx.pause();
sfx.currentTime = 0;
sfx.src = sound;
sfx.play().catch(e => e);
}
Note: You may want to replace the arrow function with an anonymous function for backward compatibility.
In IE 11 I used combined variant:
player.currentTime = 0;
player.pause();
player.currentTime = 0;
Only 2 times repeat prevents IE from continuing loading media stream after pause() and flooding a disk by that.
What's wrong with simply this?
audio.load()
As stated by the spec and on MDN, respectively:
Playback of any previously playing media resource for this element stops.
Calling load() aborts all ongoing operations involving this media element
I'm doing a html5 audio player so I'm trying to use a custom player. I don't want to use the default <audio> tag interface. I want to do my own html/css styles for the player.
My actual code(it works)
if('webkitAudioContext' in window) {
var myAudioContext = new webkitAudioContext();
}
request = new XMLHttpRequest();
request.open('GET', 'http://96.47.236.72:8364/;', true);
request.responseType = 'arraybuffer';
request.addEventListener('load', bufferSound, false);
request.send();
function bufferSound(event) {
var request = event.target;
var source = myAudioContext.createBufferSource();
source.buffer = myAudioContext.createBuffer(request.response, false);
source.connect(myAudioContext.destination);
source.noteOn(0);
}
http://jsfiddle.net/EY54q/1/
Does someone know how can to edit this player style, or do something to use my own html/css code to execute this player?
You can completely make your own style. just forget about the controls option (you can simply use controls and do not need to use controls="controls"). Just create buttons/divs/whatever, style them, and add an eventlistener that controls the audio interface:
html:
<button id="playpause">play
<!--you can style the content with anything!-->
</button>
<audio id="player">
<source src="http://96.47.236.72:8364/;" />
</audio>
JS:
window.player = document.getElementById('player');
document.getElementById('playpause').onclick = function () {
if (player.paused) {
player.play();
this.innerHTML = 'pause';
} else {
player.pause();
this.innerHTML = 'play';
}
}
http://jsfiddle.net/LqM9D/1/
I see you are also using the audio api. Please note that you can't just dump an audio file in a buffer. It needs to be decoded to raw PCM. This takes a lot of time. A really easy method is to create a source node which is linked to the audio element:
var source = context.createMediaElementSoure(player); //we defined player in the first block of code
To make your page a bit more cross-browser capable:
window.AudioContext = window.AudioContext||window.webkitAudioContext;
context = new AudioContext();
Edit:
I think you want to know what else you can do with the element.
You can also make a slider for the timeline, and a volume slider/mute button, although I'd prefer the latter two to do that on a gainnode at the end of a line of filters and such.
Yes. It is possible via "shadow dom". You just need to enable it in your browser and write styles for elements, that will arrive.
As I understend - it is browser specific feature. But for webkit-based styling of "shadow dom" work perfect.
There is not so many info, however this feature already used in full. For example see this question: Why do no user-agents implement the CSS cursor style for video elements
If you enable displaying shadow dom in inspector setting, you will se how it works. (Also there is public list with selectors list - https://gist.github.com/afabbro/3759334)
For other browsers you need check support of working with "shadow dom".
I am working on a project based on jquery animation its animation works fine on desktop (Firefox,chrome,opera,IE) also support HTML 5 audio tag but in Ipad/iphone/ Android safari audio tag doesn’t support.Its works fine on Ipad/iphone/ Android firefox.i have searched it in many forum don’t get desire Result. I have used this function :
function playmusic(file1,file2)
{
document.getElementById('music11').innerHTML='<audio id="music1"><source src="'+file1+'" type="audio/ogg"><source src="'+file2+'" type="audio/mpeg"></audio>';
$("#music1").get(0).play();
}
I have called function like : playmusic(2.ogg','2.mp3');
If I give autoplay in audio tag it works but play method not working and I have to use play method as in my application needs sound in particular event see the link
http://solutions.hariomtech.com/jarmies/
I have also changed my function and give direct audio tag in div and call function the same problem I face as I mentioned above. I need sound play in background without any click.if I use auto play method so it play sound only one time but I need sound multiple time on event.
Try to add an autoplay attribute on the audio tag:
function playmusic(file1, file2) {
document.getElementById('music11').innerHTML='<audio autoplay id="music1"><source src="'+file1+'" type="audio/ogg"><source src="'+file2+'" type="audio/mpeg"></audio>';
}
I would however recommend building a proper element and insert that into the DOM - something like this:
function playmusic(file1, file2) {
var audio = document.createElement('audio');
audio.preload = 'auto';
audio.autoplay = true;
if (audio.canPlayType('audio/ogg')) {
audio.src = file1;
}
else if (audio.canPlayType('audio/mpg')) {
audio.src = file2;
}
document.getElementById('music11').appendChild(audio);
}