How to play an audio file in the background after clicking a link? (no embed) - html

Currently I am using following code to play some audio after a link is clicked:
Pronunciation of a word
For now if the user clicks on the link, a new page with an audio playing panel is loaded. After playing the audio, the user has to click GO BACK button of the browser to get back to the original content.
Is it possible to play the audio without being directed to a new page? When the user clicks on the link, the audio just plays in the background?
(Don't want to use embed because it's just a 1 second audio for a word's pronunciation as a minor explanation of an uncommon word).

Actually the href attribute is redirecting you to the new page, you can use e.prevenDefault() in the link click event handler to stop this redirection and create a dynamic audio element with this href as source and play it.
This is what you need:
function playItHere(e, link) {
var audio = document.createElement("audio");
var src = document.createElement("source");
src.src = link.href;
audio.appendChild(src);
audio.play();
e.preventDefault();
}
Pronunciation of a word

In html5, you can actually use the <audio> tag to get that done!
<audio src="/music/myaudio.ogg" autoplay> Sorry, your browser does not support the <audio> element. </audio>
SOURCE: Wired

If you use a tag be careful with href .
Code snippet fixed .
First you will need to make convert ogg to the mp3 and than use it for multi source .
Small browser detector (chrome/opera/safari - mp3 and mozilla - ogg . )
E("PLAYER").addEventListener("error", function(e) {
console.log("error: " + e.target.error)
});
function PLAYER_BACKGROUND(what) {
var SOURCE_PATH = E(what).getAttribute("whattoplay")
if (isChrome == true)
{
SOURCE_PATH = SOURCE_PATH.replace(".ogg" , ".mp3")
}
else {
SOURCE_PATH = SOURCE_PATH.replace( ".mp3" , ".ogg" )
}
E("PLAYER").src = SOURCE_PATH
E("PLAYER").play()
}
<script>
var E = function(id){return document.getElementById(id)};
var isChrome = /Chrome/.test(navigator.userAgent) || /Safari/.test(navigator.userAgent);
</script>
<a id="audio_1" onclick="PLAYER_BACKGROUND(this.id)" whattoplay="https://maximumroulette.com/framework/res/audio/laser7.ogg" href="javascript:void(0)">Pronunciation of a word</a>
<audio style="display:none" id="PLAYER" autoplay controls>
<source src="#" type="audio/ogg">
<source src="#" type="audio/mpeg">
Sorry, your browser does not support the element.
</audio>

Related

How do I add looping on HTML5 audio?

I need help looping a HTML5 audio clip.
I have the below script, but it only plays once. I need it to play the music clip when the link is pressed and plays non-stop in a loop. The audio can only then be stopped when refreshing the page or but selecting the link again:
Link here
<script>
// Sound for background music
var html5_audiotypes={
"mp3": "audio/mpeg",
"mp4": "audio/mp4",
"ogg": "audio/ogg",
"wav": "audio/wav"
}
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("")}}
}
}
//Initialize two sound clips with 1 fallback file each:
var mouseoversound=createsoundbite("music.ogg", "music.mp3")
var clicksound=createsoundbite("music.ogg", "music.mp3")
</script>
Thank you.
why don't you try using the audio tag and add the attribute loop so it would loop back to back
replace the src with your own audio file to see it looping
<h1>The audio loop attribute</h1>
<p>Click on the play button to play a sound:</p>
<audio controls loop>
<source src="https://www.w3schools.com/tags/horse.ogg" type="audio/ogg">
<source src="https://www.w3schools.com/tags/horse.mp3" type="audio/mpeg">
Your browser does not support the audio element.
</audio>
click this link to see its working

Pick a random .mp3 file to autoplay from a list of urls on page load?

Right now I have this
<audio autoplay>
<!-- <source src="https://a.pomf.cat/vmrlef.mp3" type="audio/mpeg">--> <!-- escape through the snow -->
<!-- <source src="https://files.catbox.moe/vif2j1.mp3" type="audio/mpeg"> <!-- sea map -->
<source src="https://files.catbox.moe/4abc2w.mp3" type="audio/mpeg"> <!-- ミク - prblm- -->
</audio>
which I have no idea how to make it select each one randomly on page load up, is there a way to like have a list and then make source src choose from a list randomly on each reload? pretty new to html and any help would be much appreciated!! ^^
Like this
https://jsfiddle.net/mplungjan/6opnhymz/
const audioUrls = ["https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3",
"https://www.soundhelix.com/examples/mp3/SoundHelix-Song-2.mp3",
"https://www.soundhelix.com/examples/mp3/SoundHelix-Song-3.mp3"];
const rnd = Math.floor(Math.random()*audioUrls.length); // random number from 0 to length of array
const audio = new Audio(); // an audio object
const loadedAudio = () => audio.play(); // what happens after the audio successfully has been found
document.body.appendChild(audio); // add it to the page
audio.addEventListener('canplaythrough', loadedAudio, false); // add the event that will play, here "can it play?"
console.log(`Playing #${rnd}:${audioUrls[rnd]}`); // for us to see it works
audio.src = audioUrls[rnd]; // actual trigger to play the audio
audio.load(); // iOS may need this

Angular 8 - Is there a way to bind to a video element to determine when it is loaded/starts playing?

Given:
<video poster="assets/videos/poster.png"
#videoPlayer
onloadedmetadata="this.muted = true">
<source src="assets/videos/video.mp4" type="video/mp4">
</video>
And in Angular:
...
public videoLoaded: boolean = false;
...
How can I bind videoLoaded to update once the video starts playing? (or is loaded) I've looked online and saw some older jquery implementations that seem to not be working in newer versions of chrome and want to know the latest way on how to accomplish this
Thanks
What you could do is make a reference to the video player itself with Angular's ViewChild and check if it's clicked.
#ViewChild('videoPlayer') videoPlayer: ElementRef;
videoClicked = false;
startVideo(): void {
this.videoClicked = true;
this.videoPlayer.nativeElement.play();
}
The startVideo() method will be used inside the HTML to trigger the change. The additional paragraph is used to see the change.
<video (click)="startVideo()" width="400"
#videoPlayer>
<source src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" type="video/mp4">
</video>
<p>Video clicked: {{videoClicked}}</p>
See this StackBlitz as an example of above behaviour.
Edit
A better way to do this is to use HTMLMediaElement's onplaying and loadeddata event. See MDN for documentation on onplaying and documentation on onplaying. In normal JavaScript it would look like this:
const video = document.querySelector('video');
video.onplaying = (event) => {
console.log('Video is no longer paused.');
};
In Angular, there are some small changes required. The HTML can stay pretty clean.
<video controls width="400"
#videoPlayer>
<source src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" type="video/mp4">
</video>
<p>Video loaded: {{dataLoaded}}</p>
<p>Video started: {{videoStarted}}</p>
The biggest changes are in the component, ngAfterViewInit checks if the element is there after view has been initialised. The loadeddata event is fired when the frame at the current playback position of the media has finished loading (so ready to play). Next to that, you can access the element's onplaying event to check if the video is not paused.
#ViewChild('videoPlayer') videoPlayer: ElementRef;
dataLoaded = false;
videoStarted = false;
ngAfterViewInit() {
this.videoPlayer.nativeElement.onloadeddata = (event) => {
console.log('Video data is loaded.');
this.dataLoaded = true;
};
this.videoPlayer.nativeElement.onplaying = (event) => {
console.log('Video is no longer paused.');
this.videoStarted = true;
};
}
Here's a StackBlitz example to show this example.
you can use HTML Audio/Video Events provided by html 5 video attribute.
loadeddata -> Fires when the browser has loaded the current frame of the audio/video
loadedmetadata -> Fires when the browser has loaded meta data for the audio/video
loadstart -> Fires when the browser starts looking for the audio/video

Google Chrome does not autoplay HTML5 video on mobile

I have problems to get a video to play on my Android mobile in the latest version of Chrome. In other browsers like the Puffin browser the video is playing. For test purposes I tried all common formats:
mp4
<br />
<video autoplay="autoplay" loop="loop" onended="this.play()"><source src="http://clips.vorwaerts-gmbh.de/VfE_html5.mp4" type="video/mp4" /></video>
<br />
webm
<br />
<video autoplay="autoplay" loop="loop" onended="this.play()"><source src="http://clips.vorwaerts-gmbh.de/VfE.webm" type="video/webm" /></video>
<br />
ogg
<br />
<video autoplay="autoplay" loop="loop" onended="this.play()"><source src="http://clips.vorwaerts-gmbh.de/VfE.ogv" type="video/ogg" /></video>
https://codepen.io/anon/pen/ozpVNP
According to Mozilla the first video, that is H.264 + AAC in MP4 should play. I also take this article in account and tried to play the videos by JavaScript additionally as well as tried to remove the type attribute on the first video tag without success.
How can I get it work in Chrome on Mobile?
<video autoplay loop autobuffer muted playsinline>
<source src="video/video-hat.mp4" type="video/mp4">
</video>
The problem is that Google want that users initiate by themselves any media, so If you debug your device chrome browser, you will get the warning "Failed to execute 'play' on 'HTMLMediaElement': API can only be initiated by a user gesture."
So that means you need to attach the video initialization, for example, with a click event
There doesn't appear to be any great info on this, so thought I'd post my findings.
I've been debugging html5 video playback on Chrome desktop and mobile on an Android 5.0.1 Samsung S4 with Chrome 61 and the embedded browser, and Safari 9 & 11, using an automatic javascript play/pause written in AngularJS (below). The video is embedded in a carousel so is sometimes visible, sometimes not. In summary:
I would recommend having both webm(vp8/vorbis) and mp4(h264/aac) formats. These are the most supported formats and have equivalent quality for the same bitrate. ffmpeg can encode both.
It seems Chrome mobile prefers webm if it can get it, so put that first.
If a browser plays a file when you direct it to the file url, this does not mean it will play it when embedded in a video tag, though it will tell you if the format & codecs are supported if it does play. Chrome mobile seems very picky about having a video source whose resolution is too high.
Safari (and probably iOS) will not play a video unless served by a server supporting byte-ranges. Apache, nginx and Amazon S3 for example do support them, but many smaller web servers (like WSGI servers) do not.
The order of the videos matters more than the source media attribute. Always have low resolution versions of a video first. The example below uses 1920x1080 and 1280x720. It seems if the mobile browser encounters a video that is "too high-res", it just stops processing the other sources and prefers the poster.
having a controls attribute and manual play vs playing through javascript doesn't appear to make any difference.
the muted attribute stops android from putting a little speaker icon in the status bar when playing but off-screen, even when the video doesn't have audio. As a side-note, I'd also really think about your audience if you intend to autoplay video with sound. Personally I think it's a bad idea.
the preload attribute doesn't seem to make much difference. The browser will tend to automatically preload the selected video metadata anyway.
having a source type attribute does not stop the video from playing. If anything it helps the browser choose which source to pick for the best
the JS video.oncanplay event is the best way to see if the video tag has been successful. If you don't get that, the video won't play, but the browser won't tell you why.
HTML:
<video class="img-responsive-upscale ng-scope"
video-auto-ctrl loop muted preload poster="0022.png">
<source src="vid_small.webm" media="(max-width: 1280px)" type="video/webm">
<source src="vid_small.mp4" media="(max-width: 1280px)" type="video/mp4">
<source src="vid.webm" media="(max-width: 1920px)" type="video/webm">
<source src="vid.mp4" type="video/mp4">
<img src="0022.png" alt="something"
title="Your browser does not support the <video> tag">
</video>
Javascript:
<script type="text/javascript">
angular.module('myproducts.videoplay', []).directive('videoAutoCtrl',
function() {
return {
require: '^uibCarousel',
link: function(scope, element, attrs) {
var video = element[0];
var canplay = false;
var rs = ["HAVE_NOTHING", "HAVE_METADATA", "HAVE_CURRENT_DATA", "HAVE_FUTURE_DATA", "HAVE_ENOUGH_DATA"];
var ns = ["NETWORK_EMPTY", "NETWORK_IDLE", "NETWORK_LOADING", "NETWORK_NO_SOURCE"];
function vinfo() {
console.log("currentSrc = " + video.currentSrc);
console.log("readyState = " + rs[video.readyState]);
console.log("networkState = " + ns[video.networkState]);
bufinfo();
}
function bufinfo() {
// tr is a TimeRanges object
tr = video.buffered
if (tr.length > 0) {
var ranges = ""
for (i = 0; i < tr.length; i++) {
s = tr.start(i);
e = tr.end(i);
ranges += s + '-' + e;
if (i + 1 < tr.length) {
ranges += ', '
}
}
console.log("buffered time ranges: " + ranges);
}
}
video.onerror = function () {
console.log(video.error);
}
video.oncanplay = function () {
canplay = true;
if (!playing) {
console.log("canplay!");
vinfo();
}
}
var playing = false;
function playfulfilled(v) {
console.log("visible so playing " + video.currentSrc.split('/').pop());
playing = true;
}
function playrejected(v) {
console.log("play failed", v);
}
function setstate(visible) {
if (canplay) {
if (visible) {
p = video.play();
if (p !== undefined) {
p.then(playfulfilled, playrejected);
}
} else if (playing) {
video.pause();
console.log("invisible so paused");
playing = false;
}
} else {
console.log("!canplay, visible:", visible);
vinfo();
}
}
// Because $watch calls $parse on the 1st arg, the property doesn't need to exist on first load
scope.$parent.$watch('active', setstate);
}
};
});
</script>
I had an issue where the video worked on my desktop chrome, and desktop-mobile view, but not my iphone. Turns out i needed to add the "playsinline" property to the video tag. :]
The issue fixed for me after switching off "Data saving" mode in chrome.
I spend all my afternoon to fix an autoplay problem on iOS and discovered you just to disable the "ECO MODE" or it won't play automatically.

How to make poster behave like a hyperlink in html video

I have this audio mp3 which I wanna play in browser. The mp3 has an accompanying image and a url to navigate to when I click. So I put the mp3 in a video tag and made the image a poster like this
//cache the poster
var img = document.createElement("img");
img.src = "http://lorempixel.com/300/200";
// to make sure the poster is loaded before the video player appears
img.addEventListener("load", function(){
var video = document.getElementById("demo-player");
video.style.display = 'block';
console.log("loaded!");
});
delete img;
<video id="demo-player" controls="controls" style="display: none;"
src="http://www.stephaniequinn.com/Music/Commercial%20DEMO%20-%2003.mp3"
poster="http://lorempixel.com/300/200">
</video>
Now I want to make the poster clickable which I intend to do by creating a click event listener on the video tag. My questions are
Is it correct to override the video's click event to make poster clickable? ( Are there any alternate methods?)
Is there a way I can bring in cursor: pointer to the poster?
P.S: I am using the video tag here because, my audio will be an ad/announcement with an image and a link to navigate(if interested). And after this 4-5 second pre-roll audio, there will be a lengthy content video.
Apply css cursor: pointer property for the video tag. For handling click event attach a click event handler. I don't think anything is wrong with using click event handler on video tag which doesn't effect the video controllers.
//cache the poster
var img = document.createElement("img");
img.src = "http://lorempixel.com/300/200";
// to make sure the poster is loaded before the video player appears
img.addEventListener("load", function() {
var video = document.getElementById("demo-player");
video.style.display = 'block';
console.log("loaded!");
video.addEventListener('click', function() {
console.log('clicked');
});
});
delete img;
video {
cursor: pointer;
}
<video id="demo-player" controls="controls" style="display: none;" src="http://www.stephaniequinn.com/Music/Commercial%20DEMO%20-%2003.mp3" poster="http://lorempixel.com/300/200">
</video>