移动端音频插件howler简单配置

howlwer插件官网的地址:有兴趣的可以看一看,根据你的需求查找其中的配置项

一般音频需求可能如下:

  1. 能够自动/手动播放
  2. 可以调节音频的音量🔊
  3. 可以自由拖动进行播放

关于howlwe插件的基础配置如下:

javascript 复制代码
import {Howl, Howler} from 'howler';
var sound = new Howl({
  src: ['sound.webm'],//音频地址
  autoplay: true,// 是否自动播放
  loop: true, // 是否循环
  format:['mp3'], // 音频解析的格式
  volume: 0.5, // 音量的大小
  onload:()=>{  // 音频加载完成时触发
  console.log('success')
  },
  onplayerror:(error)=>{ // 音频报错触发
  console.log(error)
  }
 onend: function() {  // 音频播放完成时触发
    console.log('Finished!');
  },
});

一定要触发onload回调

onload的触发前提条件是你的音频是加载完成的,不然的话你后续在拖动播放的时候就出现拖动播放问题 ,你的音频的地址可能会出现如下情况

1.音频需要下载(不推荐这个)

如果你的音频地址放在浏览上是直接下载一个音频文件,那不建议你用这个,因为这个一般触发不了onload,触发不了onload就会在拖动的时候出现问题(你拖动到十分钟以后,但是你的音频位置还是从你拖动前的位置播放) ,解决方式就是要利用 URL.createObjectURL() 生成音频临时播放地址

举例如下(以v3为例):

xml 复制代码
<template>
  <div class="audio-player">
    <button @click="handleLoadAudio" :disabled="isLoading">
      {{ isLoading ? '加载中...' : '加载音频' }}
    </button>
    <button @click="playAudio" :disabled="!soundInstance || isLoading">播放</button>
    <button @click="pauseAudio" :disabled="!soundInstance || isLoading">暂停</button>
    <button @click="cleanup" :disabled="!soundInstance || isLoading">清理资源</button>
    
    <p v-if="errorMessage" class="error-text">{{ errorMessage }}</p>
  </div>
</template>

<script setup>
import { Howl } from 'howler';
import { ref, onUnmounted } from 'vue';

// 状态管理
const soundInstance = ref(null);
const tempAudioUrl = ref('');
const isLoading = ref(false);
const errorMessage = ref('');

// 音频地址(实际使用时替换)
const audioSourceUrl = 'https://example.com/audio/sample.mp3';

/**
 * 清理资源
 */
const cleanup = () => {
  // 销毁Howler实例
  if (soundInstance.value) {
    soundInstance.value.stop();
    soundInstance.value.unload();
    soundInstance.value = null;
  }
  
  // 释放临时URL
  if (tempAudioUrl.value) {
    URL.revokeObjectURL(tempAudioUrl.value);
    tempAudioUrl.value = '';
  }
  
  errorMessage.value = '';
};

/**
 * 下载音频并创建临时播放地址
 */
const handleLoadAudio = async () => {
  // 重置状态
  cleanup();
  isLoading.value = true;
  errorMessage.value = '';

  try {
    // 1. 下载音频文件
    const response = await fetch(audioSourceUrl, {
      headers: { 'Accept': 'audio/*' }
    });

    if (!response.ok) {
      throw new Error(`下载失败: ${response.status} ${response.statusText}`);
    }

    // 2. 转换为Blob对象
    const audioBlob = await response.blob();
    if (!audioBlob.type.startsWith('audio/')) {
      throw new Error(`无效音频格式: ${audioBlob.type}`);
    }

    // 3. 创建临时URL
    const tempUrl = URL.createObjectURL(audioBlob);
    tempAudioUrl.value = tempUrl;

    // 4. 初始化Howler
    soundInstance.value = new Howl({
      src: [tempUrl],
      format: ['mp3'],
      autoplay: false,
      loop: false,
      volume: 0.6,
      onload: () => {
        console.log('音频加载完成');
        isLoading.value = false;
      },
      onplayerror: (err) => {
        errorMessage.value = `播放错误: ${err}`;
        isLoading.value = false;
      },
      onend: () => {
        console.log('播放结束');
      }
    });

  } catch (err) {
    errorMessage.value = err.message;
    isLoading.value = false;
  }
};

/**
 * 播放音频
 */
const playAudio = () => {
  if (soundInstance.value && !soundInstance.value.playing()) {
    soundInstance.value.play();
  }
};

/**
 * 暂停音频
 */
const pauseAudio = () => {
  if (soundInstance.value && soundInstance.value.playing()) {
    soundInstance.value.pause();
  }
};

// 组件卸载时清理资源
onUnmounted(cleanup);
</script>

<style scoped>
.audio-player {
  display: flex;
  gap: 12px;
  padding: 20px;
  flex-wrap: wrap;
}

button {
  padding: 8px 16px;
  cursor: pointer;
  background: #42b983;
  color: white;
  border: none;
  border-radius: 4px;
  transition: background 0.3s;
}

button:disabled {
  background: #cccccc;
  cursor: not-allowed;
}

.error-text {
  color: #ff4d4f;
  margin-top: 12px;
  width: 100%;
}
</style>
    

这个时候你就可以看到在你使用临时生成的地址后你就有百分之50的可能性成功的触发onload另外的百分之50就要看音频格式啦

在移动端各家厂商的录音格式是不尽相同的:小米 华为 oppo vivo 这些基本上录音的格式都不太相同。

常见的音频格式如下:

  1. mp3
  2. wav
  3. m4a
  4. amr

所以我们还要正确的配置选项format

less 复制代码
src: [tempUrl],
format: ['mp3','m4a','wav','amr'],
autoplay: false,
loop: false,
volume: 0.6,

当然音频格式不止这些,根据你的实际项目情况来就好啦。

2.音频可以在线播放(推荐这个)

这个非常推荐使用,这个可以轻松触发onlad,你可以自由的滑动播放。

拖动播放与seek的异步性

如果拖动完成后立即调用了play去进行播放,但是播放的时候确是你拖动之前的位置,这是因为你拖动的位置尚未缓冲到。

解决方式如下:

  1. 严格等待 seek() 完成后再播放(关键)

howlerseek() 是异步操作(即使音频已加载),必须在其完成后调用 play()。通过 seek() 返回的 Promise 或 seek 事件确保时序:

javascript

scss 复制代码
// 拖动进度回调
function handleSeek(newTime) {
  // 等待 seek 完成后再播放
  sound.seek(newTime).then(() => { 
    sound.play(); 
  });
}

// 或监听 seek 事件(兼容旧版本)
sound.on('seek', () => {
  sound.play(); // 定位完成后自动播放
});
  1. 检查拖动位置是否已缓冲

即使 onload 触发,拖动到未缓冲的区域仍需等待缓冲。可通过 howlerstate()buffered() 检查:

javascript

scss 复制代码
function handleSeek(newTime) {
  // 检查当前位置是否已缓冲
  const buffered = sound.buffered(); // 返回已缓冲的时间范围数组
  const isBuffered = buffered.some(range => range[0] <= newTime && newTime <= range[1]);

  if (isBuffered) {
    sound.seek(newTime).then(() => sound.play());
  } else {
    // 未缓冲:先缓冲再播放(可加 loading 提示)
    sound.seek(newTime);
    sound.once('buffer', () => sound.play()); // 监听缓冲事件
  }
}

当然项目中遇到的问题是多种多样的,你可以回调官网提供的onplayerror去查看出现的问题,逐步的去解决。

相关推荐
Ice_Sugar_76 分钟前
React 腾讯面试手写题
javascript·react.js·ecmascript
一枚前端小能手13 分钟前
🚀 Webpack构建等到怀疑人生?试试这几个优化
前端·webpack
入秋27 分钟前
2025年项目中是怎么初始化Three.js三维场景的
前端·three.js
托尼_Captain33 分钟前
uniapp封装全局request请求
前端
Jacob023441 分钟前
Python与PostgreSQL实战:打造实时地理空间数据处理与管理系统
javascript·python·postgresql
二闹1 小时前
Map穿越JSON边境后惨遭“洗白”?前端:我只认识Object!
javascript·后端
ze_juejin1 小时前
Fetch API 详解
前端
用户66982061129821 小时前
js今日理解 blob和arrayBuffer 二进制数据
前端·javascript
想想肿子会怎么做1 小时前
Flutter 环境安装
前端·flutter
断竿散人1 小时前
Node 版本管理工具全指南
前端·node.js