W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
多音頻并發(fā),即多個(gè)音頻流同時(shí)播放。此場(chǎng)景下,如果系統(tǒng)不加管控,會(huì)造成多個(gè)音頻流混音播放,容易讓用戶感到嘈雜,造成不好的用戶體驗(yàn)。為了解決這個(gè)問(wèn)題,系統(tǒng)預(yù)設(shè)了音頻打斷策略,對(duì)多音頻播放的并發(fā)進(jìn)行管控,只有持有音頻焦點(diǎn)的音頻流才可以正常播放,避免多個(gè)音頻流無(wú)序并發(fā)播放的現(xiàn)象出現(xiàn)。
當(dāng)應(yīng)用開(kāi)始播放音頻時(shí),系統(tǒng)首先為相應(yīng)的音頻流申請(qǐng)音頻焦點(diǎn),獲得焦點(diǎn)的音頻流可以播放;若焦點(diǎn)申請(qǐng)被拒絕,則不能播放。在音頻流播放的過(guò)程中,若被其他音頻流打斷,則會(huì)失去音頻焦點(diǎn)。當(dāng)音頻流失去音頻焦點(diǎn)時(shí),只能暫停播放。在應(yīng)用播放音頻的過(guò)程中,這些動(dòng)作均由系統(tǒng)自行完成,無(wú)需應(yīng)用主動(dòng)觸發(fā)。但為了維持應(yīng)用和系統(tǒng)的狀態(tài)一致性,保證良好的用戶體驗(yàn),推薦應(yīng)用監(jiān)聽(tīng)音頻打斷事件,并在收到音頻打斷事件(InterruptEvent)時(shí)做出相應(yīng)處理。
為滿足應(yīng)用對(duì)多音頻并發(fā)策略的不同需求,音頻打斷策略預(yù)設(shè)了兩種焦點(diǎn)模式,針對(duì)同一應(yīng)用創(chuàng)建的多個(gè)音頻流,應(yīng)用可通過(guò)設(shè)置焦點(diǎn)模式,選擇由應(yīng)用自主管控或由系統(tǒng)統(tǒng)一管控。
音頻打斷策略決定了應(yīng)該對(duì)音頻流采取何種操作,如暫停播放、繼續(xù)播放、降低音量播放、恢復(fù)音量播放等,這些操作可能由系統(tǒng)或應(yīng)用來(lái)執(zhí)行。音頻打斷策略預(yù)置了兩種打斷類型,用于區(qū)分音頻打斷事件(InterruptEvent)的執(zhí)行者。
音頻打斷策略預(yù)設(shè)了兩種焦點(diǎn)模式(InterruptMode):
應(yīng)用可以按需選擇合適的焦點(diǎn)模式,在創(chuàng)建音頻流時(shí),系統(tǒng)默認(rèn)采用共享焦點(diǎn)模式,應(yīng)用可主動(dòng)設(shè)置所需的模式。
設(shè)置焦點(diǎn)模式的方法:
音頻打斷策略(包括兩種焦點(diǎn)模式)決定了應(yīng)該對(duì)各個(gè)音頻流采取何種操作,如暫停播放、繼續(xù)播放、降低音量播放、恢復(fù)音量播放等。而針對(duì)這些操作的執(zhí)行過(guò)程,根據(jù)執(zhí)行者的不同,可以分為兩種打斷類型(InterruptForceType):
對(duì)于音頻打斷策略的執(zhí)行,系統(tǒng)默認(rèn)采用強(qiáng)制打斷類型(INTERRUPT_FORCE),應(yīng)用無(wú)法更改。但對(duì)于一些策略(如繼續(xù)播放等),系統(tǒng)無(wú)法強(qiáng)制執(zhí)行,所以這兩種打斷類型均可能出現(xiàn)。應(yīng)用可根據(jù)音頻打斷事件(InterruptEvent)的成員變量forceType的值,獲取該事件采用的打斷類型。
在應(yīng)用播放音頻的過(guò)程中,系統(tǒng)自動(dòng)為音頻流執(zhí)行申請(qǐng)焦點(diǎn)、持有焦點(diǎn)、釋放焦點(diǎn)等動(dòng)作,當(dāng)發(fā)生音頻打斷事件時(shí),系統(tǒng)強(qiáng)制對(duì)音頻流執(zhí)行暫停、停止、降低音量、恢復(fù)音量等操作,并向應(yīng)用發(fā)送音頻打斷事件(InterruptEvent)回調(diào)。由于系統(tǒng)會(huì)強(qiáng)制改變音頻流狀態(tài),為了維持應(yīng)用和系統(tǒng)的狀態(tài)一致性,保證良好的用戶體驗(yàn),推薦應(yīng)用監(jiān)聽(tīng)音頻打斷事件,并在收到音頻打斷事件(InterruptEvent)時(shí)做出相應(yīng)處理。
對(duì)于一些系統(tǒng)無(wú)法強(qiáng)制執(zhí)行的操作(例如音頻流繼續(xù)播放的場(chǎng)景),會(huì)向應(yīng)用發(fā)送包含了共享打斷類型的音頻打斷事件,由應(yīng)用自行執(zhí)行相應(yīng)操作,此時(shí)應(yīng)用可以選擇執(zhí)行或忽略,系統(tǒng)不會(huì)干涉。
在應(yīng)用播放音頻時(shí),推薦應(yīng)用監(jiān)聽(tīng)音頻打斷事件,當(dāng)音頻打斷事件發(fā)生時(shí),系統(tǒng)會(huì)根據(jù)預(yù)設(shè)策略,對(duì)音頻流做出相應(yīng)的操作,并針對(duì)狀態(tài)發(fā)生改變的音頻流,向所屬的應(yīng)用發(fā)送音頻打斷事件。
應(yīng)用收到音頻打斷事件后,需根據(jù)其內(nèi)容提示,做出相應(yīng)的處理,避免出現(xiàn)應(yīng)用狀態(tài)與預(yù)期效果不一致的問(wèn)題。
監(jiān)聽(tīng)音頻打斷事件的方法:
- let isPlay; // 是否正在播放,實(shí)際開(kāi)發(fā)中,對(duì)應(yīng)與音頻播放狀態(tài)相關(guān)的模塊
- let isDucked; //是否降低音量,實(shí)際開(kāi)發(fā)中,對(duì)應(yīng)與音頻音量相關(guān)的模塊
- let started; // 標(biāo)識(shí)符,記錄“開(kāi)始播放(start)”操作是否成功
- async function onAudioInterrupt(){
- // 此處以使用AudioRenderer開(kāi)發(fā)音頻播放功能舉例,變量audioRenderer即為播放時(shí)創(chuàng)建的AudioRenderer實(shí)例。
- audioRenderer.on('audioInterrupt', async(interruptEvent) => {
- // 在發(fā)生音頻打斷事件時(shí),audioRenderer收到interruptEvent回調(diào),此處根據(jù)其內(nèi)容做相應(yīng)處理
- // 先讀取interruptEvent.forceType的類型,判斷系統(tǒng)是否已強(qiáng)制執(zhí)行相應(yīng)操作
- // 再讀取interruptEvent.hintType的類型,做出相應(yīng)的處理
- if (interruptEvent.forceType === audio.InterruptForceType.INTERRUPT_FORCE) {
- // 強(qiáng)制打斷類型(INTERRUPT_FORCE):音頻相關(guān)處理已由系統(tǒng)執(zhí)行,應(yīng)用需更新自身狀態(tài),做相應(yīng)調(diào)整
- switch (interruptEvent.hintType) {
- case audio.InterruptHint.INTERRUPT_HINT_PAUSE:
- // 此分支表示系統(tǒng)已將音頻流暫停(臨時(shí)失去焦點(diǎn)),為保持狀態(tài)一致,應(yīng)用需切換至音頻暫停狀態(tài)
- // 臨時(shí)失去焦點(diǎn):待其他音頻流釋放音頻焦點(diǎn)后,本音頻流會(huì)收到resume對(duì)應(yīng)的音頻打斷事件,到時(shí)可自行繼續(xù)播放
- isPlay = false; // 此句為簡(jiǎn)化處理,代表應(yīng)用切換至音頻暫停狀態(tài)的若干操作
- break;
- case audio.InterruptHint.INTERRUPT_HINT_STOP:
- // 此分支表示系統(tǒng)已將音頻流停止(永久失去焦點(diǎn)),為保持狀態(tài)一致,應(yīng)用需切換至音頻暫停狀態(tài)
- // 永久失去焦點(diǎn):后續(xù)不會(huì)再收到任何音頻打斷事件,若想恢復(fù)播放,需要用戶主動(dòng)觸發(fā)。
- isPlay = false; // 此句為簡(jiǎn)化處理,代表應(yīng)用切換至音頻暫停狀態(tài)的若干操作
- break;
- case audio.InterruptHint.INTERRUPT_HINT_DUCK:
- // 此分支表示系統(tǒng)已將音頻音量降低(默認(rèn)降到正常音量的20%),為保持狀態(tài)一致,應(yīng)用需切換至降低音量播放狀態(tài)
- // 若應(yīng)用不接受降低音量播放,可在此處選擇其他處理方式,如主動(dòng)暫停等
- isDucked = true; // 此句為簡(jiǎn)化處理,代表應(yīng)用切換至降低音量播放狀態(tài)的若干操作
- break;
- case audio.InterruptHint.INTERRUPT_HINT_UNDUCK:
- // 此分支表示系統(tǒng)已將音頻音量恢復(fù)正常,為保持狀態(tài)一致,應(yīng)用需切換至正常音量播放狀態(tài)
- isDucked = false; // 此句為簡(jiǎn)化處理,代表應(yīng)用切換至正常音量播放狀態(tài)的若干操作
- break;
- default:
- break;
- }
- } else if (interruptEvent.forceType === audio.InterruptForceType.INTERRUPT_SHARE) {
- // 共享打斷類型(INTERRUPT_SHARE):應(yīng)用可自主選擇執(zhí)行相關(guān)操作或忽略音頻打斷事件
- switch (interruptEvent.hintType) {
- case audio.InterruptHint.INTERRUPT_HINT_RESUME:
- // 此分支表示臨時(shí)失去焦點(diǎn)后被暫停的音頻流此時(shí)可以繼續(xù)播放,建議應(yīng)用繼續(xù)播放,切換至音頻播放狀態(tài)
- // 若應(yīng)用此時(shí)不想繼續(xù)播放,可以忽略此音頻打斷事件,不進(jìn)行處理即可
- // 繼續(xù)播放,此處主動(dòng)執(zhí)行start(),以標(biāo)識(shí)符變量started記錄start()的執(zhí)行結(jié)果
- await audioRenderer.start().then(async function () {
- started = true; // start()執(zhí)行成功
- }).catch((err) => {
- started = false; // start()執(zhí)行失敗
- });
- // 若start()執(zhí)行成功,則切換至音頻播放狀態(tài)
- if (started) {
- isPlay = true; // 此句為簡(jiǎn)化處理,代表應(yīng)用切換至音頻播放狀態(tài)的若干操作
- } else {
- // 音頻繼續(xù)播放執(zhí)行失敗
- }
- break;
- default:
- break;
- }
- }
- });
- }
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: