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.
So on my website, there are few simple audio players that are live streaming radio stations.
Here's how it looks...
audio player pic
And here is my code for these audio players:
<audio src="https://cbc_r2_tor.akacast.akamaistream.net/7/364/451661/v1/rc.akacast.akamaistream.net/cbc_r2_tor" controls style="width:75px;" volume="1.0"> </audio>
<audio src="http://204.2.199.166/7/288/80873/v1/rogers.akacast.akamaistream.net/tor925" controls="true" style="width:75px;" volume="1.0"></audio>
<audio src="http://indie.streamon.fm:8000/indie-48k.aac" controls="true" style="width:75px;" volume="1.0"></audio>
These players don't pause automatically when the other is being played.
I did some research on this topic and found this script here on stack...
<script>
document.addEventListener('play', function(e){
var audios = document.getElementsByTagName('audio');
for(var i = 0, len = audios.length; i < len;i++){
if(audios[i] != e.target){
audios[i].pause();
}
}
}, true);
</script>
Btw I'm using wix.com to build all of this and I'm really not sure where to put this script exactly. I tried to put it beneath in Edit code where the code of the individual audio player is but that doesn't seem to work at all.
What would be the simplest way to achieve this?
I'm a beginner so any help would be appreciated. Thanks in advance :)
Wix does not expose the window or document objects.
However, you can use $w().
As in let myElement = $w("#myElement");
See the site for more: https://www.wix.com/code/reference/%24w.html
EDIT
I'd advise against using 'document' as a variable name here, it could be confused with being the real document object.
Here are some pointers from the Wix site I indicated above that should sort out what you are trying to do...
Getting elements from the page (from Wix):
let imageElements = $w("Image");
let firstImage = imageElements[0];
Just replace 'Image' with 'Audio';
Use the onReady event (from Wix):
function onReady(initFunction: ReadyHandler): void
callback ReadyHandler(): Promise<void>
Put your initialisation code in the onReady event - otherwise the DOM may not be ready.
Creating your event handler (from Wix):
$w("#myElement").onEvent( (event, $w) => {
let targetId = event.target.id; // "myElement"
});
$w("#myElement").onEvent( (event, $w) => {
let eventType = event.type; // "click"
});
So, use something like:
$w.onReady(function() {
let myAudios = $w("audio");
myAudios.onEvent((event, $w) => {
let eventType = event.type;
if(eventType == "play") // or use 'click' if play is not exposed
{
let targetId = event.target.id;
for(var i = 0; i < myAudios.length; i++) {
if(myAudios[i].id != targetId) {
myAudios[i].pause();
}
}
}
});
});
Final note.
You'll want to put your javascript code on the page you are working with using the code panel.
From Wix:
The Public section of the sidebar contains files that are publicly
accessible from your site. You can create JavaScript files and text
files for use in public, and you can organize these files in folders.
Your page and site code, which are also publicly accessible, do not
appear in the Public section.
To edit page and site code, use the code panel.
See this short video from Wix (you can jump to 30secs) to see where the code panel is. https://support.wix.com/en/article/working-in-the-code-panel
EDIT 2
I finally gave in, and created a Wix account to test this.
Unfortunately, you are limited to what you can do in javascript regarding the APIs they expose from the objects placed on the page.
However, there is a way to get your functionality:
Create an HTML iframe.
Click Add, then More, then drag the HTML iframe onto your page.
Double-click it, or select it and click 'Edit Code', then add all of the below to the 'Add your code here (HTTPS only)' box.
<audio src="http://narwakk.free.fr/musiques/Bob/Bob Marley - Roots, Rock, Reggae.mp3" controls> </audio>
<audio src="https://jazz-wr06.ice.infomaniak.ch/jazz-wr06-64.aac" controls></audio>
<audio src="https://hpr.dogphilosophy.net/test/wav.wav" controls></audio>
<script>
document.addEventListener('play', function (e) {
var audios = document.getElementsByTagName('audio');
for (var i = 0, len = audios.length; i < len; i++) {
if (audios[i] != e.target) {
audios[i].pause();
}
}
}, true);
</script>
Remove any code you had for the audios before, preview it, and you should be done (apart from using your own sounds).
I'll leave the previous edit as is, because it generally works - just not for audio tags...
In this example, I'm using Howler JS as a music player and I need to create a playlist by class objects and be able to use multiple play/pause buttons in the same page.
So for the playlist I did:
var titx;
var filx;
var idx;
var myplax = [];
$.each($('.btnplay'), function(index, value) {
titx = $(this).attr("title");
filx = $(this).attr("data-track-name");
idx = $(this).attr("data-id");
myu = {
id: idx,
title: titx,
file: filx,
howl: null
}
myplax.push(myu);
});
var player = new Player(myplax);
Then for fire the play button with multiple play/pause buttons in page, I tried with jQuery like this:
$(".btnplay").click(function(){
player.play();
});
$(".btnpause").click(function(){
player.pause();
});
But when I click any play buttons it starts to play every time the first song.
Also If I click the second button (the one at the top) the jQuery animate instead the first button (the one at the bottom).
However the playlist works great, but how can I fix the issue for the play button?
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 visit this site all the time to search for solutions, but I couldn't find an answer to my question.
I want to add multiple audio files to a page. So I used the following coding. What this does is when you click one file, it starts playing the music, when you click the next file the rest will pause. That's what I wanted.
But I also want the play/pause option on each file; so when you click the "listen/pause" link for "Night Swim", it starts playing, and when you click the same link again, it will stop.
Is there any way I can do this? I'm not very handy with Javascript, I tried all sorts of other codes but nothing seems to work the way I want it.
I hope someone can help me and I hope my problem is explained correctly (I'm Dutch, I apologize for my English :S )
Here's my code:
<audio id="1">
<source src="everynight-snippet.mp3" type='audio/mpeg'>
</audio>
<audio id="2">
<source src="nightswim-snippet.mp3" type='audio/mpeg'>
</audio>
Every Night (Listen/Pause)
Night Swim (Listen/Pause)
And the script:
<script>
ids = new Array(2); // an array with total number of ids
function aud_play_pause(idNumber) {
var idNumber = document.getElementById(idNumber);
for(var i=0; i<ids.length; i++){
document.getElementById(i+1).pause(); // Pause all ids before playing next file.
document.getElementById(i+1).currentTime = 0; // Set the time back to zero, else it will replay from the pause point.
}
idNumber.play();
}
</script>
So to sum it up:
If I click the first song (Every Night), it starts playing. When I click it again, it should stop playing.
If I click the second song (Night Swim) while the first one plays, the first song should stop playing and the second song should start. If I click the second song again, it should stop.
etc
You could check if the idNumber audio is playing using the currentTime property, and start it if it is not. Otherwise, if the current one is playing you can stop all of them anyway.
ids = new Array(2); // an array with total number of ids
function aud_play_pause(idNumber) {
var clickedAudio = document.getElementById(idNumber);
for (var i = 0; i < ids.length; i++) {
if ((i + 1) == idNumber && clickedAudio.currentTime == 0) { // if it's the current one and is not playing
clickedAudio.play(); // start it
} else { // either not the current one, or the current one but it is playing
document.getElementById(i + 1).pause(); // Pause all ids before playing next file.
document.getElementById(i + 1).currentTime = 0; // Set the time back to zero, else it will replay from the pause point.
}
}
}
The way you had wrote your code though the for paused all elements.