I am trying to understand how can I obtain the current time of the audio while the audio is playing. So when the audio starts playing it will log 0 and at the end of play it will log the total duration. This is what I have tried below and it is not returning what I had in mind. I am probably doing it wrong. But I am not sure where it is going wrong.
For example, at the end of the audio, it returns currentTime:36.02133333333333 totalDuration36.006875
where currentTime>totalDuration which is completely wrong. I want to utilize these values, hence they need to be accurate.
const audioUrl = 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/128337/ongoing-thing-crop.ogg';
/*test url2 - https://s.cdpn.io/1202/Star_Wars_original_opening_crawl_1977.mp3*/
const div = document.querySelector('div');
const audioContext = new(window.AudioContext || window.webkitAudioContext)();
let bufferSource = audioContext.createBufferSource();
let analyser = audioContext.createAnalyser();
let gainNode = audioContext.createGain();
let startTime;
async function setupAudio(url) {
const response = await fetch(url);
const audioData = await response.arrayBuffer();
const buffer = await audioContext.decodeAudioData(audioData);
bufferSource.buffer = buffer;
bufferSource.connect(analyser);
analyser.connect(gainNode);
gainNode.connect(audioContext.destination);
function updateTime() {
let currentTime = audioContext.currentTime - startTime;
console.log(`currentTime:${currentTime}`,`totalDuration${buffer.duration}`);
if (currentTime < buffer.duration) {
requestAnimationFrame(updateTime);
}
}
div.addEventListener('change', () => {
startTime = audioContext.currentTime;
bufferSource.start(0);
requestAnimationFrame(updateTime);
});
}
setupAudio(audioUrl);
<div id="selector">
<label for="valueSelection">Choose a value <select id="valueSelection">
<option>off</option>
<option>on</option>
</select>
</label>
</div>
<audio></audio>
The issue happens because the code is printing console output outside of the conditional check in updateTime
function:
function updateTime() {
let currentTime = audioContext.currentTime - startTime;
console.log(`currentTime:${currentTime}`,`totalDuration${buffer.duration}`);
if (currentTime < buffer.duration) {
requestAnimationFrame(updateTime);
}
}
What you are basically doing is printing console log output in following cases:
Print log every time when currentTime
is less than buffer.duration
, and
Print log once when currentTime
is greater than or equal to buffer.duration
Note: During last log output when currentTime > totalDuration, you actually aren't calling the function updateTime
, since the conditional checking will be false
:
// false when currentTime >= buffer.duration
// so you won't call updateTime, but you are printing console log once
if (currentTime < buffer.duration) {
requestAnimationFrame(updateTime);
}
function updateTime() {
let currentTime = audioContext.currentTime - startTime;
if (currentTime < buffer.duration) {
console.log(`currentTime:${currentTime}`,`totalDuration${buffer.duration}`);
requestAnimationFrame(updateTime);
}
}
This will only print console log output when currentTime < buffer.duration
is true
.
const audioUrl = 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/128337/ongoing-thing-crop.ogg';
/*test url2 - https://s.cdpn.io/1202/Star_Wars_original_opening_crawl_1977.mp3*/
const div = document.querySelector('div');
const audioContext = new(window.AudioContext || window.webkitAudioContext)();
let bufferSource = audioContext.createBufferSource();
let analyser = audioContext.createAnalyser();
let gainNode = audioContext.createGain();
let startTime;
async function setupAudio(url) {
const response = await fetch(url);
const audioData = await response.arrayBuffer();
const buffer = await audioContext.decodeAudioData(audioData);
bufferSource.buffer = buffer;
bufferSource.connect(analyser);
analyser.connect(gainNode);
gainNode.connect(audioContext.destination);
function updateTime() {
let currentTime = audioContext.currentTime - startTime;
if (currentTime < buffer.duration) {
console.log(`currentTime:${currentTime}`, `totalDuration${buffer.duration}`);
requestAnimationFrame(updateTime);
}
}
div.addEventListener('change', () => {
startTime = audioContext.currentTime;
bufferSource.start(0);
requestAnimationFrame(updateTime);
});
}
setupAudio(audioUrl);
<div id="selector">
<label for="valueSelection">Choose a value <select id="valueSelection">
<option>off</option>
<option>on</option>
</select>
</label>
</div>
<audio></audio>