From 0ed66b83d751a5e5a5b16e74e618662c2276191a Mon Sep 17 00:00:00 2001 From: Sravan S Date: Tue, 6 Jun 2023 00:55:54 +0900 Subject: [PATCH] fix: Race condition in playing audio file Race condition occurs when two audio files are requested from backend Clear previous player and play only the last arrived file Cleanup - Do not need to fetch audio file if its already in cache --- src/hooks/VoicePlayer/index.tsx | 58 +++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/src/hooks/VoicePlayer/index.tsx b/src/hooks/VoicePlayer/index.tsx index e7518a39d..36c3fd169 100644 --- a/src/hooks/VoicePlayer/index.tsx +++ b/src/hooks/VoicePlayer/index.tsx @@ -94,19 +94,25 @@ export const VoicePlayerProvider = ({ } logger.info('VoicePlayer: Start getting audio file.'); - new Promise((resolve) => { + new Promise((resolve) => { + voicePlayerDispatcher({ + type: INITIALIZE_AUDIO_UNIT, + payload: { groupKey }, + }); + // audio file passed as a parameter if (audioFile) { - resolve(audioFile); logger.info('VoicePlayer: Use the audioFile instance.'); + resolve(audioFile); + return; } - if (audioStorage?.[groupKey]?.audioFile) { - resolve(audioStorage[groupKey].audioFile); + // audio file from the audioStorage + const cachedAudioFile = audioStorage?.[groupKey]?.audioFile; + if (cachedAudioFile) { logger.info('VoicePlayer: Get from the audioStorage.'); + resolve(cachedAudioFile); + return; } - voicePlayerDispatcher({ - type: INITIALIZE_AUDIO_UNIT, - payload: { groupKey }, - }); + // fetch the audio file from URL fetch(audioFileUrl) .then((res) => res.blob()) .then((blob) => { @@ -118,7 +124,8 @@ export const VoicePlayerProvider = ({ logger.info('VoicePlayer: Get the audioFile from URL.'); }); }).then((audioFile: File) => { - logger.info('VoicePlayer: Succeeded getting audio file.', audioFile); + const voicePlayerRoot = document.getElementById(VOICE_PLAYER_ROOT_ID); + logger.info('VoicePlayer: Succeeded getting audio file.', { audioFile }); const currentAudioUnit = audioStorage[groupKey] || AudioUnitDefaultValue() as AudioStorageUnit; const audioPlayer = new Audio(URL?.createObjectURL?.(audioFile)); audioPlayer.id = VOICE_PLAYER_AUDIO_ID; @@ -145,14 +152,31 @@ export const VoicePlayerProvider = ({ payload: { groupKey }, }); }; - audioPlayer?.play(); - const voicePlayerRoot = document.getElementById(VOICE_PLAYER_ROOT_ID); - voicePlayerRoot.appendChild(audioPlayer); - voicePlayerDispatcher({ - type: SET_CURRENT_PLAYER, - payload: { groupKey, audioPlayer }, - }); - logger.info('VoicePlayer: Succeeded playing audio player.', { groupKey, audioPlayer }); + audioPlayer.dataset.sbGroupId = groupKey; + // clean up the previous audio player + try { + voicePlayerRoot?.childNodes.forEach((node) => { + const element = node as HTMLAudioElement; + const thisGroupKey = element.dataset?.sbGroupKey; + if (thisGroupKey !== groupKey) { + element?.pause?.(); + voicePlayerDispatcher({ + type: ON_VOICE_PLAYER_PAUSE, + payload: { groupKey }, + }); + voicePlayerRoot.removeChild(element); + logger.info('VoicePlayer: Removed other player.', { element }); + } + }); + } finally { + audioPlayer?.play(); + voicePlayerRoot?.appendChild(audioPlayer); + voicePlayerDispatcher({ + type: SET_CURRENT_PLAYER, + payload: { groupKey, audioPlayer }, + }); + logger.info('VoicePlayer: Succeeded playing audio player.', { groupKey, audioPlayer }); + } }); };