uniapp音频管理开发

141 阅读1分钟

场景

uniapp播放音频Uni.createInnerAudio方法在ios某些机型报错,为此使用uni.getBackgroundAudioManager方法来兼容。

直接上代码

<template>
  <!-- 音频播放器组件 -->
  <view>
    <view v-if="audioUrl" class="flex justify-between align-center audio">
      <view class="mr-3" @click="audioPlay(audioId)">
        {{ isPlaying ? "点击暂停" : "点击播放" }}
        <!-- <image src="@/static/daily-supervision/play.png" class="icon" v-show="!isPlaying"></image>
      <image src="@/static/daily-supervision/pause.png" class="icon" v-show="isPlaying"></image> -->
      </view>
      <view class="flex-1">
        <slider @change="changeAudio" :activeColor="activeColor" :min="0" :max="duration" :value="currentTime.toFixed(0)" :step="0.1"></slider>
      </view>
      <!-- <view class='ml-3'>{{getTime(Math.round(currentTime))}}</view> -->
      <view class="ml-3">{{ getTime(Math.round(currentTime)) }}/{{ getTime(Math.round(duration)) }}</view>
    </view>
  </view>
</template>

<script>
let innerAudioContext = null;
let bgAudioManager = null;
export default {
  data() {
    return {
      currentTime: 0,
      duration: 0,
      totalDuration: 0,
      useBackgroundAudioManager: false,
      isPlaying: false,
      flag: true,
      res: "",
      autoPlay: false,
    };
  },
  props: {
    audioUrl: String,
    activeColor: {
      type: String,
      default: "#0E7EFC",
    },
    autoPlay: {
      type: Boolean,
      default: true,
    },
    title: {
      type: String,
      default: "暂无",
    },
    singer: {
      type: String,
      default: "暂无",
    },
    coverImgUrl: {
      type: String,
      default: "https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/music-a.png",
    },
    audioId: [String, Number],
  },
  created() {
    this.innerAudioContextInit();
    // this.backgroundAudioInit();
  },
  methods: {
    innerAudioContextInit() {
      if (innerAudioContext) return;
      console.log("音频-innerAudioContextInit");
      innerAudioContext = uni.createInnerAudioContext();
      innerAudioContext.src = this.audioUrl;
      innerAudioContext.play();
      this.onCanplay();
      this.onPlay();
      this.onTimeUpdate();
      this.onEnded();
      this.onErrorHandle();
      uni.setInnerAudioOption({
        obeyMuteSwitch: false,
      });

      // uni.$on("stop", (id) => {
      //   if (id && id != this.audioId) {
      //     innerAudioContext.stop();
      //     this.isPlaying = false;
      //   } else if (!id) {
      //     innerAudioContext.stop();
      //     this.isPlaying = false;
      //   }
      // });

      // uni.$on("BackgroundAudioStop", (id) => {
      //   if (id && id != this.audioId) {
      //     innerAudioContext.stop();
      //     this.isPlaying = false;
      //   } else if (!id) {
      //     innerAudioContext.stop();
      //     this.isPlaying = false;
      //   }
      // });
    },

    backgroundAudioInit() {
      if (bgAudioManager) return;
      console.log("音频-backgroundAudioInit");
      bgAudioManager = uni.getBackgroundAudioManager();
      bgAudioManager.title = this.title;
      bgAudioManager.singer = this.singer;
      bgAudioManager.coverImgUrl = this.coverImgUrl;
      bgAudioManager.src = this.audioUrl;
      // if (this.autoPlay) {
      //   this.isPlaying = true;
      //   bgAudioManager.play();
      // }

      this.onBgCanplay();
      this.onBgTimeUpdate();
      this.onBgEnded();
      this.onBgStop();
    },

    audioPlay(id) {
      //点击播放
      let audioId = id;
      if (this.useBackgroundAudioManager) {
        console.log(bgAudioManager, "bgAudioManager");
        // if (this.flag) {
        //   bgAudioManager.src = this.audioUrl;
        //   this.flag = false;
        // }
        if (!bgAudioManager.src) {
          bgAudioManager.title = "云南白药电子书";
          bgAudioManager.singer = "暂无";
          bgAudioManager.coverImgUrl = "https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/music-a.png";
          bgAudioManager.src = this.audioUrl;
        }

        if (!bgAudioManager.paused) {
          bgAudioManager.pause();
        } else {
          bgAudioManager.play();
          // uni.$emit('BackgroundAudioStop',id);
          // if (!bgAudioManager.src) {
          //   // 解决暂停后播放从新开始播放bug
          //   bgAudioManager.src = this.audioUrl;
          // } else {
          //   bgAudioManager.play();
          // }
        }
        this.isPlaying = !this.isPlaying;
      } else {
        console.log(innerAudioContext, "innerAudioContext");
        if (!innerAudioContext.paused) {
          innerAudioContext.pause();
          this.isPlaying = !this.isPlaying;
        } else {
          // uni.$emit("stop", id);
          if (!innerAudioContext.src) {
            // 解决暂停后播放从新开始播放bug
            innerAudioContext.src = this.audioUrl;
          } else {
            innerAudioContext.play();
          }
          this.isPlaying = !this.isPlaying;
        }
      }
    },

    onPlay() {
      innerAudioContext.onPlay(() => {
        console.log("音频-onPlay-开始播放", innerAudioContext);
      });
    },

    onCanplay() {
      innerAudioContext.onCanplay(() => {
        console.log("音频-onCanplay-可播放状态", innerAudioContext);
        this.duration = innerAudioContext.duration;
        this.totalDuration = innerAudioContext.duration;
      });
    },
    onTimeUpdate() {
      innerAudioContext.onTimeUpdate(() => {
        if (!Number.isFinite(innerAudioContext.duration)) {
          this.duration = innerAudioContext.currentTime + 10;
          this.currentTime = innerAudioContext.currentTime;
        } else {
          this.duration = innerAudioContext.duration;
          this.currentTime = innerAudioContext.currentTime;
        }
      });
    },

    onEnded() {
      innerAudioContext.onEnded(() => {
        console.log("音频-onEnded-播放结束");
        this.isPlaying = false;
        this.currentTime = 0;
        innerAudioContext.src = this.audioUrl;
      });
    },

    onErrorHandle() {
      innerAudioContext.onError((res) => {
        console.log("音频-onErrorHandle-播放失败");
        this.res = JSON.stringify(res);
        this.useBackgroundAudioManager = true;
        // bgAudioManager.play();
        this.backgroundAudioInit();
      });
    },

    /**
     * uni.getBackgroundAudioManager事件监听
     */
    onBgCanplay() {
      bgAudioManager.onCanplay(() => {
        console.log("音频-onBgCanplay-背景可播放状态");
        this.duration = bgAudioManager.duration;
        this.totalDuration = bgAudioManager.duration;
        if (!this.autoPlay) {
          innerAudioContext.pause();
        }
      });
    },
    onBgTimeUpdate() {
      bgAudioManager.onTimeUpdate(() => {
        if (!Number.isFinite(bgAudioManager.duration)) {
          this.duration = bgAudioManager.currentTime + 10;
          this.currentTime = bgAudioManager.currentTime;
        } else {
          this.duration = bgAudioManager.duration;
          this.currentTime = bgAudioManager.currentTime;
        }
      });
    },
    onBgEnded() {
      bgAudioManager.onEnded(() => {
        console.log("音频-onBgEnded-背景播放end");
        this.isPlaying = false;
        this.currentTime = 0;
        this.flag = true;
      });
    },
    onBgStop() {
      bgAudioManager.onStop(() => {
        console.log("音频-onBgStop-背景播放stop");
        this.isPlaying = false;
        this.currentTime = 0;
        this.flag = true;
        console.log("onBgStop");
      });
    },

    changeAudio(e) {
      let context = this.useBackgroundAudioManager ? bgAudioManager : innerAudioContext;
      context.seek(e.detail.value);
    },

    getTime(time) {
      let m = parseInt(time / 60);
      let s = time % 60;
      return this.towNum(m) + ":" + this.towNum(s);
    },
    towNum(num) {
      if (num >= 10) {
        return num;
      } else {
        return "0" + num;
      }
    },
  },

  beforeDestroy() {
    if (innerAudioContext) innerAudioContext.destroy();
    if (bgAudioManager) bgAudioManager.stop();
  },
};
</script>

<style>
.audio {
  background: #f4f4f4;
  padding: 20rpx;
}

.icon {
  width: 60rpx;
  height: 60rpx;
}

.flex {
  display: flex;
  flex-direction: row;
}

.justify-between {
  justify-content: between;
}

.align-center {
  align-items: center;
}

.flex-1 {
  flex: 1;
}

.ml-3 {
  margin-left: 30rpx;
}

.mr-3 {
  margin-right: 30rpx;
}
</style>

注意

  1. 音频必须使用标准map3格式
  2. getBackgroundAudioManager方法必须设置title才能播放

  3. 注意页面销毁对getBackgroundAudioManager控制