How is a partial audio file played? - javascript

How would I play an audio file in javascript that has been spliced into two byte arrays and loaded separately from a server at different times? I want to load the first half of an mp3 file, then, while the mp3 is playing, load the second half and seamlessly continue playing through the whole file.

You can use the canplaythrough and ended events to, play the first audio while loading the second, then play the second after loading. Something like this:
var canPlayAudio2 = false;
var audio1Ended = false;
var audio = document.createElement('audio');
audio.src = "your_audio_source";
audio.addEventListener('canplaythrough', function() {
//after first audio loads, start loading second audio
var audio2 = document.createElement('audio');
audio2.src = "your_audio2_source";
audio2.addEventListener('canplaythrough', function() {
canPlayAudio2 = true;
if (audio1Ended) {
audio2.play();
}
});
//play the first audio, play second audio if availible once finished
audio.play();
audio.addEventListener('ended', function() {
audio1Ended = true;
if (canPlayAudio2) {
audio2.play();
}
});
});

While the first part is playing, create another audio tag to pre-load the second half, but do not play it.
<audio src="the second half.mp3” preload="auto"></audio>
When the first audio trigger the ended event, change its URL to the second half.
The browser will get the file from cache and starts to play it immediately.
Sorry for my poor English, hoping this helps.

Related

Iframe Not Showing Random Videos

I am working on a script so that it fetches a random video and continuously keeps playing random videos back to back once the previous video is finished playing. It worked when I played the videos as mp4s in the video element, but when I rewrote the script to play them as embedded videos in an iframe, nothing shows up at all.
I just cannot seem to make it work. Any help would be greatly appreciated.
Thanks in advance.
<iframe class="frame" src="" width="640" height="360"></iframe>
<script>
var lastVideo = null;
var selection = null;
var player = document.getElementsByClassName("frame")[0]; // Get video element
var playlist = ["https://www.youtube.com/embed/qXYb8R3_B0k", "https://www.youtube.com/embed/Gi1P6UFTioQ", "https://www.youtube.com/embed/l_pR5obOwss"]; // List of videos
player.autoplay = true;
player.addEventListener("ended", getRandomUrl); // Run when video ends
function getRandomUrl(player) {
while (selection == lastVideo) { // Repeat until different video is selected
selection = Math.floor(Math.random() * playlist.length);
}
lastVideo = selection; // Remember last video
player.src = playlist[selection]; // Location of new video
}
getRandomUrl(player); // Select first video
player.play(); // Start video
</script>
I would guess that your eventListener for "ended" never triggers because a video is never started in the first place.
The solution in this case would be set a random video to the src attribute as the default and then the eventListener takes care of the rest.

Audio is playing after a delay on IPad

I am trying to play two audio at the same time. One audio is using to provide background music and another one is using to provide speech. I am playing audio on click . After click, audio plays simultaneously and immediately on desktop but on IPad Air and Ipad pro audios play after a delay. I am not getting what is wrong with my code ?
<script>
var audio1 = new Audio();
var audio2 = new Audio();
$(document).ready(function(){
$(".playAudio").on("click touchstart" , function(){
audio1.src= "media/audio/music.mp3";
audio2.src= "media/audio/fullIntro.mp3";
audio1.play();
audio2.play();
});
});
</script>
HTML
<div class="playAudio"><span id="span1">Play Audio</span></div>
Please help !
Thanks !
I highly suspect that your problem might be that both files aren't finished downloading at the same time. Hence the delay between the two audio files.
My suggestion would be to wait for every file to be downloaded before proceeding. You can do so with a little bit of Javascript :
Here's the code
$(window).on("load", function() {
$(".playAudio").on("click touchstart" , function()
{
audio1.src= "media/audio/music.mp3";
audio2.src= "media/audio/fullIntro.mp3";
audio1.play();
audio2.play();
});
});
That should do the trick.
Credits : I found another question that may help you as well
Official way to ask jQuery wait for all images to load before executing something

Stopping an audio in Javascript

I played an audio with the following code:
var audio;
function playAudio(y){
audio = new Audio(y);
audio.play();
}
Now I want to stop this audio from another function. I cannot find any audio.stop(). Please note I want to stop not pause.

How to keep synchronized video element especially after pause/play event in (html5/javascript)

I try to have in a html5 webpage project three elements fully synchronized. To ensure no shift due to video download, I put the attribute preload="auto" to the video elements.
My script is as follows:
var run = document.getElementById("run"); //run is a button element
var vid = document.getElementById("video1"); // the first video element
function PlayVideo() {
if (vid.paused) {
vid.play();
run.textContent = "||";
} else {
vid.pause();
run.textContent = ">";
}
} // The PlayVideo() function is called onclick on the run button
$('#video1').on('play', ambiance = function(){
document.getElementById("video2").play();
document.getElementById("video3").play();
});
$('#video1').on('pause', ambiance = function(){
document.getElementById("video2").pause();
document.getElementById("video3").pause();
});
When using this piece of script after waiting few seconds to a complete load of the video files, the run button plays correctly the first video and the two others start synchronized. But when I pause the run button pushing a second time on it, only the first video stops and the two others continue to be played during 2 or 3 seconds (both of them synchronized but not with the first one).
Could you help me?
Is there an other way (more elegant) to play synchronized video?
One last element: the source of the three video is the same. (Same video played in each elements).
Thank you
Try something like this:
var videos = document.querySelectorAll('video');
function playAll() {
[].forEach.call(videos, function(video) {
video.play()
});
}
function pauseAll() {
[].forEach.call(videos, function(video) {
video.pause()
});
}
// this keeps everything synchronized
[].forEach.call(videos, function(video) {
video.addEventListener('play', playAll, false);
video.addEventListener('pause', pauseAll, false);
});
Keep in mind there will probably still be a slight offset (if you have sound it'll sound distorted)

Loading Audio Element After Dynamically Changing the Source

I have a couple of audio elements that appear in the body of my page. They look like this.
<audio id="sound1" preload="auto">
<source id="sound1source" src="../../Content/Audio/gau.mp3">
//add .ogg here later
</audio>
<audio id="sound2" preload="auto">
<source id="sound2source" src="../../Content/Audio/mah.mp3">
//add .ogg here later
</audio>
The audio plays when a user mouses over certain divs. Here's the code that triggers it.
var audio = $("#sound1")[0];
$("#ChoiceA").mouseenter(function () {
audio.play();
});
var audio2 = $("#sound2")[0];
$("#ChoiceB").mouseenter(function () {
audio2.play();
});
Everything above works fine. My problem occurs when I attempt to dynamically change the source element after making an ajax call. Here's my javascript that accomplishes that.
var src1 = "../../Content/Audio/" + data.nouns[0].Audio1 + ".mp3";
var src2 = "../../Content/Audio/" + data.nouns[1].Audio1 + ".mp3";
$("#sound1source").attr("src", src1);
$("#sound2source").attr("src", src2);
When I inspect the page after triggering the ajax call to change the source path for the audio elements, I see that the source is updated. No problem there. The problem is that the audio that the new paths point to does not play.
After hunting around I found this note on w3.org "Dynamically modifying a source element and its attribute when the element is already inserted in a video or audio element will have no effect. To change what is playing, either just use the src attribute on the media element directly, or call the load() method on the media element after manipulating the source elements."
The comment on w3.org seems to be related so I tried calling $('#sound1').load() and also $('#sound1source').load(). Neither solved my problem.
Can someone tell me what I've done wrong? If I need to cause the audio element to load again after dynamically changing the src, how do I do that?
-------------UPDATE-------------
Based on Swatkins suggestion I created the following function to create the audio tag when the user mouses over the target div. Unfortunately this has not solved the problem either.
function attachAudio1(src) {
$('#audio1').remove();
var audio = $('<audio>');
audio.attr("src", src);
audio.attr("id", "audio1");
audio.appendTo('body');
attachPlayAction();
};
function attachPlayAction() {
var audio = $("#audio1")[0];
$('#ChoiceA').live('mouseenter', function () {
audio.play();
});
};
You should call load like this:
var audio = $("#sound1")[0];
$("#ChoiceA").mouseenter(function () {
audio.load();
audio.play();
});
var audio2 = $("#sound2")[0];
$("#ChoiceB").mouseenter(function () {
audio.load();
audio2.play();
});
Have not tested doing it like above, but have testet this previously with a seperate function looking something like this:
<audio id="sound1" preload="auto" src="../../Content/Audio/gau.mp3">
function changeAudio(){
audio = document.getElementById("sound1");
audio.src = "../../Content/Audio/" + data.nouns[0].Audio1 + ".mp3";
audio.load();
audio.play();
}
$("#ChoiceA").mouseenter(function () {
changeAudio();
});
and that worked fine for me?
EDIT: Adding a fiddle, maybe that will help you figure this out?
http://jsfiddle.net/Z3VrV/
This is tricky. I would try replacing the whole <audio> element instead of just changing its source. This way, the new audio element hasn't been added to the page, so it will be forced to load the file.
load() followed by play() right away leads to trouble. Trying listening for the canplay event before attempting to play the audio as suggested in https://stackoverflow.com/a/8705478/1374208

Categories