🌟前端如何播放AMR格式的音频文件🌟## 前言 最近在做的一个需求里,有一个播放音频的功能。上游给到的音频文件是 `
前言
最近在做的一个需求里,有一个播放音频的功能。上游给到的音频文件是 .amr
格式,我也是第一次见这种格式的音频。
我就像往常一样,直接通过一个 audio
标签来引入,结果发现根本播放不了。
import React from "react";
const Amr = () => {
return (
<div>
<audio controls src="/test.amr"/>
</div>
);
};
export default Amr;
在后续搜了一些资料发现,浏览器是不支持直接播放 amr
格式的音频的,需要转成 wav
或者 mp3
等格式。
常见的音频格式
以下是常见的一些音频格式以及他们的特点、优缺点,不感兴趣的同学可以直接跳过
-
MP3 (MPEG-1 Audio Layer III) :
- 特点:MP3 是最常见的音频格式之一,具有良好的压缩性能,能够显著减小音频文件的大小,同时保持相对较高的音质。
- 优点:广泛支持,几乎所有的音频播放器都能够播放MP3格式的文件。适用于网络流媒体、音乐下载和存储等场景。
- 缺点:MP3 是有损压缩格式,压缩过程中会损失一些音频信息,因此相对于无损格式,音质略有降低。
-
AAC (Advanced Audio Coding) :
- 特点:AAC 是一种高级音频编码格式,通常具有比MP3更高的音频质量,并且相对于相同音质的MP3文件,AAC文件的大小更小。
- 优点:音质较好,文件大小相对较小,支持多通道编码(例如立体声和环绕声)。
- 缺点:虽然AAC是一种有损压缩格式,但与MP3相比,AAC通常需要更多的计算资源进行编码和解码。
-
WAV (Waveform Audio File Format) :
- 特点:WAV 是一种无损音频格式,保留了音频文件的原始音频数据,因此音质非常高。
- 优点:无损压缩,不会丢失任何音频信息,音质非常高,适用于专业音频录制和编辑。
- 缺点:文件体积较大,不适合用于网络流媒体传输和存储。
-
FLAC (Free Lossless Audio Codec) :
- 特点:FLAC 是一种开源的无损音频编码格式,压缩率通常比WAV更高,但仍然保持了音频的完整性。
- 优点:无损压缩,音质高,压缩率较高,适用于音乐存储和传输,尤其是对音频质量要求较高的场景。
- 缺点:相对于有损格式如MP3和AAC,FLAC文件的解码需要更多的计算资源,不适合在资源受限的设备上播放。
-
OGG (Ogg Vorbis) :
- 特点:OGG 是一种自由、开放的多媒体容器格式,通常使用Vorbis音频编解码器来编码音频。
- 优点:开源、免费,音质较好,支持标签和元数据,适用于网络音频流传输和存储。
- 缺点:相对于MP3和AAC,OGG的普及率较低,不是所有的播放器都支持OGG格式。
-
AMR(Adaptive Multi-Rate):
- 特点:AMR是专门为语音信号设计的编码格式,因此对于语音的编码和解码具有良好的性能和效果。
- 优点:由于AMR采用了有损压缩,因此生成的音频文件通常比较小,适合在网络传输和存储时节省带宽和空间,特别适用于语音通信场景,如手机通话、语音信箱等,能够提供较好的语音质量和效率
- 缺点:虽然AMR的压缩效率较高,但在压缩过程中会丢失一些音频信息,因此相对于无损格式,音质会有所降低
上面提到的格式中,浏览器直接支持播放的有:
- MP3
- AAC
- OGG,在一些主流浏览器中被支持,如Firefox、Chrome等。但并非所有的浏览器都支持OGG格式。
- WAV
转码处理
也就是说我们需要把它转换成一些浏览器可以播放的格式,主要是使用到这个库——opencore-amr-js。它是一个 amr
解码器的 js
版本实现。
具体实现代码如下:
import React, { useEffect, useState } from "react";
const Amr = () => {
const [url, setUrl] = useState("");
const readBlob = (blob) => {
return new Promise((resolve) => {
const reader = new FileReader();
reader.onload = function (e) {
const data = new Uint8Array(e.target.result);
resolve(data);
};
reader.readAsArrayBuffer(blob);
});
};
const convertAmrToWav = async (origin) => {
const res = await fetch(origin);
const blob = await res.blob();
const data = await readBlob(blob);
const buffer = window.AMR.toWAV(data);
const url = URL.createObjectURL(
new Blob([buffer], { type: "audio/x-wav" })
);
setUrl(url);
};
useEffect(() => {
convertAmrToWav("/test.amr");
}, []);
return (
<div>
<audio controls src={url} />
</div>
);
};
export default Amr;
实现过程如下:
fetch
获取到音频的元数据- 转成
Uint8Array
格式 - 调用
AMR
进行转换 - 播放
可以看到,可以正常播放了。
需要注意的是,这个包还是有点大的, gzip
压缩之后还有大概 140KB
左右。
需要注意的地方
由于我们需要 fetch
获取音频,但很多时候这种音频都是存在对象存储里面。我们的应用大概率跟对象存储是不同域的,这个时候 fetch
的时候就会被跨域策略拦截。
如果你是使用node来启动前端服务,那么可以按照下面类似的方式去配置:
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const path = require('path');
const app = express();
// 创建代理服务器
const proxyMiddleware = createProxyMiddleware({
target: 'http://oss.com',
changeOrigin: true,
pathRewrite: { '^/source': '/source' },
});
// 将代理中间件应用于指定的路径
app.use('/source', proxyMiddleware);
// 将 dist 目录下的静态文件提供给客户端
app.use(express.static(path.join(__dirname, 'dist')));
// 启动 Express 服务器
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Proxy server is running on port ${PORT}`);
});
假如说我们的音频地址是oss.com/source/audi… ,那么在前端 fetch
的时候就使用如下方式去请求:
fetch('/source/audio.amr')
还有一种是你使用 nginx
作为静态资源服务器,也是同样配置一个反向代理,大致的配置如下:
server {
listen 80; # 监听的端口号
server_name your_domain.com;
location /oss {
proxy_pass http://oss.com/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location / {
alias /www/wwwroot/dist
}
}
最好的方案
让后端把音频格式转成 wav
或者 mp3
。
最后
以上就是本文的全部内容,如果你觉得有意思的话,点点关注点点赞吧~
转载自:https://juejin.cn/post/7415911762129010688