uni-app uni.createInnerAudioContext() seek方法在安卓下播放音频与currentTime对不上

发布于 1周前 作者 yibo5220 来自 Uni-App

uni-app uni.createInnerAudioContext() seek方法在安卓下播放音频与currentTime对不上

开发环境 版本号 项目创建方式
Windows Windows 11 家庭版 23H2 HBuilderX

产品分类:uniapp/App

PC开发环境操作系统:Windows

手机系统:Android

手机系统版本号:Android 14

手机厂商:小米

手机机型:redmi note 14 5G

页面类型:vue

vue版本:vue3

打包方式:云端

示例代码:

<template>  
  <view class="app">  
    <view>当前时间{{currentTime}}</view>  
    <view @click="seek">从48s开始播放</view>  
    <view @click="play">直接播放</view>  
  </view>  
</template>  

<script setup>  
import {ref} from 'vue';  
import {onReady} from "@dcloudio/uni-app";  
let innerAudioContext = ref();  
const currentTime = ref(0);  
let timer = null;  
onReady(() => {  
  innerAudioContext = uni.createInnerAudioContext();  
  innerAudioContext.src = "/storage/emulated/0/Android/data/com.luanmiyun.pluad/apps/__UNI__18354DE/doc/audio/1733362495043_IMPORT_2F153FA31F50E418E0A5E5465D37DFC9_1h-29m-48s_965065ab-1e85-47d0-ba9d-e9758d110dd3_12-02_周例会_项目进展与问题解决_项目管理与技术实现_项目开发与集成.mp3";  
  innerAudioContext.onPlay(() => {  
    timer && clearInterval(timer);  
    timer = setInterval(() => {  
      currentTime.value = innerAudioContext.currentTime  
    }, 100)  
  });  
});  
const seek = () => {  
  innerAudioContext.seek(48);  
  play();  
}  
const play = () => {  
  innerAudioContext.play();  
}  
</script>  

<style scoped lang="scss">  
.app{  
  height: 100%;  
  width: 100%;  
  display: flex;  
  flex-direction: column;  
  align-items: center;  
  justify-content: center;  
  view{  
    margin-top: 40rpx;  
  }  
}  
</style>

操作步骤:

操作流程:

  1. 点击“直接播放”,让音频正常播放到48-49s的时候,音频片段播放“那个本质…”的话语,这个是正常的
  2. 点击“从48s开始播放”,用seek方法跳转到48s再播,音频和时间就对不上了,“那个本质”的话语需要到57s左右才能播出来,也就是音频延迟了大约10s。用onTimeUpdate监听的currentTime却正常,只是音频和时间对不上。

预期结果:

seek之后播放的音频和正常播放的音频片段一致。

实际结果:

seek之后播放的音频慢了大概10s

bug描述:

uni.createInnerAudioContext()的seek方法在安卓端的实际播放音频内容慢了10s左右。ios正常。

测试音频超过了10兆,我贴个下载链接:https://meta.luanmiyun.com/files/demo/12-02%E5%91%A8%E4%BE%8B%E4%BC%9A%E9%A1%B9%E7%9B%AE%E8%BF%9B%E5%B1%95%E4%B8%8E%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3%E9%A1%B9%E7%9B%AE%E7%AE%A1%E7%90%86%E4%B8%8E%E6%8A%80%E6%9C%AF%E5%AE%9E%E7%8E%B0%E9%A1%B9%E7%9B%AE%E5%BC%80%E5%8F%91%E4%B8%8E%E9%9B%86%E6%88%90.mp3


1 回复

在处理 uni-app 中使用 uni.createInnerAudioContext() 播放音频时,如果发现在安卓设备上 seek 方法设置的位置与 currentTime 属性显示的位置不一致,这可能是由于音频缓冲或同步问题导致的。以下是一个简化的代码示例,展示如何使用 seek 方法并监听 timeupdate 事件来观察 currentTime 的变化,以便进行调试和进一步处理。

// 创建一个音频上下文
const innerAudioContext = uni.createInnerAudioContext();

// 设置音频源
innerAudioContext.src = 'https://example.com/audio.mp3';

// 监听音频自然播放到结束事件
innerAudioContext.onEnded(() => {
  console.log('Audio ended');
});

// 监听时间更新事件,用于观察currentTime的变化
innerAudioContext.ontimeupdate(() => {
  console.log('Current time:', innerAudioContext.currentTime);
});

// 播放音频
innerAudioContext.play();

// 假设在某个时间点,我们需要跳转到音频的某个位置
setTimeout(() => {
  const targetTime = 60; // 目标跳转时间,单位为秒
  console.log(`Seeking to ${targetTime}s`);
  innerAudioContext.seek(targetTime);
}, 5000); // 5秒后执行seek操作

// 为了进一步调试,我们可以在seek后定期检查currentTime
const checkCurrentTime = () => {
  if (innerAudioContext.currentTime !== targetTime) {
    console.log(`Expected time: ${targetTime}s, Actual time: ${innerAudioContext.currentTime}s`);
    setTimeout(checkCurrentTime, 1000); // 每秒检查一次
  } else {
    console.log('Seek completed successfully');
  }
};

// 在seek操作后立即开始检查currentTime
setTimeout(checkCurrentTime, 1000); // 稍微延迟开始检查,给seek操作一些缓冲时间

// 注意:这里的checkCurrentTime函数是一个简单的调试辅助,
// 在实际应用中,可能需要根据具体需求调整检查频率或逻辑,
// 比如增加超时机制以避免无限循环。

// 停止播放(用于测试结束或其他目的)
// innerAudioContext.stop();

在上述代码中,我们通过 setTimeout 模拟了在播放一段时间后跳转到指定时间点的操作,并通过 ontimeupdate 事件监听器来实时输出当前的播放时间。此外,还定义了一个 checkCurrentTime 函数来定期检查 currentTime 是否达到了预期的位置,这有助于诊断 seek 方法与 currentTime 不一致的问题。

请注意,由于音频缓冲和设备性能的差异,seek 操作后的 currentTime 可能会有短暂的延迟才能达到目标值。在实际应用中,应根据用户体验需求合理处理这种延迟。

回到顶部