展开应用主线程泳道,通过其中的子泳道H:ABILITY_OR_PAGE_SWITCH找到页面退出的部分。
在上方搜索框中输入H:AudioRenderer::Pause关键字,找到停止音频播放的部分,如果有多个H:AudioRenderer::Pause搜索结果,可通过点击搜索框右侧的箭头来找到靠近H:ABILITY_OR_PAGE_SWITCH的那一个。如下图所示可看到停止音频播放是在页面切换完成之后执行的,而应用停止音频播放时,系统侧需要时间处理,因此会有延迟。

从停止音频播放操作处看不出来是由什么触发的,但通常音频播放和停止是由应用控制的,因此可以通过查看线程的唤醒关系来确定。点击应用线程状态中的Runnable状态、查看其中WakeUp From Tid,从下图中可看到是由PlayerRequest线程唤醒的。

PlayerRequest线程是属于音频服务media_service的子线程,不属于应用部分,因此继续查看该线程的唤醒线程。
通过不断查看线程的唤醒关系,最终找到唤醒线程为主线程,从下图中可看到停止音频播放时在视频页面退出过渡完成之后才执行的,而暂停音频播放需要时间,因此会出现页面退出后声音延迟暂停的问题。

首先展开应用主线程泳道,通过其中的子泳道H:ABILITY_OR_PAGE_SWITCH找到页面退出的部分。

然后确定停止音频播放的地方,Web页面音频开始播放、发送数据、停止播放时由AudioThread线程完成的,因此在应用泳道中找到AudioThread,同时通过H:RendererInClientInner::StopAudioStream关键字来确定停止音频播放的部分。从下图中可看到停止音频播放是在页面切换完成后执行的,而暂停音频播放需要时间,因此会出现页面退出后声音延迟暂停的问题。

Web页面音频播放和暂停是由Web相关的线程控制,可搜索H:AudioOutputDevice::Stop关键字确认Web侧触发音频停止的地方,然后通过该线程的Runnable线程状态查看该线程的唤醒线程,可看到Web侧音频停止是由应用Web渲染线程在执行SetPageLifecycleState时触发。

对比SetPageLifecycleState和H:ABILITY_OR_PAGE_SWITCH,可看到SetPageLifecycleState执行在页面切换完成,由此可知页面退出后,应用Web渲染线程会更新Web页面生命周期状态,同时停止音频播放,停止音频播放是在页面切换完成后执行的,导致页面退出后声音延迟暂停的问题。

可重写onBackPress,在开始退出时就停止音频播放。
@Entry
@Component
struct VideoPage {
controller: VideoController = new VideoController();
onBackPress(): boolean | void {
this.controller.stop();
}
build() {
Column() {
Video({
src: $rawfile('sample.mp4'), // 测试需要替换成可引用到的资源
controller: this.controller
})
.size({
width: '100%',
height: '100%'
})
.autoPlay(true)
}
.height('100%')
.width('100%')
}
} import { webview } from '@kit.ArkWeb';
@Entry
@Component
struct VideoPage {
controller: webview.WebviewController = new webview.WebviewController();
onBackPress(): boolean | void {
try {
this.controller.stopAllMedia();
} catch (error) {
console.error('error: ', error);
}
}
build() {
Column() {
Web({
src: 'https://developer.huawei.com/consumer/cn/design/', // 测试需要替换成可引用到的资源
controller: this.controller
})
}
.height('100%')
.width('100%')
}
}