cocos creater音频播放失败 || 不回调 || 卡死 || 鸿蒙
问题背景
-
开发过程中 未发现问题
-
线上 部分鸿蒙用户反馈: 页面卡死没反应 || 页面不能继续下一步
-
so: 问题有可能是 音频没播出来, 或者回调没回来, 或者 获取音频的时长错误
测试现场1
-
经过测试的重复复现问题 得到一个现场数据 如下
2022-08-09 17:10:54.792 21491-21981/com.zuoyebang.bangbangshizi V/AudioEngineImpl: play2d, _audioPlayers.size=0 2022-08-09 17:10:54.792 21491-21981/com.zuoyebang.bangbangshizi V/AudioPlayerProvider: (@assets/assets/bundle_common/native/5b/5b1f43ed-ff53-42f2-ae62-b8770d2533ad.mp3) file size: 979728 2022-08-09 17:10:54.792 21491-21981/com.zuoyebang.bangbangshizi V/UrlAudioPlayer: Current UrlAudioPlayer instance count: 1 2022-08-09 17:10:54.792 21491-21981/com.zuoyebang.bangbangshizi V/UrlAudioPlayer: UrlAudioPlayer::prepare: @assets/assets/bundle_common/native/5b/5b1f43ed-ff53-42f2-ae62-b8770d2533ad.mp3, SL_DATALOCATOR_ANDROIDFD, 147, 190559016, 979728 2022-08-09 17:10:54.792 21491-21981/com.zuoyebang.bangbangshizi I/AudioSystem: getDeviceConnectionState , Connecting to the Bluetooth device 2022-08-09 17:10:54.792 21491-21981/com.zuoyebang.bangbangshizi I/IAudioPolicyService: getDeviceConnectionState, BpAudioPolicy: Bluetooth device 2022-08-09 17:10:54.796 21491-21981/com.zuoyebang.bangbangshizi V/AudioEngineImpl: play2d, _audioPlayers.size=1 2022-08-09 17:10:54.796 21491-21981/com.zuoyebang.bangbangshizi V/AudioPlayerProvider: (@assets/assets/bundle_common/native/be/be1894f3-7064-4479-94fe-cfaabe1a07c6.mp3) file size: 202477 2022-08-09 17:10:54.796 21491-21981/com.zuoyebang.bangbangshizi V/UrlAudioPlayer: Current UrlAudioPlayer instance count: 2 2022-08-09 17:10:54.796 21491-21981/com.zuoyebang.bangbangshizi V/UrlAudioPlayer: UrlAudioPlayer::prepare: @assets/assets/bundle_common/native/be/be1894f3-7064-4479-94fe-cfaabe1a07c6.mp3, SL_DATALOCATOR_ANDROIDFD, 151, 387146732, 202477 2022-08-09 17:10:54.796 21491-21981/com.zuoyebang.bangbangshizi I/AudioSystem: getDeviceConnectionState , Connecting to the Bluetooth device 2022-08-09 17:10:54.796 21491-21981/com.zuoyebang.bangbangshizi I/IAudioPolicyService: getDeviceConnectionState, BpAudioPolicy: Bluetooth device 2022-08-09 17:10:54.880 21491-28436/com.zuoyebang.bangbangshizi E/libOpenSLES: Error after prepare: 1 2022-08-09 17:10:54.885 21491-28433/com.zuoyebang.bangbangshizi E/libOpenSLES: Error after prepare: 1 2022-08-09 17:11:01.042 21491-22407/com.zuoyebang.bangbangshizi E/NLog: start or restart send timer, sendInterval=30.
-
上边的数据可以看到: E/libOpenSLES: Error after prepare: 1
-
查找相关资料 : https://www.twblogs.net/a/5c83723dbd9eee35fc13cb3e/?lang=zh-cn
-
查阅资料可知:
(1) E/libOpenSLES(25131): Too many objects (2) E/libOpenSLES: Error after prepare: 1 第一个, 是SLPlayItf对象没有及时销毁,不同的平台SLPlayItf同时支持的数量不同,大约是2-10左右,所以音频播放完成之后,需要及时销毁。否则,出现(1)的错误,就会播放不出来声音,到一定程度就会导致崩溃。 第二个, 是因为播放文件的格式OpenSLES不支持,或是文件有问题,无法正确播放。并且出现这种问题后,会让SLPlayItf的回调函数无法正确执行,最终导致SLPlayItf越来越多,从而出现(1)的情况和结局。 那么,解决(1)的问题,就是在音频播放完成后及时销毁,我们可以使用回调来实现,但是(2)的问题又会导致回调不正确。
-
所以, 现在分析错误原因: 是因为调用关系, 或者别的位置原因 导致音频播放失败
测试现场1 解决方案
-
由于 代码中频繁的调用 cc.audioEngine.stopAll
-
这个错误 是 io 还挺快的鸿蒙机器上发现的
-
怀疑 stopAll 和 play 调用时间不确定。 stop 还未完成 直接调play 导致播放失败
-
顺着这个思路 尝试解决的方案 就是
1. 切换场景 和 切换页面 调用 stopAll 之后 等待 0.1s 在初始化场景 2. 0.1s 用户感知上 未见明显延迟
测试现场2
-
测试现场2 是 比较老的 鸿蒙pad 上发现的
08-08 15:29:06.345 588 806 I APM_AudioPolicyManager: getNewOutputDevice() selected device 2 connectdeDevices(10002) 08-08 15:29:06.346 588 806 D APM::AudioOutputDescriptor: stop, profile name: primary out, curActiveCount: 0 08-08 15:29:06.346 13482 14264 E libOpenSLES: frameworks/wilhelm/src/android/AudioPlayer_to_android.cpp:889: pthread_mutex_lock_timeout_np returned 110 08-08 15:29:06.346 817 894 I dubaid : [AudioHandler.cpp] stopSession# Failed to find audio session: 3753 08-08 15:29:06.354 9599 9893 W ContentSensor_AudioInfoCapture: No need notify, resultList is empty 08-08 15:29:06.354 9599 9893 W ContentSensor_AudioInfoCapture: insert info list is empty 08-08 15:29:06.354 9599 9893 W ContentSensor_AudioInfoCapture: insert info list is empty 08-08 15:29:06.372 2494 3160 D nStackXCoAP: ParseServiceDiscover:[416] :new device join 08-08 15:29:06.372 2494 3160 E nStackXDFinder: DatabaseAllocRecord:[136] :DB max limit exceeded maxcnt:20, usecnt:20 08-08 15:29:06.372 2494 3160 E nStackXDFinder: CreateNewDevice:[227] :Failed to allocate device info 08-08 15:29:06.376 13482 14264 E libOpenSLES: frameworks/wilhelm/src/android/AudioPlayer_to_android.cpp:889: pthread_mutex_lock_timeout_np returned 110 08-08 15:29:06.382 9599 9893 W ContentSensor_AudioInfoCapture: No need notify, resultList is empty 08-08 15:29:06.382 9599 9893 W ContentSensor_AudioInfoCapture: insert info list is empty 08-08 15:29:06.382 9599 9893 W ContentSensor_AudioInfoCapture: insert info list is empty 08-08 15:29:06.384 9599 9893 W ContentSensor_AudioInfoCapture: No need notify, resultList is empty 08-08 15:29:06.384 9599 9893 W ContentSensor_AudioInfoCapture: insert info list is empty 08-08 15:29:06.384 9599 9893 W ContentSensor_AudioInfoCapture: insert info list is empty 08-08 15:29:06.385 1589 1598 I system_server: Background concurrent copying GC freed 826201(24MB) AllocSpace objects, 3(60KB) LOS objects, 40% free, 34MB/58MB, paused 839us total 209.358ms 08-08 15:29:06.386 13482 14263 D : TrackPlayerBase::~TrackPlayerBase() 08-08 15:29:06.386 13482 14263 D : PlayerBase::~PlayerBase() 08-08 15:29:06.387 13482 14263 D : TrackPlayerBase::~TrackPlayerBase() 08-08 15:29:06.387 13482 14263 D : PlayerBase::~PlayerBase() 08-08 15:29:06.399 9599 9893 W ContentSensor_AudioInfoCapture: No need notify, resultList is empty 08-08 15:29:06.399 9599 9893 W ContentSensor_AudioInfoCapture: insert info list is empty 08-08 15:29:06.399 9599 9893 W ContentSensor_AudioInfoCapture: insert info list is empty 08-08 15:29:06.416 13482 14264 E libOpenSLES: frameworks/wilhelm/src/android/AudioPlayer_to_android.cpp:889: pthread_mutex_lock_timeout_np returned 110 08-08 15:29:06.433 1589 1815 I HwFingersSnapshooter: handleMotionEvent first finger(0) touch down at (106.9443,115.90342) 08-08 15:29:06.467 13482 14264 E libOpenSLES: frameworks/wilhelm/src/android/AudioPlayer_to_android.cpp:889: pthread_mutex_lock_timeout_np returned 110
-
表现为: 页面不能点击 动画不播放 , 连接V8 调试模式 连接失败
-
怀疑 V8 引擎崩溃 或者卡死
-
但是 查看上述 log 发现
libOpenSLES: frameworks/wilhelm/src/android/AudioPlayer_to_android.cpp:889: pthread_mutex_lock_timeout_np returned 110
-
所以 最后怀疑: 音频线程死锁,把主线程 卡死
-
查找资料: https://developer.aliyun.com/article/580467
-
查找资料:https://forum.cocos.org/t/topic/115287 论坛中有人提到:卡死的问题我也遇到过,是短时间内停止、播放音效导致的,上层做下管理,避免这种情况的出现。
-
结合 复现机器, io 很慢,
-
所以 分析原因: 有可能是 因为io慢, 音频加载的时间变长, 刚播放 就调用 stop ,导致音频线程锁死
测试现场2 解决方案
-
由于 代码中频繁的调用 cc.audioEngine.stopAll
-
这个错误 是 io 非常慢的鸿蒙机器 发现的
-
音频加载的时间变长, 刚播放 就调用 stop ,导致音频线程锁死
-
顺着这个思路 尝试解决的方案 就是
1. 调用 cc.audioEngine.play 之后 0.1s 之内 不允许stopAll 2. 调用play之前 记录一下 当前时间戳 3. 调用 stopAll之前 判断 是否 超过记录时间戳的 0.1s 如果不够的话 等待到0.1s 再stop 记录的代码如下 public static initFuncForAudioEngine(){ let playFunc = cc.audioEngine.play cc.audioEngine.play = (clip: cc.AudioClip, loop: boolean, volume: number):number=>{ AudioUtils._lastTimeSound = new Date().getTime() return playFunc.call(cc.audioEngine, clip, loop, volume) } let playEffectFunc = cc.audioEngine.playEffect cc.audioEngine.playEffect = (clip: cc.AudioClip, loop: boolean):number=>{ AudioUtils._lastTimeSound = new Date().getTime() return playEffectFunc.call(cc.audioEngine, clip, loop) } let playMusicFunc = cc.audioEngine.playMusic cc.audioEngine.playMusic = (clip: cc.AudioClip, loop: boolean):number=>{ AudioUtils._lastTimeMusic = new Date().getTime() return playMusicFunc.call(cc.audioEngine, clip, loop) } }