File: //proc/self/root/home/arjun/projects/buyercall/buyercall/assets/vue/components/AudioPlayer.vue
<template>
<div id="audio-player-root">
<!-- Hide the default audio player -->
<div>
<audio style="display: none" ref="player" :id="playerid">
<source :src="url" type="audio/mpeg" />
</audio>
</div>
<div class="" style="margin: auto">
<div id="player-row" class="audio-player-row">
<div id="button-div" class="button-div">
<svg
@click="toggleAudio()"
v-show="!isPlaying"
class="play-button text-gray-400"
:class="{
'text-orange-600': audioLoaded,
'hover:text-orange-400': audioLoaded,
'cursor-pointer': audioLoaded,
}"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fill-rule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z"
clip-rule="evenodd"
/>
</svg>
<svg
@click="toggleAudio()"
v-show="isPlaying"
class="
play-button
text-orange-400
hover:text-orange-400
cursor-pointer
"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fill-rule="evenodd"
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zM7 8a1 1 0 012 0v4a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v4a1 1 0 102 0V8a1 1 0 00-1-1z"
clip-rule="evenodd"
/>
</svg>
</div>
<div id="progress-bar" class="progress-bar">
<div class="overlay-container">
<input
v-model="playbackTime"
type="range"
min="0"
:max="audioDuration"
class="slider inputrange"
id="position"
name="position"
/>
<!-- <av-line
:line-width="2"
line-color="lime"
audio-src="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3"
:audio-controls="false"
></av-line> -->
<!-- Show loading indicator until audio has been loaded -->
<div v-show="!audioLoaded" class="" style="color: #94bcec">
Loading please wait...
</div>
<div v-show="audioLoaded" class="">
<span
class="text-sm"
style="color: #94bcec"
v-html="elapsedTime()"
>
</span>
<span class="text-sm" style="color: #94bcec" v-html="totalTime()">
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
url: {
type: String,
required: true,
},
playerid: {
type: String,
required: true,
},
},
/**
* playbackTime = local var that syncs to audio.currentTime
* audioDuration = duration of audio file in seconds
* isPlaying = boolean (true if audio is playing)
*
**/
data() {
return {
playbackTime: 0,
audioDuration: 100,
audioLoaded: false,
isPlaying: false,
listenerActive: false,
};
},
methods: {
//Set the range slider max value equal to audio duration
initSlider() {
var audio = this.$refs.player;
if (audio) {
this.audioDuration = Math.round(audio.duration);
}
},
//Convert audio current time from seconds to min:sec display
convertTime(seconds) {
const format = (val) => `0${Math.floor(val)}`.slice(-2);
var hours = seconds / 3600;
var minutes = (seconds % 3600) / 60;
return [minutes, seconds % 60].map(format).join(':');
},
//Show the total duration of audio file
totalTime() {
var audio = this.$refs.player;
if (audio) {
var seconds = audio.duration;
return this.convertTime(seconds);
} else {
return '00:00';
}
},
//Display the audio time elapsed so far
elapsedTime() {
var audio = this.$refs.player;
if (audio) {
var seconds = audio.currentTime;
return this.convertTime(seconds);
} else {
return '00:00';
}
},
//Playback listener function runs every 100ms while audio is playing
playbackListener(e) {
var audio = this.$refs.player;
//Sync local 'playbackTime' var to audio.currentTime and update global state
this.playbackTime = audio.currentTime;
//console.log("update: " + audio.currentTime);
//Add listeners for audio pause and audio end events
audio.addEventListener('ended', this.endListener);
audio.addEventListener('pause', this.pauseListener);
},
//Function to run when audio is paused by user
pauseListener() {
this.isPlaying = false;
this.listenerActive = false;
this.cleanupListeners();
},
//Function to run when audio play reaches the end of file
endListener() {
this.isPlaying = false;
this.listenerActive = false;
this.cleanupListeners();
},
//Remove listeners after audio play stops
cleanupListeners() {
var audio = this.$refs.player;
audio.removeEventListener('freqtimeupdate', this.playbackListener);
audio.removeEventListener('ended', this.endListener);
audio.removeEventListener('pause', this.pauseListener);
//console.log("All cleaned up!");
},
toggleAudio() {
var audio = this.$refs.player;
//var audio = document.getElementById("audio-player");
if (audio.paused) {
audio.play();
this.isPlaying = true;
} else {
audio.pause();
this.isPlaying = false;
}
},
createCustomEvent() {
(function (global) {
'use strict';
// console.log('freqtimeupdate');
// Create the new `freqtimeupdate` event
var freqtimeupdate = global.CustomEvent('freqtimeupdate'),
// The event frequency in milliseconds
frequency = 100,
// Wrappers around setInterval and clearInterval to ensure one interval per audio
setInterval = function () {
if (!this.hasOwnProperty('_interval')) {
this._interval = global.setInterval(
intervalFunc.bind(this),
frequency,
);
}
},
clearInterval = function () {
global.clearInterval(this._interval);
delete this._interval;
},
// The actual interval function that dispatches the event
intervalFunc = function () {
this.dispatchEvent(freqtimeupdate);
},
// Get all audios from the page to add the event to
audios = global.document.getElementsByTagName('audio');
// Add listeners to the audios for adding and removing the interval
for (var i = 0; i < audios.length; i++) {
if (!audios[i].paused) {
setInterval.call(audios[i]);
}
audios[i].addEventListener('play', setInterval);
audios[i].addEventListener('playing', setInterval);
audios[i].addEventListener('seeked', setInterval);
audios[i].addEventListener('abort', clearInterval);
audios[i].addEventListener('emptied', clearInterval);
audios[i].addEventListener('ended', clearInterval);
audios[i].addEventListener('pause', clearInterval);
}
})(window);
},
},
mounted: function () {
// nextTick code will run only after the entire view has been rendered
this.$nextTick(function () {
var audio = this.$refs.player;
//Wait for audio to load, then run initSlider() to get audio duration and set the max value of our slider
// "loademetadata" Event https://www.w3schools.com/tags/av_event_loadedmetadata.asp
audio.addEventListener(
'loadedmetadata',
function (e) {
this.initSlider();
}.bind(this),
);
// "canplay" HTML Event lets us know audio is ready for play https://www.w3schools.com/tags/av_event_canplay.asp
audio.addEventListener(
'canplay',
function (e) {
this.audioLoaded = true;
this.createCustomEvent();
}.bind(this),
);
//Wait for audio to begin play, then start playback listener function
this.$watch('isPlaying', function () {
if (this.isPlaying) {
var audio = this.$refs.player;
this.initSlider();
//console.log("Audio playback started.");
console.log('Hi1');
//prevent starting multiple listeners at the same time
if (!this.listenerActive) {
this.listenerActive = true;
console.log('Hi');
audio.addEventListener('freqtimeupdate', this.playbackListener);
}
}
});
//Update current audio position when user drags progress slider
this.$watch('playbackTime', function () {
var audio = this.$refs.player;
var diff = Math.abs(this.playbackTime - this.$refs.player.currentTime);
//Throttle synchronization to prevent infinite loop between playback listener and this watcher
if (diff > 0.01) {
this.$refs.player.currentTime = this.playbackTime;
}
});
});
},
};
</script>