移动端音频插件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去查看出现的问题,逐步的去解决。

相关推荐
星辰引路-Lefan1 天前
[特殊字符] 开源一款基于 PaddleOCR 的纯离线 OCR 识别插件 | 支持身份证、银行卡、驾驶证识别
前端·开源·ocr
Cache技术分享1 天前
285. Java Stream API - 通过 Supplier 创建 Stream
前端·后端
阿基米东1 天前
从嵌入式到前端的探索之旅,分享 5 个开源 Web 小工具
前端·javascript·github
clove1 天前
js中的数据类型,类型判断,类型转换,一篇文章全面罗列解析
javascript
hxjhnct1 天前
响应式布局有哪些?
前端·html·css3
LYFlied1 天前
【每日算法】LeetCode215. 数组中的第K个最大元素
前端·算法
怎么就重名了1 天前
Kivy的KV语言总结
前端·javascript·html
jqq6661 天前
解析ElementPlus打包源码(四、打包主题)
前端·javascript·vue.js
代码猎人1 天前
类数组对象是什么,如何转化为数组
前端
duanyuehuan1 天前
js 解构赋值
开发语言·前端·javascript