uniapp小程序语音播报功能

小程序语音播报

背景:项目中有一个功能是小程序扫码之后进行语音播报,使用uni.createInnerAudioContext方法,并不是一帆风顺的,所以记录一下。

需要注意的点

  • 全局使用一个音频实例(uni 官方建议这种方法,因为频繁切换 src,可能会出现-99 的错误)
  • 语音播放过程中,调用uni.scanCode会中断语音
  • 据测试,ios直接播放,会出现延迟播放的情况,项目里面使用uni.downloadFile将资源下载下来,再播放可以有效缓解该问题
  • ios直接进行播放,可能是由于音频资源没准备好,可能会直接进入到onError,这时根据错误码重新调用播放即可。 碰到的两种错误信息如下:
  1. {"errMsg": "operateAudio:fail jsapi has no permission, event=operateAudio, runningState=background, permissionMsg=permission got, detail=jsapi has no permission, appId=wxd161895220febc6f", "errCode": -1}

  2. {"errMsg": "operateAudio:fail audioInstance is not set", "errCode": -1}

代码示例

ts 复制代码
import { onUnload } from "@dcloudio/uni-app";
let innerAudioContext: any = null;
// 销毁音频
const destroyAudio = () => {
  if (innerAudioContext) {
    innerAudioContext.stop();
    innerAudioContext.destroy();
    innerAudioContext = null;
  }
};
// 创建音频
const createAudio = (audioSrc: string) => {
  destroyAudio(); // 每次创建将上一个实例销毁
  innerAudioContext = uni.createInnerAudioContext();
  innerAudioContext.src = audioSrc;
  // 播放事件
  innerAudioContext.onPlay(() => {
    console.log("play audio");
  });
  // 播放结束事件
  innerAudioContext.onEnded(() => {
    console.log("ended audio");
  });
  // 播放错误事件
  innerAudioContext.onError((error: any) => {
    console.log("play audio error", error);
    // 兼容ios(估计是官方bug),可能是ios资源没准备好时,播放会发生错误返回errCode为-1,这时需要重新播放,直至播放成功
    if (error.errCode === -1) {
      createAudio(audioSrc);
    } else {
      // 比如文件不存在等情况,会进入到这个提示
      uni.showToast({
        title: "播放失败:" + error.errMsg,
        icon: "none",
      });
    }
  });
  innerAudioContext.play();
};
const downloadAudio = (fileName: string) => {
  if (!fileName) {
    return;
  }
  // 扫码失败时接口返回一个音频文件名,通过文件名拼接成完整的音频地址
  const audioUrl = "https://xxx.com/static/" + fileName;
  // 先将资源下载下来,在ios下播放速度会更快(经本人测试,不下载,直接播放,ios机型会有明显的延迟播放行为)
  uni.downloadFile({
    url: audioUrl,
    success: ({ tempFilePath }) => {
      createAudio(tempFilePath);
    },
  });
};
const onScan = () => {
    uni.scanCode({
        success(res) {
            // 扫码结果
            scanCheck(res.result);
        },
    });
};
const scanCheck = (code: string) => {
  // 发送扫码请求
  scanRequest(code)
    .then(() => {
      // 扫码成功之后,每隔1s进行一次扫码
      setTimeout(() => onScan(), 1000);
      uni.showToast({
        title:"扫码成功",
        icon:'none',
        mask:true
      }
      );
    })
    .catch((res) => {
      // 扫码失败之后,利用接口返回的文件名创建语音实例,播报音频
      downloadAudio(res.fileName);
      uni.showToast({
        title:res.msg|| "扫码失败",
        icon:'none',
        mask:true,
        duration:2000
      }
    });
};
onUnload(() => {
  // 页面卸载时销毁音频
  destroyAudio();
});
相关推荐
福兮说6 小时前
设计稿是 #4A7C6F,页面量出来是 #4B7C6F:HEX、HSL、透明度、canvas 来回转的七个坑
前端·javascript·css·canvas
郑州光合科技余经理7 小时前
海外版外卖加盟:总站与分站配送规则怎么分开管
java·开发语言·前端·后端·uni-app·php·ai编程
小呆呆6668 小时前
副业搞起来,小说,漫画,漫剧的成本优化思路
前端·后端·面试
Dovis(誓平步青云)8 小时前
浇水提醒刚弹出又消失,植物状态别只存一个百分比
开发语言·前端·javascript·pdf·ecmascript·电脑
码艺-Alimjan8 小时前
Vben Admin 新增维吾尔语 Vben-Modal的关键坑之一
前端·javascript·vue.js
可乐鸡翅yeah_9 小时前
hls.js 手动自定义 http 请求 loader,修改请求头实战
开发语言·前端·javascript·网络协议·http·ecmascript·m3u8在线
IT_陈寒9 小时前
Vite静态资源导入这个坑我帮你们踩过了
前端·人工智能·后端
广州华水科技9 小时前
大坝安全监测解决方案:单北斗GNSS形变监测系统应用与维护
前端
星光开发者10 小时前
基于决策树随机森林算法的小说推荐系统的设计与实现-计算机毕设【课程设计】78485
vue.js·算法·微信小程序·django·php·课程设计·express
yivifu10 小时前
中文古籍电子书注释集成
前端·javascript·python·beautifulsoup·epub