From 64c0c621bca6e84f76acfbf24ad2d5a795d7b71b Mon Sep 17 00:00:00 2001 From: lanterngamescn Date: Sat, 27 Jun 2026 18:19:21 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E5=BD=95=E9=9F=B3):=20gameui=5Fplay=5Fvoic?= =?UTF-8?q?e/stop=5Fvoice=20=E5=AF=B9=E9=BD=90=20Android=20play()=20?= =?UTF-8?q?=E6=97=B6=E6=9C=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit play_voice 改为进入 mediaTypeAudio 即立刻同步回调(对齐 Android play()在播放前调), 不再等 AVPlayer prepared(网络AMR延迟致动画起得晚/疑似没调);打断旧语音补发旧 user 的 stop_voice;创建失败也补 stop_voice;抽出 endVoice 统一收尾(完成/出错)防重复。 Co-Authored-By: Claude Opus 4.8 (1M context) --- .../src/main/ets/providers/AudioProvider.ets | 34 ++++++++++++++----- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/feature_capabilities/src/main/ets/providers/AudioProvider.ets b/feature_capabilities/src/main/ets/providers/AudioProvider.ets index 3544a42..2d3b2a8 100644 --- a/feature_capabilities/src/main/ets/providers/AudioProvider.ets +++ b/feature_capabilities/src/main/ets/providers/AudioProvider.ets @@ -134,14 +134,21 @@ export class AudioProvider implements CapabilityProvider { return; } const user: string = req.user; + // 打断正在播的旧语音:先通知 H5 停旧座位动画,再释放(对齐"同一时刻只播一条")。 + if (this.voicePlayer !== undefined && this.currentVoiceUser !== '') { + this.bridge?.callHandler(OutboundHandlers.GameUiStopVoice, this.currentVoiceUser); + } this.releaseVoice(); + // 对齐 Android play():进入即立刻同步通知 H5 开始播放(座位说话动画),再创建播放器; + // 不等到 prepared 才报——网络 AMR 加载可能延迟数百 ms,晚报会被认为"没调/动画起得晚"。 + this.currentVoiceUser = user; + this.bridge?.callHandler(OutboundHandlers.GameUiPlayVoice, user); media.createAVPlayer().then((player: media.AVPlayer) => { - if (this.disposed) { - player.release(); // 创建期间已销毁:直接释放,勿播放/勿挂回调(防泄漏 + 打已弃桥) + if (this.disposed || this.currentVoiceUser !== user) { + player.release(); // 创建期间已销毁或已被新语音取代:释放孤儿播放器(旧 user 的 stop 已发) return; } this.voicePlayer = player; - this.currentVoiceUser = user; player.on('stateChange', (state: string) => { if (state === 'initialized') { player.prepare(); @@ -149,19 +156,28 @@ export class AudioProvider implements CapabilityProvider { player.loop = false; player.setVolume(this.effVolume()); player.play(); - this.bridge?.callHandler(OutboundHandlers.GameUiPlayVoice, user); } else if (state === 'completed') { - this.bridge?.callHandler(OutboundHandlers.GameUiStopVoice, user); - this.releaseVoice(); + this.endVoice(user); // 播放完成:gameui_stop_voice + 释放 } }); player.on('error', (e: BusinessError) => { this.log.w(`voice play error: ${e.code} ${e.message}`); - this.bridge?.callHandler(OutboundHandlers.GameUiStopVoice, user); - this.releaseVoice(); + this.endVoice(user); }); player.url = req.audiourl; - }).catch((e: BusinessError) => this.log.w(`createAVPlayer(voice) failed: ${e.message}`)); + }).catch((e: BusinessError) => { + this.log.w(`createAVPlayer(voice) failed: ${e.message}`); + this.endVoice(user); // 创建失败也补 stop_voice,避免座位动画卡在"说话中" + }); + } + + /** 语音播放完成/出错:通知 H5 停座位动画(gameui_stop_voice) + 释放播放器。一次性,防重复。 */ + private endVoice(user: string): void { + if (this.currentVoiceUser !== user) { + return; // 已被新语音取代或已结束 + } + this.bridge?.callHandler(OutboundHandlers.GameUiStopVoice, user); + this.releaseVoice(); } /** 播放本地音效/背景乐://assets/wav/。isloop<0 停止该 src。 */