Audio in a tool tip/hover? - javascript

I would like to include audio that will automatically play when the user scrolls over. I have not found a tooltip that will do this. Does anyone know of a way to accomplish this?
(Note: The user will be warned about the audio before they have access to the page.)
UPDATE
I got this working thanks to Bakudan - хан ювиги. But is there a flash fall back available using Bakudan - хан ювиги's method? Thanks!
UPDATE 2
Using Bakudan - хан ювиги's recommended method for adding a flash fallback using swfobject leaves me a bit confused. My lack of javascript knowledge is where I get lost. Here is the code I am using for my audio:
<script>
// Mouseover/ Click sound effect- by JavaScript Kit (www.javascriptkit.com)
// Visit JavaScript Kit at http://www.javascriptkit.com/ for full source code
var html5_audiotypes={ //define list of audio file extensions
"mp3": "audio/mpeg",
"ogg": "audio/ogg",
}
function createsoundbite(sound){
var html5audio=document.createElement('audio')
if (html5audio.canPlayType){ //check support for HTML5 audio
for (var i=0; i<arguments.length; i++){
var sourceel=document.createElement('source')
sourceel.setAttribute('src', arguments[i])
if (arguments[i].match(/\.(\w+)$/i))
sourceel.setAttribute('type', html5_audiotypes[RegExp.$1])
html5audio.appendChild(sourceel)
}
html5audio.load()
html5audio.playclip=function(){
html5audio.pause()
html5audio.currentTime=0
html5audio.play()
}
return html5audio
}
else{
return {playclip:function(){throw new Error(
"Your browser doesn't support HTML5 audio unfortunately")}}
}
}
//Initialize sound clips with 1 fallback file each:
var mouseoversound=createsoundbite(
"/messages4u/2011/images/october/laugh.ogg",
"/messages4u/2011/images/october/laugh.mp3")
</script>
I changed the else to the flash instead of the error message. How do I change this using swfobject to play the flash audio file? I am a bit lost by that.
Thanks for the help!

This is a good start. I`ve made a demo. If the audio is a little bit longer, add stopclip function to the createsoundbite function and then add it to the .mouseleave.
Edit:
To add flash change the else part. I'm very familiar with flash, but basically use one of the following:
create object - "document.createElement("object");... etc"
or which I think is better use swfobject

Here's a version that plays sound in older browsers and does not require flash:
var sound = document.createElement("audio");
if (!("src" in sound)) {
sound = document.createElement("bgsound");
}
document.body.appendChild(sound);
function playSound(src) {
sound.src = src;
sound.play && sound.play();
}
...
playSound("/sounds/something.mp3");
Edit: Here's a version that uses .hover() to play the sound when the mouse hovers over your element:
$(function) {
var sound = document.createElement("audio");
if (!("src" in sound)) {
sound = document.createElement("bgsound");
}
document.body.appendChild(sound);
$(".playable").hover(function() {
sound.src = this.soundFile;
sound.play && sound.play();
}, function() {
sound.src = "";
});
});
Set up your elements that you want to play a sound with a class of "playable" and custom attribute "soundFile" containing the source url for the sound file:
<span class="playable" soundFile="/sounds/something.mp3">Something</span>
<span class="playable" soundFile="/sounds/somethingElse.mp3">Something else</span>

soundmanager2

Related

Autoplay doesn't work with my music playlist [duplicate]

This question already has answers here:
How to make audio autoplay on chrome
(23 answers)
Closed 2 years ago.
I want to play a music playlist on my web-page in the background, I'm using chrome I don't want the console and I want autoplay but, though I write autoplay, the audio is starting only with the play button of the console. That's what I write in the HTML:
<div id="music_list">
<audio controls autoplay></audio>
</div>
And in the Javascript
(function () {
// Playlist array
var files = [
"ms4/14_1.30.mp3",
"ms4/20_20.mp3",
"ms4/21_34.mp3"
];
// Current index of the files array
var i = 0;
// Get the audio element
var music_player = document.querySelector("#music_list audio");
// function for moving to next audio file
function next() {
// Check for last audio file in the playlist
if (i === files.length - 1) {
i = 0;
} else {
i++;
}
// Change the audio element source
music_player.src = files[i];
}
// Check if the player is slected
if (music_player === null) {
throw "Playlist Player does not exists ...";
} else {
// Start the player
music_player.src = files[i];
// Listen for the music ended event, to play the next audio file
music_player.addEventListener('ended', next, false)
}
})();
How can I fix that? I'm really new in HTML and JS and I'm stuck in this problem.
I got this problem 1 year ago. The problem is of the Internet Browser you using at, for example, in Google Chrome controls autoplay doesn't work, the problem is about the permission, security and privacity of the users.
I think there is some way to make it work in any Internet Browser but, "controls autoplay" doesn't work, just in some Internet Explorers.
Bug players consider autoplay a bad thing because ads. At the end you will be forced to click to play. Nowadays you can try adding muted property to the audio element alongside with autoplay, and remove it after ading the first src
This depends upon your browsers
Run your code in different browsers
and also try this javascript function
var mp3 = document.getElementByTagName("audio");
mp3.autoplay = true;
mp3.load();

Create Seamless Loop of Audio - Web

I want to create a seamless loop of an audio file. But in all approaches I used so far, there was a noticeable gap between end & start.
This is what I tried so far:
First approach was to use the audio in the HTML and it loops but there is still a noticeable delay when going from the end of the track to the beginning.
<audio loop autoplay>
<source src="audio.mp3" type="audio/mpeg">
<audio>
Then I tried it from JavaScript with the same result:
let myAudio = new Audio(file);
myAudio.loop = true;
myAudio.play();
After that I tried this (according to this answer)
myAudio.addEventListener(
'timeupdate',
function() {
var buffer = .44;
if (this.currentTime > this.duration - buffer) {
this.currentTime = 0;
this.play();
}
},
false
);
I played around with the buffer but I only got it to reduce the gap but not leave it out entirely.
I turned to the library SeamlessLoop (GitHub) and got it to work to loop seamlessly in Chromium browsers (but not in the latest Safari. Didn't test in other browsers). Code I used for that:
let loop = new SeamlessLoop();
// My File is 58 Seconds long. Btw there aren't any gaps in the file.
loop.addUri(file, 58000, 'sound1');
loop.callback(soundsLoaded);
function soundsLoaded() {
let n = 1;
loop.start('sound' + n);
}
EDIT: I tried another approach: Looping it trough two different audio elements:
var current_player = "a";
var player_a = document.createElement("audio");
var player_b = document.createElement("audio");
player_a.src = "sounds/back_music.ogg";
player_b.src = player_a.src;
function loopIt(){
var player = null;
if(current_player == "a"){
player = player_b;
current_player = "b";
}
else{
player = player_a;
current_player = "a";
}
player.play();
/*
3104.897 is the length of the audio clip in milliseconds.
Received from player.duration.
This is a different file than the first one
*/
setTimeout(loopIt, 3104.897);
}
loopIt();
But as milliseconds in browsers are not consistent or granular enough this doesn't work too well but it does work much better than the normal "loop" property of the audio.
Can anyone guide me into the right direction to loop the audio seamlessly?
You can use the Web Audio API instead. There are a couple of caveats with this, but it will allow you to loop accurately down to the single sample level.
The caveats are that you have to load the entire file into memory. This may not be practical with large files. If the files are only a few seconds it should however not be any problem.
The second is that you have to write control buttons manually (if needed) as the API has a low-level approach. This means play, pause/stop, mute, volume etc. Scanning and possibly pausing can be a challenge of their own.
And lastly, not all browsers support Web Audio API - in this case you will have to fallback to the regular Audio API or even Flash, but if your target is modern browsers this should not be a major problem nowadays.
Example
This will load a 4 bar drum-loop and play without any gap when looped. The main steps are:
It loads the audio from a CORS enabled source (this is important, either use the same domain as your page or set up the external server to allow for cross-origin usage as Dropbox does for us in this example).
AudioContext then decodes the loaded file
The decoded file is used for the source node
The source node is connected to an output
Looping is enabled and the buffer is played from memory.
var actx = new (AudioContext || webkitAudioContext)(),
src = "https://dl.dropboxusercontent.com/s/fdcf2lwsa748qav/drum44.wav",
audioData, srcNode; // global so we can access them from handlers
// Load some audio (CORS need to be allowed or we won't be able to decode the data)
fetch(src, {mode: "cors"}).then(function(resp) {return resp.arrayBuffer()}).then(decode);
// Decode the audio file, then start the show
function decode(buffer) {
actx.decodeAudioData(buffer, playLoop);
}
// Sets up a new source node as needed as stopping will render current invalid
function playLoop(abuffer) {
if (!audioData) audioData = abuffer; // create a reference for control buttons
srcNode = actx.createBufferSource(); // create audio source
srcNode.buffer = abuffer; // use decoded buffer
srcNode.connect(actx.destination); // create output
srcNode.loop = true; // takes care of perfect looping
srcNode.start(); // play...
}
// Simple example control
document.querySelector("button").onclick = function() {
if (srcNode) {
srcNode.stop();
srcNode = null;
this.innerText = "Play";
} else {
playLoop(audioData);
this.innerText = "Stop";
}
};
<button>Stop</button>
There is a very simple solution for that, just use loopify it makes use of the html5 web audio api and works perfectly well with many formats, not only wav as the dev says.
<script src="loopify.js" type="text/javascript"></script>
<script>
loopify("yourfile.mp3|ogg|webm|flac",ready);
function ready(err,loop){
if (err) {
console.warn(err);
}
loop.play();
}
</script>
This will automatically play the file, if you want to have start and stop buttons for example take a look at his demo

HTML 5 audio .play() delay on mobile

I just built a real-time app using socket.io where a "master" user can trigger sounds on receiving devices (desktop browsers, mobile browsers). That master user sees a list of sound files, and can click "Play" on a sound file.
The audio playback is instant on browsers. On mobiles however, there is a 0.5-2 seconds delay (my Nexus 4 and iPhone 5 about 1 second and iPhone 3GS 1-2 seconds).
I've tried several things to optimize the audio playback to make it faster on mobiles. Right now (at the best "phase" of its optimization I'd say), I combine all the mp3's together in one audio file (it creates .mp3, .ogg, and .mp4 files). I need ideas on how I can further fix / improve this issue. The bottleneck really seems to be in the hmtl 5 audio methods such as .play().
On the receivers I use as such:
<audio id="audioFile" preload="auto">
<source src="/output.m4a" type="audio/mp4"/>
<source src="/output.mp3" type="audio/mpeg"/>
<source src="/output.ogg" type="audio/ogg"/>
<p>Your browser does not support HTML5 audio.</p>
</audio>
In my JS:
var audioFile = document.getElementById('audioFile');
// Little hack for mobile, as only a user generated click will enable us to play the sounds
$('#prepareAudioBtn').on('click', function () {
$(this).hide();
audioFile.play();
audioFile.pause();
audioFile.currentTime = 0;
});
// Master user triggered a sound sprite to play
socket.on('playAudio', function (audioClip) {
if (audioFile.paused)
audioFile.play();
audioFile.currentTime = audioClip.startTime;
// checks every 750ms to pause the clip if the endTime has been reached.
// There is a second of "silence" between each sound sprite so the pause is sure to happen at a correct time.
timeListener(audioClip.endTime);
});
function timeListener(clipEndTime) {
this.clear = function () {
clearInterval(interval);
interval = null;
};
if (interval !== null) {
this.clear();
}
interval = setInterval(function () {
if (audioFile.currentTime >= clipEndTime) {
audioFile.pause();
this.clear();
}
}, 750);
}
Also considered blob for each sound but some sounds can go for minutes so that's why I resorted to combining all sounds together for 1 big audio file (better than several audio tags on the page for each clip)
Instead of pausing / playing, I simply set the volume to 0 when it shouldn't be playing, and back to 1 when it should be playing. The Audio methods currentTime and volume don't slow the audio playback at all even on an iPhone 3GS.
I also added the 'loop' attribute to the audio element so it never has to be .play()'ed again.
It was fruitful to combine all mp3 sounds together because this solutions can work because of that.
Edit: audioElement.muted = true or audioElement.muted = false makes more sense.
Edit2: Can't control volume on user's behalf on iOS so I must pause() and play() the audio element as opposed to just muting and unmuting it.
Your setup is working well on desktop because of the preload attribute.
Unfortunately, here's Apple on the subject of preload:
Safari on iOS never preloads.
And here's MDN:
Note: This value is often ignored on mobile platforms.
The mobile platforms are making a tradeoff to save battery and data usage to only load media when it's actually interacted with by the user or programmatically played (autoplay generally doesn't work for similar reasons).
I think the best you're going to do is combining your tracks together, as you said you've done, so you don't have to pay the initial load-up "cost" as much.
I was having the same delay issue when testing in mobile. I found out what some HTML 5 games are using for audio since games demand very low latencies. Some are using SoundJS. I recommend you try that library out.
You can find a speed comparison between using the HTML Audio tag vs using SoundJS here:
http://www.nickfrazier.com/javascript/audio/ui/2016/08/14/js-sound-libraries.html
(test in mobile to hear the difference)
From my tests SoundJS is much faster.
In fact, it's Good enough to be used in a game, or for sound feedback in a user interface.
Old question but here is my solution using one of the answer above:
const el = document.createElement("audio");
el.muted = true;
el.loop = true;
const source = document.createElement("source");
source.src = lineSe;
source.type = "audio/mpeg";
el.appendChild(source);
// need to call this function after user first interaction, or safari won't do it.
function firstPlay() {
el.play();
}
let timeout = null;
function play() {
// In case user press the button too fast, cancel last timeout
if (lineSeTimeout) {
clearTimeout(timeout);
}
// Back to beginning
el.currentTime = 0;
// unmute
el.muted = false;
// set to mute after the audio finish. In my case 500ms later
// onended event won't work because loop=tue
timeout = setTimeout(() => {
// mute audio again
el.muted = true;
}, 500);
}

Play music at the end of function with javascript

I would like to start a music file by passing it to a function and then play it automatically after the another function has completed execution. Once the function finishes I want to play "done.mp3", and on an error play "error.wav" etc...
I just want to write down easy pure JavaScript function to do so. Call it wherever and provide an .mp3, or .wav music file... and it plays it directly.
My work will be used within an ASP.NET project.
I want to be able to work it in Internet Explorer, Firefox, Chrome.
Create an Audio element and trigger it from your function like this:
var audio = document.createElement('audio');
audio.src = 'link/to/audio/file.ogg|mp3'; //mp3 not supported in current FF
audio.addEventListener('canplaythrough', function() {
audio.play();
}, false);
Or pre-load the audio - when you get to the end of your function call audio.play().
if (audio.attr('readyState')) audio.play();
If no readyState, just use a setTimeout to re-try. Rememeber to check for errors (in case file does not exist, unsupported codec etc.).
According to multiple of search beside other think I found a solution unfortunately it's not working for IE.
I can just add tool inside div this one works for Firefox, and chrome:
document.getElementById("TestDiv").innerHTML = "<audio autoplay='autoplay' ID= 'audioPlayerElement' src=" + MusicLink + " ></audio>";

Proper onload for <audio>

I've been looking around and I'm starting to worry that this isn't possible.
Is there any way to make a standard <audio> tag with fallbacks...
<audio>
<source src='song.ogg' type='audio/ogg'></source>
<source src='song.mp3' type='audio/mp3'></source>
</audio>
...have an onload event. I've looked around and all I could find are some hacks that may or may not work (they don't for me on Chrome) and the canplaythrough event.
The reason I want this is because I am making a presentation that has lots of audio clips to play at certain points. I don't want the presentation to start until all of the audio is loaded (otherwise things could get out of sync). I want the clips to be loaded 1 at a time so that I can create a sort of loading bar. I really don't want to resort to using Flash sound because this is supposed to demonstrate pure web technologies.
So basically I've got this one loadAudio function that cycles through the array of audio files to be loaded audioQueue. loadAudio is called once and then it calls itself until all the files are loaded.
Problem is I haven't found the correct event to trigger loading the next file.
loadAudio = function(index)
{
mer = audioQueue[index];
var ob = "<audio id='" + mer + "'><source src='resources/sounds/" + mer + ".ogg' type='audio/ogg'></source><source src='resources/sounds/" + mer + ".mp3' type='audio/mp3'></source></audio>";
$("#audios").append(ob);
$("#" + mer).get(0).addEventListener('A WORKING EVENT RIGHT HERE WOULD BE NICE', function() { alert("loaded");
if (index + 1 < audioQueue) { loadAudio(index + 1); } }, false);
}
So. Any chance for a proper audio onload? I'm basically willing to do anything as long as it's still all HTML and Javascript.
You can use the loadeddata-MediaEvent. For example you can put all of your audio files in an Array and do something like:
var files = ['a.mp3', 'b.mp3'];
$.each(files, function() {
$(new Audio())
.on('loadeddata', function() {
var i = files.indexOf(this);
files.splice(i, 1);
if (!files.length) {
alert('Preloading done!');
}
})
.attr('src', this);
});
EDIT: this would a little more modern approach as of 2016:
var files = ['a.mp3','b.mp3'];
Promise
.all(files.map(function(file) {
return new Promise(function(resolve) {
var tmp = new Audio();
tmp.src = file;
tmp.addEventListener('loadeddata', resolve);
});
})).then(function() {
alert('Preloading done!');
});
I did a small PONG-game with WebGL and some audio-tags for the sounds. I borrowed the audio-implementation from Opera's Emberwind HTML5 implementation: https://github.com/operasoftware/Emberwind/blob/master/src/Audio.js
Their solution worked fine for me (Chrome, Opera and Firefox). Maybe it could be of interest to you? They have some code that will try to find a playable format from line 22 and below.

Categories

Resources