How to make HTML5 audio play exactly once on clicking? - html

I'm putting together an online evaluation survey of synthesized speech. Part of the test requires that listeners are only allowed to hear a given WAV file play once (as an experimental control).
I've already figured out how to simply embed an audio clip with controls, so that it can be played several times:
<audio controls>
<source src="http://mypage.com/my_sound.wav" type="audio/wav">
Your browser does not support the audio element
</audio>
Furthermore, I've seen that some HTML questions have attempted to resolve the error of HTML audio playing back only once:
Audio played once only in Google Chrome in html
JavaScript + HTML5: Audio will only play once under certain circumstances
However, my question is how to code this (play HTML audio just once on-click) intentionally? Everything I've seen treats it as a bug to be fixed, rather than an intentional goal.
Cheers!

I've been looking for this one too.
You have a few options.
The key to this stop is the onended event, which as you might expect, triggers when the fat lady stops singing.
<audio id="gilda">
<source url="epic-aria.mp3">
</audio>
var fatLady = document.getElementById('gilda');
fatLady.onended = function() {
fatLady.pause();
fatLady.currentTime = 0; // << only needed if you're cutting off the sound misstep (before the end) and need to return to the beginning - but you might need it. Since you are doing some gaming, I figured that might come up...
};
There is also a jQuery way, which I am currently using. jQuery doesn't use onended, however - it uses ended instead...
var fatLady = $('#gilda');
fatLady.bind('ended', function(event) {
fatLady
.pause()
.currentTime = 0; // << haven't field-tested this yet, but jquery didn't yell at me about it.
});
Let me know if you run into any hiccups.

Related

Is there a way to reduce the size of requests when using <audio> with preload set to metadata

I have an audio element on my page, set up like this:
<audio id="audio" controls preload="metadata">
<source src="/audio/episode.mp3" type="audio/mpeg">
<source src="/audio/episode.ogg" type="audio/ogg">
[Not supported message]
</audio>
I was happy with preload being set to "metadata", because being able to see the length of the file is handy, and it's nice to be able to skip ahead without having to click the play button first.
But then I noticed that in Firefox and IE, this 'metadata' was loading between 20KB and 50KB. Chrome was worse, loading over 1MB. Seems like a lot of wasted bandwidth for a timestamp.
I know that preload is treated by browsers as more what you'd call 'guidelines' than actual rules. I've also found this more in-depth article about the issue.
Are there any methods to reduce the size of these requests?
What I've Tried/Considered
I did try quickly cutting most of the metadata out of a file in a text-editor as a test. This made the requests in Firefox and IE larger, but it leaves me optimistic that there's some way to affect it positively.
I've also considered including the length on the page and setting it using javascript, but those settings appear to be read-only.
Finally, I've been thinking that as a last resort I could generate an empty audio file that is the exact same length, compress it down to as small a file as is possible, and then when the user interacts with it, swap it out for the real one*. At this point I realized I should probably get some help...
*EDIT: I ended up trying this out! It's not going to work for my site, but at the very least its interesting. I included it as an answer below.
This solution is hacky, but it does have a measurable effect. By loading the page initially with a silent doppelganger, and then switching it out for the real file when audio starts playing, I managed to save quite a bit on the initial page load.
Here are my average results with a 10 minute 20 second long mp3. Before and after:
IE: 16KB — Firefox: 43KB — Chrome: 1.4MB
IE: 15KB — Firefox: 08KB — Chrome: 34KB
On Chrome the saving are 1.36MB, more data than the full text of Crime and Punishment. Here's the code:
HTML
<audio id="audio" controls preload="metadata">
<source src="/silence.mp3" type="audio/mpeg">
</audio>
Javascript
var audio = document.getElementById("audio");
var time, volume, muted;
audio.addEventListener("playing", loadAudio, false);
function loadAudio(e) {
time = audio.currentTime;
volume = audio.volume;
muted = audio.muted;
audio.innerHTML = "<source src=\"/episode.mp3\" type=\"audio/mpeg\">";
audio.setAttribute("preload", "auto");
audio.load();
audio.addEventListener("canplaythrough", playAudio, false);
e.target.removeEventListener(e.type, arguments.callee);
}
function playAudio(e) {
audio.currentTime = time;
audio.volume = volume;
audio.muted = muted;
audio.play();
e.target.removeEventListener(e.type, arguments.callee);
}
This was just written as a test; it can be improved quite a bit.
There are enough drawbacks to this method that I don't think I'll be using it. These include:
You have to generate a silent copy of every single audio file you'd like to load this way.
The users that actually play the audio will be requesting both files.
It takes longer for the audio to start playing.
The controls clearly switch to 0:00 and back again, especially when using high latency internet like mine.
That said, hopefully this method works for somebody out there! At the very least it was fun to play around with.

Play video files online sequentially without delay/buffering between videos

Is it possible to play video online that's made of two or more video files?
Since my original post wasn't clear enough, here's expanded explanation and question.
My site is hosted on Linux/Apache/PHP server. I have video files in FLV/F4V format. I can also convert them to other available formats if necessary. All videos have same aspect ratio and other parameters.
What I want is to build (or use if exist) online video player that plays video composed of multiple video files concatenated together in real-time, i.e. when user clicks to see a video.
For example, visitor comes to my site and sees video titled "Welcome" available to play. When he/she clicks to play that video, I take video files "Opening.f4v", "Welcome.f4v" and "Ending.f4v" and join/merge/concatenate them one after another to create one continuous video on the fly.
Resulting video looks like one video, with no visual clues, lags or even smallest observable delay between video parts. Basically what is done is some form of on-the-fly editing or pre-editing, and user sees the result. This resulting video is not saved on the server, it's just composed and played that way real-time.
Also, if possible, user shouldn't be made to wait for this merging to be over before he/she sees resulting video, but to be able to get first part of the video playing immediately, while merging is done simultaneously.
Is this possible with flash/actionscript, ffmpeg, html5 or some other online technology? I don't need explanation how it's possible, just a nod that it's possible and some links to further investigate.
Also, if one option is to use flash, what are alternatives for making this work when site is visited from iphone/ipad?
An approach that will work on some browsers currently, and on most browsers going forwards is to use the HTML5 Video Media Source Extension mechanism.
This essentially allows you replace a static 'src' file for a video in your HTML5 page, with a dynamic src buffer which you can then fill any way you want using your own Javascript code.
So you can write code to pre-buffer the second video when you get towards the end of the first video and then immediately start adding packets from the second video to the src right after the last packet for the first video.
In very high level terms this looks like:
Your HTML to insert the video where you want it in your page:
.
.
.
<div>
<video id="yourVideo1" controls="" autoplay="" width="320" height="240"></video>
</div>
.
.
.
Your Javascript to provide the source for your video:
//Get the video element
var videoElement = document.getElementById('yourVideo1');
//Create a 'MediaSource' and associate it with this video
var mediaSource = new MediaSource();
video.src = window.URL.createObjectURL(mediaSource);
//Add a listener to the MediaSource object to check for
//the video been opened. In this function you can add your
//code to get the get your videos from the servers and add
//'chunks' to the media source buffer
mediaSource.addEventListener('sourceopen', function(e) {
//Set the format of the source video
var mediaSourceBuffer = mediaSource.addSourceBuffer('video/webm; codecs="vorbis,vp8"');
//Get your video from the web
while (not the end of your video playlist) {
...
//Stream video from server
...
//Add packets received to the media source bufer
mediaSourceBuffer.appendBuffer(receivedVideoPackets);
//If near end of video start fetching next video to
//avoid buffering delay
...
//If end of video go to next video in playlist
...
}
}, false);
Look at the HTML5 Rocks demo below to see this in action (for a slightly different usecase).
Given how tricky video manipulation is and the multitude of formats etc, it would be much easier for you if one of the established video players provided the functionality out of the box so I would still try their forums as mentioned in the comment, but at least you know it is technically possible.
The MSE spec is available here:
http://w3c.github.io/media-source/
And a good intro blog and demo is here (make sure your browser supports MSE - latest version of Chrome does):
http://updates.html5rocks.com/2011/11/Stream-video-using-the-MediaSource-API
You can find latest browser support here:
http://www.jwplayer.com/html5/mediasource/
Use two video elements, first visible and second display:none for buffering.
After first video playing, check currentPosition and currentDuration,
specify second video preloader prepare visible video player's buffer data.
First video element's SRC could be specified anytime for seamless playing.

Simple Background Music for website

I have been designing a website recently and I had the idea to try implementing some background music.
I went about this by simply having the music play through a video looper
<embed name="Example Song Here"
src="http://www.infinitelooper.com/?v=GGtcJCzB9cU&p=n"
loop="True"
hidden="true"
autostart="true">
</embed
That works perfectly, the problem comes that users will probably want to stop the music, so I added a "Stop Music" button
FORM METHOD="LINK" ACTION="WebsiteURL">
<INPUT TYPE="submit" VALUE="Stop Music">
</FORM>
Adds the button fine, but as you can see it doesn't do anything but redirect back to the site, I've been looking for that extra line I need to make the button stop the music above.
Yes, I'm a total novice.
This code uses Html5. if you can use html5 this works fine.
<audio id="myAudio"
<source src="http://media.w3.org/2010/07/bunny/04-Death_Becomes_Fur.mp4"
type='audio/mp4'>
<source src="http://media.w3.org/2010/07/bunny/04-Death_Becomes_Fur.oga"
type='audio/ogg; codecs=vorbis'>
Your user agent does not support the HTML5 Audio element.
</audio>
<button type="button" onclick="aud_play_pause()">Play/Pause</button>
<script>
function aud_play_pause() {
var myAudio = document.getElementById("myAudio");
if (myAudio.paused) {
myAudio.play();
} else {
myAudio.pause();
}
}
</script>
The embed element as such is conforming in the current HTML specification (HTML5), but it isn’t what it used to be. The old, nonstandard embed element had various attributes that controlled the presentation, but they are not included in the specification and support to them varies greatly and is diminishing. Besides, your example does not actually embed sound directly. Instead, it embeds an HTML element, which has embedded sound its own way. Normally you cannot control what happens on a page that you embed from another server.
There is no HTML way to control playing in an embed element, since it is expected to be implemented with a plugin. Note that modern browsers might lack any plugins for the purpose by default or might have such plugins disabled. So embed really isn’t what it used to be.
Others have suggested, for good reasons, that you don’t use background sound and that if you use, implement it with the audio element. (You could have an embed element inside the audio element, as fallback content for browsers that do not recognize audio markup at all.) However, audio only applies to direct embedding of sound, as opposite to embedding a page that has background sound.
In your case, you can create your own stop button using JavaScript. You can make a click on the button to simply remove the embed element. Of course, it would then simply terminate the sound. Removing an element is a bit indirect in JavaScript: you tell its parent to kick that child out.
<embed id=bgs name="Example Song Here" controls=stopbutton
src="http://www.infinitelooper.com/?v=GGtcJCzB9cU&p=n">
</embed>
<button onclick=
"var bgs = document.getElementById('bgs'); bgs.parentNode.removeChild(bgs);
this.parentNode.removeChild(this)">
Stop background sound</button>

Embedding a media player in a website using HTML [closed]

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 4 years ago.
Improve this question
What I want to do is to embed music files within a website (Have something a'la little mp3 player on the site). I want the audience to be able to play, stop etc the songs by using custom made controllers.
How do I code those custom made buttons so that they all work fine?
You can use plenty of things.
If you're a standards junkie, you can use the HTML5 <audio> tag:
Here is the official W3C specification for the audio tag.
Usage:
<audio controls>
<source src="http://media.w3.org/2010/07/bunny/04-Death_Becomes_Fur.mp4"
type='audio/mp4'>
<!-- The next two lines are only executed if the browser doesn't support MP4 files -->
<source src="http://media.w3.org/2010/07/bunny/04-Death_Becomes_Fur.oga"
type='audio/ogg; codecs=vorbis'>
<!-- The next line will only be executed if the browser doesn't support the <audio> tag-->
<p>Your user agent does not support the HTML5 Audio element.</p>
</audio>
jsFiddle here.
Or, if you want to support older browsers, you can use many of the free audio flash players available. Such as:
Dewplayer
MP3 Player (boring name... right? :) )
Website Music Player (even more boring... right?)
Zanorg Player
Note: I'm not sure which are the best ones, as I have never used one (yet).
UPDATE: As mentioned in another answer's comment, you are using XHTML 1.0 Transitional. You might be able to get <audio> to work with some hack.
UPDATE 2: I just remembered another way to do play audio. This will work in XHTML!!! This is fully standards-compliant.
You use this JavaScript:
var aud = document.createElement("iframe");
aud.setAttribute('src', "http://yoursite.com/youraudio.mp4"); // replace with actual file path
aud.setAttribute('width', '1px');
aud.setAttribute('height', '1px');
aud.setAttribute('scrolling', 'no');
aud.style.border = "0px";
document.body.appendChild(aud);
This is my answer to another question.
UPDATE 3: To customise the controls, you can use something like this.
Definitely the HTML5 element is the way to go. There's at least basic support for it in the most recent versions of almost all browsers:
http://caniuse.com/#feat=audio
And it allows to specify what to do when the element is not supported by the browser. For example you could add a link to a file by doing:
<audio controls src="intro.mp3">
Introduction to HTML5 (10:12) - MP3 - 3.2MB
</audio>
You can find this examples and more information about the audio element in the following link:
http://hacks.mozilla.org/2012/04/enhanceyourhtml5appwithaudio/
Finally, the good news are that mozilla's April's dev Derby is about this element so that's probably going to provide loads of great examples of how to make the most out of this element:
http://hacks.mozilla.org/2012/04/april-dev-derby-show-us-what-you-can-do-with-html5-audio/
Here is a solution to make an accessible audio player with valid xHTML and non-intrusive javascript thanks to W3C Web Audio API :
What to do :
If the browser is able to read, then we display controls
If the browser is not able to read, we just render a link to the file
First of all, we check if the browser implements Web Audio API:
if (typeof Audio === 'undefined') {
// abort
}
Then we instanciate an Audio object:
var player = new Audio('mysong.ogg');
Then we can check if the browser is able to decode this type of file :
if(!player.canPlayType('audio/ogg')) {
// abort
}
Or even if it can play the codec :
if(!player.canPlayType('audio/ogg; codecs="vorbis"')) {
// abort
}
Then we can use player.play(), player.pause();
I have done a tiny JQuery plugin that I called nanodio to test this.
You can check how it works on my demo page (sorry, but text is in french :p )
Just click on a link to play, and click again to pause. If the browser can read it natively, it will. If it can't, it should download the file.
This is just a little example, but you can improve it to use any element of your page as a control button or generate ones on the fly with javascript... Whatever you want.
I found the that either IE or Chrome choked on most of these, or they required external libraries. I just wanted to play an MP3, and I found the page http://www.w3schools.com/html/html_sounds.asp very helpful.
<audio controls>
<source src="horse.mp3" type="audio/mpeg">
<embed height="50" width="100" src="horse.mp3">
</audio>
Worked for me in the browsers I tried, but I didn't have some of the old ones around at this time.
<html>
<head>
<H1>
Automatically play music files on your website when a page loads
</H1>
</head>
<body>
<embed src="YourMusic.mp3" autostart="true" loop="true" width="2" height="0">
</embed>
</body>
</html>
If you are using HTML 5, there is the <audio> element.
On MDN:
The audio element is used to embed sound content in an HTML or XHTML document. The audio element was added as part of HTML5.
Update:
In order to play audio in the browser in HTML versions before 5 (including XHTML), you need to use one of the many flash audio players.

HTML5 Multiple Video Display - Hover Over to Play

Okay so I have followed a good tutorial regarding embedding videos via HTML5 video tag, which can be found here. Basically the idea is that on hover the video plays, on hover out it stops playing.
Well, I've been trying to include multiple videos on one page (all the same video, mind you) in hopes that I could create a sort of interactive multi-tiled board of sorts. In other words, you hover over each video, it creates varying images based on where in each video you end up, etc.
Whatever, the question I am asking is: based on this tutorial that I've followed, what is the best way to create multiple, tiled videos? I'll paste the code I've been working with. The problem I'm having is that if I create multiple javascript functions, it shows only the video of the last function I've created, rather than all videos.
I hope this makes sense. Here is the link to what I've been working on so far. NOTE: the video takes a while to load, so until then it will play the sound but no image.
Thanks in advance for any help!
Here is the solution I found:
The only warning I give you is to set the videos to preload="none" because if they all load it will be nightmare on your bandwidth. I had to switch mine and now I am looking for a solution to let people know a video is loading.
var vid = document.getElementsByTagName("video");
[].forEach.call(vid, function (item) {
item.addEventListener('mouseover', hoverVideo, false);
item.addEventListener('mouseout', hideVideo, false);
});
function hoverVideo(e)
{
this.play();
}
function hideVideo(e)
{
this.pause();
}
Here is where I got the answer: http://www.dreamincode.net/forums/topic/281583-video-plays-on-mouse-over-but-not-with-multiple-videos/
For anyone that's looking to achieve this using jQuery, here's a solution that I use for dynamically loaded content:
//play video on hover
$(document).on('mouseover', 'video', function() {
$(this).get(0).play();
});
//pause video on mouse leave
$(document).on('mouseleave', 'video', function() {
$(this).get(0).pause();
});
This can be used for a page with 1 - N videos, and only the hovered video will play at each time, while each will pause on the current frame on mouseleave.
Here's an example of it in action: http://jsfiddle.net/cc7w0pda/
Try this, it's easy to understand
<!DOCTYPE html>
<html>
<video id="vv" width="500" height="500" controls onmouseout="this.pause()" onmouseover="this.play()">
<source src="xx.mp4">
Your browser does not support this file
</video>
</html>