cocos creater音频播放失败 || 不回调 || 卡死 || 鸿蒙

问题背景

  1. 开发过程中 未发现问题

  2. 线上 部分鸿蒙用户反馈: 页面卡死没反应 || 页面不能继续下一步

  3. so: 问题有可能是 音频没播出来, 或者回调没回来, 或者 获取音频的时长错误

测试现场1

  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.
    
  2. 上边的数据可以看到: E/libOpenSLES: Error after prepare: 1

  3. 查找相关资料 : https://www.twblogs.net/a/5c83723dbd9eee35fc13cb3e/?lang=zh-cn

  4. 查阅资料可知:

    (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)的问题又会导致回调不正确。
    
  5. 所以, 现在分析错误原因: 是因为调用关系, 或者别的位置原因 导致音频播放失败

测试现场1 解决方案
  1. 由于 代码中频繁的调用 cc.audioEngine.stopAll

  2. 这个错误 是 io 还挺快的鸿蒙机器上发现的

  3. 怀疑 stopAll 和 play 调用时间不确定。 stop 还未完成 直接调play 导致播放失败

  4. 顺着这个思路 尝试解决的方案 就是

    1. 切换场景 和 切换页面 调用 stopAll 之后 等待 0.1s 在初始化场景
    2. 0.1s 用户感知上 未见明显延迟
    

测试现场2

  1. 测试现场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
    
  2. 表现为: 页面不能点击 动画不播放 , 连接V8 调试模式 连接失败

  3. 怀疑 V8 引擎崩溃 或者卡死

  4. 但是 查看上述 log 发现

    libOpenSLES: frameworks/wilhelm/src/android/AudioPlayer_to_android.cpp:889: pthread_mutex_lock_timeout_np returned 110
    
  5. 所以 最后怀疑: 音频线程死锁,把主线程 卡死

  6. 查找资料: https://developer.aliyun.com/article/580467

  7. 查找资料:https://forum.cocos.org/t/topic/115287 论坛中有人提到:卡死的问题我也遇到过,是短时间内停止、播放音效导致的,上层做下管理,避免这种情况的出现。

  8. 结合 复现机器, io 很慢,

  9. 所以 分析原因: 有可能是 因为io慢, 音频加载的时间变长, 刚播放 就调用 stop ,导致音频线程锁死

测试现场2 解决方案
  1. 由于 代码中频繁的调用 cc.audioEngine.stopAll

  2. 这个错误 是 io 非常慢的鸿蒙机器 发现的

  3. 音频加载的时间变长, 刚播放 就调用 stop ,导致音频线程锁死

  4. 顺着这个思路 尝试解决的方案 就是

    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)
            }
        }
    
    

From 2023-04-11

随着 chatgpt的爆火 把错误日志丢给chatgpt试试

12-30 15:06:03.013   725  2075 I AF::TrackHandle: OpPlayAudio: track:184 usage:1 not muted
12-30 15:06:03.013   725  2075 E AudioFlinger: createTrack_l() initCheck failed -12; no control block?
12-30 15:06:03.015   997 20097 E IAudioFlinger: createTrack returned error -12
12-30 15:06:03.015   997 20097 E AudioTrack: createTrack_l(0): AudioFlinger could not create track, status: -12 output 0
12-30 15:06:03.015   997 20097 E AudioSink: Unable to create audio track
12-30 15:06:03.015   997 20097 D AudioTrack: gather(): no metrics gathered, track status=-12
12-30 15:06:03.015   997 20097 W NuPlayerRenderer: openAudioSink: non offloaded open failed status: -19
12-30 15:06:03.015   997 20097 W NuPlayerRenderer: onDrainAudioQueue(): audio sink is not ready
12-30 15:06:03.015   997 20098 E NuPlayerDecoder: Renderer reported 0xffffffed when changing audio output format
12-30 15:06:03.015   997 20095 E NuPlayer: received error(0xffffffed) from audio decoder, flushing(0), now shutting down
12-30 15:06:03.015   997 20099 I MediaCodec: kWhatFlush processing is complete
12-30 15:06:03.015  3204 20093 E libOpenSLES: Error after prepare: 1
12-30 15:06:03.015   997 20099 I CCodecBufferChannel: [c2.android.mp3.decoder#492] flush
12-30 15:06:03.015   997 20099 D CCodecBuffers: [c2.android.mp3.decoder#492:1D-Output.Impl[N]] Client returned a buffer it does not own according to our record: 0
12-30 15:06:03.016   997 20099 D CCodecBuffers: [c2.android.mp3.decoder#492:1D-Output.Impl[N]] Client returned a buffer it does not own according to our record: 1
12-30 15:06:03.016   997 20099 D CCodecBuffers: [c2.android.mp3.decoder#492:1D-Output.Impl[N]] Client returned a buffer it does not own according to our record: 2
12-30 15:06:03.016   997 20099 I MediaCodec: Start Processing kWhatFlushCompleted
12-30 15:06:03.017   997 20101 D BufferPoolAccessor: buffer invalidation added bp:125 1
12-30 15:06:03.018  2506  3226 I DeviceStateService: event is too short, not process app: com.zuoyebang.bangbangshizi mediacodec action.

得到的回答是

上述log显示的是Android设备在进行音频播放时出现的一系列错误信息。它们的含义如下:

I AF::TrackHandle: OpPlayAudio: track:184 usage:1 not muted 表示一个音频轨道正在被播放,且未被静音;
E AudioFlinger: createTrack_l() initCheck failed -12; no control block? 表示音频播放引擎(AudioFlinger)创建音频轨道失败,错误码为-12,没有找到控制块;
E IAudioFlinger: createTrack returned error -12 表示音频播放引擎创建音频轨道失败,错误码为-12;
E AudioTrack: createTrack_l(0): AudioFlinger could not create track, status: -12 output 0 表示创建音频轨道的操作失败,输出错误码为-12;
E AudioSink: Unable to create audio track 表示音频播放引擎无法创建音频轨道;
D AudioTrack: gather(): no metrics gathered, track status=-12 表示音频轨道创建失败导致采集不到度量数据;
W NuPlayerRenderer: openAudioSink: non offloaded open failed status: -19 表示音频播放器(NuPlayerRenderer)的开放音频输出(AudioSink)失败,错误码为-19;
W NuPlayerRenderer: onDrainAudioQueue(): audio sink is not ready 表示音频播放器无法正常采集音频数据,因为音频输出并未准备就绪;
E NuPlayerDecoder: Renderer reported 0xffffffed when changing audio output format 表示更改音频输出格式时音频解码器(NuPlayerDecoder)报告了错误;
E NuPlayer: received error(0xffffffed) from audio decoder, flushing(0), now shutting down 表示音频解码器收到了错误报告,并且准备关闭应用;
I MediaCodec: kWhatFlush processing is complete 表示音频解码器已经完成清除缓存的操作;
E libOpenSLES: Error after prepare: 1 表示OpenSLES库准备出现错误;
I CCodecBufferChannel: [c2.android.mp3.decoder#492] flush 表示解码器缓存通道将要被清空;
D CCodecBuffers: [c2.android.mp3.decoder#492:1D-Output.Impl[N]] Client returned a buffer it does not own according to our record: 0/1/2 表示解码器缓存通道收到了客户端返回不属于自己的缓存对象或偏移量的错误信息;
I MediaCodec: Start Processing kWhatFlushCompleted 表示解码器完成清除缓存的操作;
D BufferPoolAccessor: buffer invalidation added bp:125 1 表示缓冲池出现问题。
综上所述,这些错误可能是由设备的音频硬件或驱动程序发生问题、应用程序本身出现功能问题或权限不足、音频文件格式不正确等原因引起的。解决方法包括检查设备硬件,重新安装、更新应用程序,确保网络连接,等等。

这个分析就很明显了。结合我们自己的代码 准备先把audio的双声道 先压成单声道 试试 后续有进展 接着同步

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐