Reputation: 3543
I have a wired issue with my function. you don't need to read and understand every part of the function although I've copied all the functions for you to have a look. The MovieAudio
function has PlayAudio()
function inside and it's where the issue exist ...
We have this line of code inside PlayAudio()
function:
console.log('before sfx');
if(sfx) { await sfxPlay(sfx.before_listen); }
console.log('after sfx');
As you see we have two console logs right before and after this line. If sfxPlay
promise resolves we should see the console.log('after sfx');
but we never see this unfortunately!
I have tested the await sfxPlay(sfx.before_listen);
another place outside of this code and it works correctly!
In the first sight I thought maybe sfxPlay
function doesn't resolve correctly so I put console.log('sfx has been resolved');
inside sfxPlay
function to check if sfxPlay
function is resolved correctly, and yes it resolves correctly but still we don't proceed to console.log('after sfx')
Here is my console. note that we don't see console.log('after sfx')
which we except to see of course:
What am I missing? it seems simple but it doesn't behave correctly?
let StopMovieAudio;
function MovieAudio(duration, stress, option = {}) {
let movieAudioResolve;
const speed = option.speed ? option.speed : 1;
const sfx = option.sfx ? false : true;
const guideIndex = option.guideIndex ? [...Array(option.guideIndex).keys()] : [];
if(!stress) stress = { to: '__', from: '__', within: ['__-__'] };
const guide = !!guideIndex.length;
const video = document.createElement('video');
document.body.appendChild(video);
video.id = 'audio-clip';
const clip = document.getElementById("audio-clip");
clip.style.visibility = "hidden";
const source = document.createElement('source');
source.src = getBlob(clipSource);
source.type = 'video/mp4';
video.appendChild(source);
video.load();
const start = duration.start + startPlus;
const end = duration.end + endPlus;
PlayAudio();
async function PlayAudio() {
clip.currentTime = start;
clip.playbackRate = speed;
console.log('sfx', sfx);
console.log('before sfx');
if(sfx) { await sfxPlay(sfx.before_listen); } // sfx is true and we enter the if block
console.log('after sfx');
StartAudio();
const endCheck = setInterval(endCheckInterval, 5);
function endCheckInterval() {
guidePhraseUpper(guideIndex[0]);
checkStopMovie();
}
} // end of Play function
function checkStopMovie() {
if (clip.currentTime >= end) {
clearInterval(endCheck);
StopMovieAudio();
guidePhrasesDown();
}
}
function guidePhraseUpper(index) {
if(!guideIndex.length) return;
if (clip.currentTime >= portionDurations[index].start) {
guideIndex.shift();
guidePhrasesDown();
guidePhraseUp(movieSentenceArrayEn[index]);
}
}
function guidePhrasesDown() {
if(!guide) return;
const component = $(`iframe[src*='${components.chief}']`)[0];
referenceString.split(' ').forEach((phrase, index) => component.contentWindow.guideWordDown(index));
}
function StartAudio() {
console.log('start of StartAudio');
clip.volume = 1;
clip.play();
stressEffectTo();
stressEffectFrom();
stressEffectWithin();
}
StopMovieAudio = () => {
const audioClip = document.getElementById("audio-clip");
if(audioClip) { document.body.removeChild(audioClip); }
if(typeof StopMovieAudio === "function") { movieAudioResolve(); }
}
function stressEffectTo() {
if(stress.to.includes('_')) { return; }
clip.playbackRate = 0.75;
speedUpFrom(stress.to);
}
function stressEffectFrom() {
if(stress.from.includes('_')) { return; }
clip.playbackRate = 1;
speedDownFrom(stress.from);
}
function stressEffectWithin() {
const stressWithin = stress.within.filter(w => !w.includes('_'));
if(!stressWithin.length){ return; }
for(let i = 0; i < stressWithin.length; i++) {
speedDownFrom(stressWithin[i].split('-')[0]);
speedUpFrom(stressWithin[i].split('-')[1]);
}
} // end of stressEffectWithin function
function speedUpFrom(timer) {
const endCheck = setInterval(endCheckInterval, 5);
function endCheckInterval() {
if (clip.currentTime >= timer) {
clearInterval(endCheck);
clip.playbackRate = 1;
}
}
} // end of Track function
function speedDownFrom(timer) {
const endCheck = setInterval(endCheckInterval, 5);
function endCheckInterval() {
if (clip.currentTime >= timer) {
clearInterval(endCheck);
clip.playbackRate = 0.7;
}
}
} // end of Track function
return new Promise(resolve => {
movieAudioResolve = resolve;
console.log('Promise reached');
});
} // end of MovieAudio function
let sfxPlayResolve;
function sfxPlay(source) {
return new Promise(resolve => {
sfxPlayResolve = resolve;
const sfxAudio = new Audio(source);
playingAudios.push(sfxAudio);
sfxAudio.play();
sfxAudio.onerror = function() {
console.log("Error loading: " + this.src);
sfxPlay(sfx.no_sources);
resolve();
}
sfxAudio.addEventListener("ended", function() {
sfxAudio.currentTime = 0;
resolve();
console.log('sfx has been resolved');
});
});
}
A Codepen has been added (I have commented the if block (where the issue exist) to show you the correct behavior of the function and You need to click on somewhere to play the audio of the video):
https://codepen.io/pixy-dixy/pen/mdOVgZw
Upvotes: 2
Views: 85
Reputation: 126
The user has to interact with the document, one cannot just autoplay a video. See https://developers.google.com/web/updates/2017/09/autoplay-policy-changes
For me it works just fine when the PlayAudio
function is run on clicking a button, like:
HTML:
<button onclick="startTheShow()">Play</button>
JS:
// setTimeout(async () => {
// await MovieAudio({start: '3', end: '15'}, { to: '__', from: '__', within: ['__-__'] }, 1, true);
// }, 5000);
const startTheShow = async () => {
await MovieAudio({start: '3', end: '15'}, { to: '__', from: '__', within: ['__-__'] }, 1, true);
}
Upvotes: 0
Reputation: 1742
try calling the play function like this:
let flag = true;
sfxAudio.addEventListener("canplay", function() {
console.log('sfx can play');
flag && this.play();
flag = false;
});
I think it is a race condition, that would also explain why your code fails locally, but works in the codepen.
The docs also recommend an Event-based approach to calling play(): https://developer.mozilla.org/en-US/docs/Web/API/HTMLAudioElement/Audio
Upvotes: 1