cocos creater 鸿蒙 音频卡死 播放失败 不回调
Posted 丶党玲儿
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cocos creater 鸿蒙 音频卡死 播放失败 不回调相关的知识,希望对你有一定的参考价值。
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)
如何在 Cocos2d 中播放音频文件的特定部分
【中文标题】如何在 Cocos2d 中播放音频文件的特定部分【英文标题】:How to play a particular portion of an audio file in Cocos2d 【发布时间】:2014-10-01 09:44:34 【问题描述】:我正在使用 SimpleAudioEngine 播放名为“myTrack.mp3”的音频文件:
[[SimpleAudioEngine sharedEngine]playBackgroundMusic:@"myTrack.mp3" loop:NO];
00:17 秒时长的音频,我播放整个文件。但现在我只需要播放时间 00:08 和 00:14 之间的部分。在 Cocos2d 中可以吗?
谢谢。
【问题讨论】:
【参考方案1】:我不熟悉 SimpleAudioEngine,但您可以使用标准的 AVQueuePlayer:
1) seekToTime。例如([_player seekToTime:CMTimeMakeWithSeconds(8.0, 1.0)]
)
2) 然后给播放器添加时间观察器:
_timeObserver = [_player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(1.0, 1.0)
queue:NULL
usingBlock:^(CMTime time)
check current duration and stop the playback.
];
【讨论】:
如果我没记错的话,CocosDenshion 在后台使用 AVAudioPlayer 进行(背景)音乐播放。不要以为可以通过简单的接口访问,必须在 CDAudioManager 之类的。 抱歉,'timeObserver' 对象类型是什么?在添加这些行时,我收到了 Mach-O 链接器错误:“架构 i386 的未定义符号:”。你能帮我吗? id timeObserver。最后你可以做 [_player removeTimeObserver:_timeObserver] 并将其设置为 nil。 i386的奇怪问题。什么符号?以上是关于cocos creater 鸿蒙 音频卡死 播放失败 不回调的主要内容,如果未能解决你的问题,请参考以下文章
cocos2d-JS 第三炮Helloworld及Cocos Creater简介(宝贵的经验!)