Audio API 实现音频播放器

这篇具有很好参考价值的文章主要介绍了Audio API 实现音频播放器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

市面上实现音频播放器的库有很多,比如wavesurfer.js、howler.js等等,但是都不支持大音频文件处理,100多M的文件就有可能导致程序崩溃。总之和我目前的需求不太符合,所以打算自己实现一个音频播放器,这样不管什么需求 在技术上都可控。下面我们简单介绍下wavesurferJs、和howlerJs的实现,然后再讲解如何利用audio API实现自定义语音播放器。

具体资源github下载

wavesurferJs

一开始选择wavesurferJs 主要是因为它的音频图功能。
效果如下:
Audio API 实现音频播放器
是不是很漂亮 hh
下面是实现步骤:

  1. 初始化
this.playWavesurfer = WaveSurfer.create({
	container: '#waveform2',
	mediaType: 'audio',
	height: 43,
	scrollParent: false,
	hideScrollbar: true,
	waveColor: '#ed6c00',
	interact: true,
	progressColor: '#dd5e98',
	cursorColor: '#ddd5e9',
	interact: true,
	cursorWidth: 1,
	barHeight: 1,
	barWidth: 1,
	plugins: [
		WaveSurfer.microphone.create()
	]
});
  1. 动态加载音频地址
this.playWavesurfer.load(this.audioUrl);
  1. 设置加载loading和完毕后计算音频总时长
this.playWavesurfer.on('loading', (percent, xhr) => {
		this.audioLoadPercent = percent - 1;
	})
	this.playWavesurfer.on('ready', () => {
		this.audioLoading = false;
		const duration = this.playWavesurfer.getDuration();
		this.duration = this.formatTime(duration);
		this.currentTime = this.formatTime(0);
	})
  1. 播放中计算时长
this.playWavesurfer.on('audioprocess', function () {
	const duration = that.playWavesurfer.getDuration();
	const currentTime = that.playWavesurfer.getCurrentTime();
	that.currentTime = that.formatTime(currentTime);
	that.duration = that.formatTime(duration);
	if (that.currentTime === that.duration) {
		that.audioPlayingFlag = false;
	}
});
  1. 播放、暂停
this.playWavesurfer.playPause.bind(this.playWavesurfer)();
  1. 快进、快退
this.playWavesurfer.skip(15);
//this.playWavesurfer.skip(-15);
  1. 倍数播放
this.playWavesurfer.setPlaybackRate(value, true);

这样基本功能大概实现。

利用howlerJs实现

  1. 初始化、动态加载音频路径
this.howler = new Howl({
	src: [this.audioUrl]
});
  1. 加载完毕计算音频总时长
this.howler.on('load', () => {
	this.audioLoading = false;
	const duration = this.howler.duration();
	this.duration = this.formatTime(duration);
	this.currentTime = this.formatTime(0);
});

  1. 播放中获取当前时间
this.currentTime = this.formatTime(this.howler.seek());
  1. 播放完毕
this.howler.on('end', () => {
	this.audioPlayingFlag = false;
	this.siriWave2.stop();
	this.currentTime = "00:00:00";
	this.progressPercent = 0;
	cancelAnimationFrame(this.playTimer);
})
  1. 快进、快退
this.howler.seek(this.howler.seek() + 15);
//this.howler.seek(this.howler.seek() - 15);
  1. 设置倍数播放
this.howler.rate(value);
  1. 播放、暂停
this.howler.play();
// this.howler.pause();
  1. 手动定位播放时长
<div id="waveform2" ref="waveform2" @click="changProgress">
	<div class="bar" v-if="!audioLoading&&!audioPlayingFlag"></div>
	<div class="progress" :style="{width: `${progressPercent}`}"></div>
</div>
changProgress(e) {
	if (this.howler.playing()) {
		this.howler.seek((e.offsetX / this.$refs['waveform2'].offsetWidth)*this.howler.duration());
	}
},

这样基本功能大概实现。

利用audio API实现播放器

效果图:
Audio API 实现音频播放器
动画库 暂时用的 siriwave.js

先定义audio标签隐藏,可以js里面动态生成

<audio :src="audioUrl" style="display: none;" controls ref="audio"></audio>
this.audio = this.$refs['audio'];
  1. 获取音频url后 动态加载 需要load一下
this.audio.load();
  1. 音频加载完毕
this.audio.addEventListener("canplaythrough", () => {
	this.audioLoading = false;
	console.log('music ready');
}, false);
  1. 监听可以播放后 计算音频时长
this.audio.addEventListener("canplay", this.showTime, false);
showTime() {
	if (!isNaN(this.audio.duration)) {
		this.duration = this.formatTime(this.audio.duration);
		this.currentTime = this.formatTime(this.audio.currentTime);
	}
},
  1. 播放中 时间改变计算当前 时间
this.audio.addEventListener("timeupdate", this.showTime, true);
  1. 监听播放事件
this.audio.addEventListener('play', () => {
	this.audioPlaying();
}, false);
  1. 播放完毕
this.audio.addEventListener('ended', () => {
	this.audioPlayingFlag = false;
	this.siriWave2.stop();
	this.currentTime = "00:00:00";
	this.progressPercent = 0;
	cancelAnimationFrame(this.playTimer);
}, false)
  1. 前进、后退
this.audio.currentTime += 15;
// this.audio.currentTime -= 15;
  1. 设置播放倍数
this.audio.playbackRate = value;
  1. 播放、暂停
this.audio.play();
// this.audio.pause();
  1. 音频定位
<div id="waveform2" ref="waveform2" @click="changProgress">
	<div class="bar" v-if="!audioLoading&&!audioPlayingFlag"></div>
	<div class="progress" :style="{width: `${progressPercent}`}"></div>
</div>

计算 定位时长

changProgress(e) {
	// if (this.audioPlayingFlag) {
		this.audio.currentTime = (e.offsetX / this.$refs['waveform2'].offsetWidth)*this.audio.duration;
		this.progressPercent = ((this.audio.currentTime/this.audio.duration) * 100) + '%';
	// }
},
  1. siri动画实现
this.siriWave = new SiriWave({
	container: that.$refs['waveform'],
		height: 43,
		cover: true,
		color: '#ed6c00',
		speed: 0.03,
		amplitude: 1,
		frequency: 6
	});

开启动画、停止动画

this.siriWave.start();
// this.siriWave.stop();

这样基本功能大概实现。 即使加载再大音频文件也不会卡。

踩坑

Audio API 实现音频播放器
这里遇到一个大坑就是 audio自带,音频播放定位功能,在外面浏览器和vscode主体代码里面都可以定位,偏偏我在vscode插件里面不可以定位,会自动归0。翻遍了文档在MDN上找到这样一段描述:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Configuring_servers_for_Ogg_media#Handle_HTTP_1.1_byte_range_requests_correctly

Handle HTTP 1.1 byte range requests correctly
In order to support seeking and playing back regions of the media that aren’t yet downloaded, Gecko uses HTTP 1.1 byte-range requests to retrieve the media from the seek target position. In addition, Gecko uses byte-range requests to seek to the end of the media (assuming you serve the Content-Length header) in order to determine the duration of the media.
Your server should accept the Accept-Ranges: bytes HTTP header if it can accept byte-range requests. It must return 206: Partial content to all byte range requests; otherwise, browsers can’t be sure you actually support byte range requests.
Your server must also return 206: Partial Content for the request Range: bytes=0- as well.

经验证是和response header有关的。我通过对MP3资源set不同的response header来验证,结果如下(貌似segmentfault不支持markdown的表格,所以下面排版有点乱。):
ie
Content-Type 必须,当我设为audio/mpeg时才能播放,设为application/octet-stream不能。
Content-Length必须。和Accept-Ranges无关。

chrome
Content-Type 无关,设为application/octet-stream可以播放。
Content-LengthAccept-Ranges必须都有才可更改 currentTime。

也就是说ie需要response header 有正确的Content-TypeContent-Length
chrome需要头部有Content-LengthAccept-Ranges

然后我想到 vscode插件系统使用了 Service Worker

const headers = {
		'Content-Type': entry.mime,
		'Content-Length': entry.data.byteLength.toString(),
		'Access-Control-Allow-Origin': '*',
	};

果然 没有添加 Accept-Ranges字段

const headers = {
	'Content-Type': entry.mime,
	'Content-Length': entry.data.byteLength.toString(),
	'Access-Control-Allow-Origin': '*',
};

/**
 * @author lichangwei
 * @description 音频额外处理 否则无法调节进度
 * https://developer.mozilla.org/en-US/docs/Web/HTTP/Configuring_servers_for_Ogg_media#Handle_HTTP_1.1_byte_range_requests_correctly
 */

if (entry.mime === 'audio/mpeg') {
	headers['Accept-Ranges'] = 'bytes';
}

添加后就可以使用了。

后续

看了一下印象笔记的语音笔记实现。
Audio API 实现音频播放器

Audio API 实现音频播放器
印象笔记是如何避免大文件处理的呢

  • 首先录音过程中绘制的是真的音频线
  • 录音结束后是用假的音频线替代的

其实录制过程中实时处理音频数据还好,不至于导致浏览器崩溃,录制后生成的音频文件处理数据量太大了,内存直接飙升2-3G,所以会导致程序崩溃

后续实现音频图文章来源地址https://www.toymoban.com/news/detail-496157.html

兄弟萌给个关注~

到了这里,关于Audio API 实现音频播放器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【html本地工具】html+css+js本地音乐播放器,实现可视化音频频谱

    html+css+js本地音乐播放器,实现可视化音频频谱 之前用swing写了个本地音乐播放器(如下图),但是效果一言难尽,界面丑,功能bug也多,唉 所以后面又重新用html写了个,界面样式和功能方面,比swing写的好看、完善多了。 导入音乐(已完成) 展示列表(已完成) 列表双击

    2024年02月14日
    浏览(37)
  • Android 中封装优雅的 MediaPlayer 音频播放器,支持多个播放器

    Android 中封装优雅的 MediaPlayer 音频播放器,支持多个播放器实例的示例: 上述代码中,使用 getInstance() 方法获取 AudioPlayer 的单例对象,参数传入 Context 对象。 在 getInstance() 方法中判断单例对象是否为空,如果为空则创建新的 AudioPlayer 对象,否则返回已有的单例对象。 这样

    2024年02月12日
    浏览(46)
  • uniapp之音频播放器

    日常业务会遇到 微信音频 mp3播放器, 特别是微信文章阅读,下面仅作参考 1.解决滑动卡顿bug 加了防抖 2.滑动进度条时 先暂停再播放 就不会出现卡顿 3.初始化时 要onCanplay钩子中 setInterval 获取音频文件长度 不然会显示 0 注意用了vantUI 框架的icon 不用可以去掉 换图片或者其他

    2024年02月11日
    浏览(41)
  • 播放器开发(六):音频帧处理并用SDL播放

    AudioOutPut 模块 1、初始化【分配缓存、读取信息】 2、开始线程工作【从队列读帧-重采样-SDL回调-写入音频播放数据-SDL进行播放】 分配缓存 重采样相关 SDL的音频回调 AudioOutPut PlayerMain 添加音频输出代码 测试运行结果 如果需要同时执行视频和音频的输出,记得要在解复用模块

    2024年02月20日
    浏览(47)
  • 浏览器网页内嵌Qt-C++音视频播放器的实现,支持软硬解码,支持音频,支持录像截图,支持多路播放等,提供源码工程下载

        在浏览器中实现播放RTSP实时视频流,⼤体上有如下⼏个⽅案: ⽅案一:浏览器插件⽅案 ActiveX、NPAPI、PPAPI     ActiveX插件适用于IE浏览器,NPAPI与PPAPI插件适用于谷歌浏览器,不过这些插件都已经不被浏览器所支持。 ⽅案二:先转码再转流⽅案     ⼯作原理是架设一

    2024年01月17日
    浏览(94)
  • 用selenium爬取直播信息,前端音频播放器

    #保存数据的函数 def save_data(self,data_list,i): #在当前目录下将数据存为txt文件 with open(‘./douyu.txt’,‘w’,encoding=‘utf-8’) as fp: for data in data_list: data = str(data) fp.write(data+‘n’) print(“第%d页保存完成!” % i) (2)保存为json文件 #保存数据的函数 def save_data(self,data_list,i): with op

    2024年04月16日
    浏览(47)
  • 一个WPF开发的、界面简洁漂亮的音频播放器

    今天推荐一个界面简洁、美观的、支持国际化开源音频播放器。 这是一个基于C# + WPF开发的,界面外观简洁大方,操作体验良好的音频播放器。 支持各种音频格式,包括:MP4、WMA、OGG、FLAC、M4A、AAC、WAV、APE 和 OPUS;支持标记、实时显示歌词等功能;支持换肤、中英文等主流

    2024年02月01日
    浏览(51)
  • Vue 3 + ffmpeg + wasm 实现前端视频剪辑、音频剪辑、音波展示、视频抽帧、gif抽帧、帧播放器、字幕、贴图、时间轴、素材轨道

    预览 www.bilibili.com/video/BV1YT411Y7YJ 技术栈: 💪 Vue 3、Vue-Router 4、Vite、pnpm、esbuild、TypeScript ☀️ Pinia 状态管理 🌪 Tailwind 原子css集成 💥 ffmpeg、wasm 底层音视频处理集成 功能 多轨道时间轴,支持帧缩放,时间缩放 支持多种类型轨道的添加删除 多功能轨道调节,支持音视频轨

    2024年02月11日
    浏览(52)
  • 音频播放器Web页面代码实例(基于HTML5)

    音频播放器Web页面代码实例(基于HTML5):   特别需要注意的点:     如果上传文件时设置的是默认转码方式,所有的文件都会转码为视频文件,使用音频播放器播放视频文件时,只会播放声音,没有图像。     如果上传文件时设置了\\\"源文件播放\\\",平台不会对源文件进行

    2024年02月16日
    浏览(36)
  • 基于 FFmpeg 的跨平台视频播放器简明教程(六):使用 SDL 播放音频和视频

    基于 FFmpeg 的跨平台视频播放器简明教程(一):FFMPEG + Conan 环境集成 基于 FFmpeg 的跨平台视频播放器简明教程(二):基础知识和解封装(demux) 基于 FFmpeg 的跨平台视频播放器简明教程(三):视频解码 基于 FFmpeg 的跨平台视频播放器简明教程(四):像素格式与格式转换

    2024年02月13日
    浏览(58)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包