titio
titio
  • 发布:2026-02-27 17:18
  • 更新:2026-03-02 13:48
  • 阅读:99

uni.getBackgroundAudioManager 的offTimeUpdate不存在

分类:uni-app x

文档和示例中都使用了这个offTimeUpdate方法。但是编译报错提示属性“offTimeUpdate”在类型“BackgroundAudioManager”上不存在。

2026-02-27 17:18 负责人:无 分享
已邀请:
DCloud_UNI_yuhe

DCloud_UNI_yuhe

你好, 你的 hbuilderx 的版本号是多少

  • titio (作者)

    4.87

    2026-03-02 15:28

  • DCloud_UNI_yuhe

    回复 titio: 麻烦给一下完整的代码片段,我这里没有发现报错

    2026-03-02 18:00

  • titio (作者)

    回复 DCloud_UNI_yuhe: <script lang="uts">

    const defaultAudioUrl = "https://web-ext-storage.dcloud.net.cn/uni-app/ForElise.mp3";


    export default {

    props: {

    src: {

    type: String,

    default: defaultAudioUrl,

    },

    allowClick: {

    type: Boolean,

    default: true,

    },

    showSlider:{

    type:Boolean,

    default:true

    }

    },

    emits: ["onCanplay", "statusChange", "onPlayEnd"],

    data() {

    return {

    title: "innerAudioContext",

    currentTime: 0,

    duration: 0,

    startTime: 0,

    buffered: 0,

    volume: 1,

    isCanplay: false,

    isPlaying: false,

    isPaused: true,

    isPlayEnd: false,

    _isChanging: false,

    _audioContext: null as BackgroundAudioManager | null,

    // 自动化测试

    onSeekingTest: false,

    onSeekedTest: false,

    onWaitingTest: false,

    playbackRateChecked: true,

    onTimeUpdateCb: (res: any) => {},

    onWaitingCb: (res: any) => {},

    // 事件监听回调函数

    stopOtherAudioCb: (data: UTSJSONObject) => {},


      // 当前倍速  
    curRate: "1.0",
    // 倍速选项列表
    playbackRates: ["0.5", "0.8", "1.0", "1.25", "1.5", "2.0"],
    };

    },

    computed: {

    position() {

    return this.isPlayEnd ? 0 : this.currentTime;

    },

    // 添加进度百分比计算属性

    progressPercentage() {

    if (this.isPlayEnd) {

    return 0; // 播放结束时显示100%

    }

    if (this.duration <= 0) {

    return 0; // 防止除以0

    }

    if (this.currentTime == 0) {

    return 0.01; //防止IOS为0时不显示

    }

    return Math.round(((this.currentTime + 1) / this.duration) * 100);

    },

    },

    watch: {

    src: {

    handler(newValue: string) {

    if (this._audioContext != null && newValue != this._audioContext!.src) {

    this.setSrc(newValue);

    }

    },

    immediate: false,

    },

    },

    mounted() {

    this._audioContext = uni.getBackgroundAudioManager();

    this._audioContext.cache=true

    this._audioContext!.playbackRate=1//每次重置倍速

    console.log('执行')

    let initialSrc = this.src;

    if (initialSrc.endsWith(".crdownload")) {

    initialSrc = initialSrc.replace(".crdownload", "") + ".mp3";

    }

    this._audioContext!.src = initialSrc;

    console.log('执行',initialSrc)

    this.onCanplay();

    this.onPause();


    // this.initEventListeners();  

    this._audioContext!.onPlay(() => {
    // this.isPaused = false;
    // this.isPlaying = true;
    console.log('onPlay');
    });

    this.onTimeUpdateCb = (res: any) => {
    if (this._isChanging) {
    return;
    }
    this.currentTime = this._audioContext!.currentTime;
    this.buffered = this._audioContext!.buffered;

    // #ifdef MP
    // 微信小程序安卓端过早的时机获取的buffered、duration为0,改为在此处获取
    if (this._audioContext!.duration === 0) {
    this.buffered = this._audioContext!.buffered;
    this.duration = this._audioContext!.duration;
    }
    // #endif
    if (this.currentTime > this.buffered) {
    console.log("缓冲不足");
    }
    };

    this.onWaitingCb = (res: any) => {
    this.onWaitingTest = true;
    };

    this.onTimeUpdate();
    // this.onWaiting()
    this.onError();
    this.onEnded();

    },

    unmounted() {

    if (this._audioContext != null) {

    if (this.isPlaying) {

    this.stop();


      }  
    // this._audioContext!.destroy();
    }
    this.removeEventListeners();

    },

    methods: {

    // 初始化事件监听

    initEventListeners() {

    type StopOtherAudioData = {

    source: string;

    };

    // 监听停止其他音频的事件

    this.stopOtherAudioCb = (data: UTSJSONObject) => {

    const res = JSON.parse<StopOtherAudioData>(JSON.stringify(data));

    // 当收到其他音频组件发送的停止事件时,如果当前组件正在播放,则停止播放

    if (res?.source !== "MaterialAudioPlayer") {

    this.stop();

    }

    };

    uni.$on("stopOtherAudioEmit", this.stopOtherAudioCb);

    },


    // 移除事件监听  
    removeEventListeners() {
    uni.$off("stopOtherAudioEmit", this.stopOtherAudioCb);
    },

    handlePlayClick() {
    if (this.allowClick) {
    this.play();
    }
    },
    handlePauseClick() {
    if (this.allowClick) {
    this.pause();
    }
    },
    formatTime(seconds: number): string {
    if (seconds == null || isNaN(seconds)) {
    return "00:00";
    }
    const min = Math.floor(seconds / 60);
    const sec = Math.floor(seconds % 60);
    return `${min.toString().padStart(2, "0")}:${sec.toString().padStart(2, "0")}`;
    },
    // 切换播放速率
    changeRate(rate: string) {
    this._audioContext!.playbackRate = parseFloat(rate);
    this.curRate = rate;
    },

    // 提供给父组件调用的从头播放方法
    playFromStart() {
    if (this._audioContext != null) {
    this.onchangeValue(0); // 跳转到开始位置
    this.isPlayEnd = false;
    // 如果当前不是播放状态,则开始播放
    if (!this.isPlaying) {
    this.play();
    }
    }
    },
    onCanplay() {
    this._audioContext!.onCanplay(() => {
    console.log('可以播放')
    this.isCanplay = true;
    // 当音频可以播放时,获取缓冲信息
    this.buffered = this._audioContext!.buffered;
    this.duration = this._audioContext!.duration;
    this.$emit("onCanplay", true);
    // #ifdef MP
    // 微信小程序安卓端过早的时机获取的volume为undefine,改为在此处获取
    this.volume = this._audioContext!.volume;
    // #endif
    });
    },
    onchanging() {
    this._isChanging = true;
    },
    onchange(e: UniSliderChangeEvent) {
    let pos = e.detail.value;
    this.onSeeking();
    this.onSeeked();
    this._audioContext!.seek(pos);
    this._isChanging = false;
    },
    onchangeValue(pos: number) {
    this.onSeeking();
    this.onSeeked();
    this._audioContext!.seek(pos);
    this._isChanging = false;
    },
    startTimeInput(e: UniInputEvent) {
    let startTimeValue = parseInt(e.detail.value);
    this._audioContext!.startTime = startTimeValue;
    this.onchangeValue(startTimeValue);
    },
    play() {
    if (!this.isCanplay) {
    uni.showToast({
    title: "音频未进入可以播放状态,请稍后再试",
    icon: "error",
    });
    return;
    }
    this.isPlaying = true;
    this._audioContext!.play();
    this.isPlayEnd = false;
    if (this._audioContext!.startTime > 0) {
    this.onchangeValue(this._audioContext!.startTime);
    }
    // 无论是否有其他音频正在播放,都发送停止其他音频的事件
    // 使用nextTick确保所有组件的事件监听都已注册
    this.$nextTick(() => {
    uni.$emit("stopOtherAudioEmit", { source: "MaterialAudioPlayer" });
    });
    console.log('播放')
    },
    onSeeking() {
    this._audioContext!.onSeeking(() => {
    this.onSeekingTest = true;
    });
    },
    onSeeked() {
    this._audioContext!.onSeeked(() => {
    this.onSeekedTest = true;
    });
    },
    onTimeUpdate() {
    this._audioContext!.onTimeUpdate(this.onTimeUpdateCb);
    },
    offTimeUpdate() {
    this._audioContext!.offTimeUpdate(this.onTimeUpdateCb);
    },
    onEnded() {
    this._audioContext!.onEnded(() => {
    this.currentTime = 0;
    this.startTime = 0;
    this.isPlaying = false;
    this.isPaused = true;
    this.isPlayEnd = true;
    this.$emit("onPlayEnd", true);
    // (this.$refs["slider"] as UniSliderElement)?.value = 0;
    });
    },
    onError() {
    this._audioContext!.onError((err) => {
    this.isPlaying = false;
    this.isPaused = true;
    console.log('音频加载错误',err)
    });
    },
    pause() {
    this._audioContext!.onPause(() => {
    this.isPaused = true;
    });
    this._audioContext!.pause();
    this.isPlaying = false;
    },
    onPause(){
    this._audioContext!.onPause(() => {
    this.isPaused = true;
    });
    },
    stop() {
    this._audioContext!.onStop(() => {
    // 第一次点停止时,不触发
    this.isPaused = true;
    });
    this._audioContext!.stop();
    this.isPlaying = false;
    this.currentTime = 0;
    },
    playbackRateChange(e: UniRadioGroupChangeEvent) {
    // if (this._audioContext != null && this.isPlaying) {
    this._audioContext!.playbackRate = parseFloat(e.detail.value);
    // }
    },
    //源代码中已有的方法,增强实现
    setSrc(src: string) {
    if (this._audioContext != null) {
    // 如果当前正在播放,先停止
    if (this.isPlaying) {
    this.pause();
    }

    let finalSrc = src;
    if (finalSrc.endsWith(".crdownload")) {
    finalSrc = finalSrc.replace(".crdownload", "") + ".mp3";
    }
    this._audioContext!.src = finalSrc;
    this.isCanplay = false; // 重置可播放状态
    this.$emit("onCanplay", false);
    this.currentTime = 0;
    this.duration = 0; // 默认值,将在onCanplay中更新
    this.buffered = 0;
    this.isPlayEnd = false;
    }
    },

    },

    };

    </script>

    2026-03-03 10:18

Ask小助手

Ask小助手

欢迎到专业群( uni-app 官方技术交流群 1 ) 咨询,群中有相关专业的管理员和群友。

根据知识库内容,目前 uni.getBackgroundAudioManageroffTimeUpdate 方法确实存在问题:

  1. 官方文档与实现不符:虽然文档和示例中提到了 offTimeUpdate 方法,但实际编译时提示该方法在 BackgroundAudioManager 类型上不存在。

  2. 已知问题:从对话知识库中可以看到,有用户反馈 uni.getBackgroundAudioManager 存在长音频缓冲问题(相关issue),但并未提及 offTimeUpdate 的解决方案。

  3. 建议方案

    • 暂时不要使用 offTimeUpdate,可以尝试使用 onTimeUpdate 的返回值来手动移除监听(如果支持的话)
    • 检查是否使用了最新版本的 HBuilderX(建议4.87+)
    • 关注后续版本更新,这个问题可能会在后续版本中修复
  4. 替代方案:如果必须移除时间更新监听,可以考虑重新创建一个新的 BackgroundAudioManager 实例来替代。

抱歉,我在知识库中没有找到关于 offTimeUpdate 方法的明确解决方案,建议暂时使用其他方式处理时间更新监听的需求。

内容为 AI 生成,仅供参考

要回复问题请先登录注册