这篇文章发布于 2023年11月29日,星期三,00:21,归类于 JS实例。 阅读 12340 次, 今日 7 次 7 条评论
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11070 鑫空间-鑫生活
本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可以联系授权。
一、基本常识
音频文件不仅仅有音频采样数据,还包含很多源信息,还是叫元信息的。
这些元信息内容非常丰富,有作者名字、专辑信息、封面、编码格式、音轨信息等。
然而,我们在Web中使用的音频文件大多是没有这些信息的,都被工具移除了,减小文件的体积,节约传输的流量。
这些信息多在音乐网站下载的MP3音频中。
OK,下面需求来了,网站有个本地上传MP3音频的功能,希望如果MP3音频有封面图等信息,也一并上传,没有,那就算了,请问如何实现?
二、封面图和时长的获取
音频的时长不属于元信息,因此,封面图的获取和时长的获取需要分开实现。
1. 封面图的获取
音乐的封面图内容属于元信息,因此,需要从元信息中读取。
至于读取的方法,可以使用目前市面上比较成熟的JavaScript项目,例如:https://github.com/aadsm/jsmediatags
使用很简单,引用JS文件,读取MP3音频,输出结果:
<script src="./jsmediatags.min.js"></script> <script> jsmediatags.read("./music-file.mp3", { onSuccess: function(tag) { console.log(tag); }, onError: function(error) { console.log(':(', error.type, error.info); } }); </script>
其中的tag
是个巨大的对象,里面包含很多的信息,当然,前提是这个音频的元信息都保留下来了。
其中的封面图信息就存在 tag.tags.picture.data
这个对象上。
如果是本地文件,则可以直接读取文件本身,例如:
inputFile.addEventListener("change", function(event) { var file = event.target.files[0]; jsmediatags.read(file, ...); }, false);
不过tag.tags.picture.data
的值是个ArrayBuffer数据,不能直接作为图片显示,如下图所示:
有两种方法可以转成图片地址。
- 转Base64地址,这是jsmediatags这个项目提供的方法:
const { data, format } = result.tags.picture; let base64String = ""; for (const i = 0; i < data.length; i++) { base64String += String.fromCharCode(data[i]); } img.src = `data:${data.format};base64,${window.btoa(base64String)}`;
不过此方法有些啰嗦。
- 转Blob URL地址,参考实现如下:
img.src = URL.createObjectURL(new Blob([new Uint8Array(tag.tags.picture.data).buffer]));
本文提供的demo页面就使用的上面的实现。
2. 音频文件时长的获取
这个通过FileReader对象读取选择的本地文件,然后通过触发加载的方式就可以指定音频的时长了。参考实现如下:
inputFile.addEventListener("change", function(event) { var file = event.target.files[0]; const reader = new FileReader(); reader.onload = function (event) { const url = event.target.result; const audio = new Audio(url); audio.addEventListener('loadedmetadata', function () { console.log('音频时长:' + audio.duration); }); }; reader.readAsDataURL(file); }, false);
上述方法返回的音频时长的单位是秒,实际使用的时候,还需要转换成分:秒的形式,这个属于JS基础了,不展示。
三、万事具备,演示页面
好,预备知识都get到了,接下来就简单了,套用代码,设想个场景,做个demo演示页面。
您可以狠狠地点击这里:使用JS读取本地音频图片时长demo
例如,从本地选择个如下图所示的音乐文件:
随后JS执行上面一小节提到的巴拉巴拉实现,然后把获取到的信息再一渲染,当~效果有了,如下图所示:
四、短小精悍结束语
貌似最近的文章都是围绕音视频开发,还有视觉特效展开的,其实都属于前端非常规的业务开发分支,在大厂都是有专门的岗位的,分别是富媒体方向和视觉表现方向,虽小众,但积累到一定程度,还是很有竞争力的,是个香饽饽。
下个月开发,文章应该会回到CSS、HTML和JavaScript上,继续介绍新特性,例如CSS新出的@scope
规则,这也是好东西。
好了,就说这么多吧,唉,突然想钓鱼了。
本文为原创文章,欢迎分享,勿全文转载,如果实在喜欢,可收藏,永不过期,且会及时更新知识点及修正错误,阅读体验也更好。
本文地址:https://www.zhangxinxu.com/wordpress/?p=11070
(本篇完)
- CSS ::file-selector-button伪元素简介 (0.580)
- 纯前端实现可传图可字幕台词定制的GIF表情生成器 (0.342)
- HTML5 file API加canvas实现图片前端JS压缩并上传 (0.254)
- 小tips: 纯前端JS读取与解析本地文本类文件 (0.254)
- 又get到了,JS复制图片到剪切板 (0.245)
- 本地开发设置个区分明显的favicon吧~ (0.209)
- 直接剪切板粘贴上传图片的前端JS实现 (0.185)
- 原来浏览器原生支持JS Base64编码解码 (0.176)
- 理解DOMString、Document、FormData、Blob、File、ArrayBuffer数据类型 (0.166)
- XMLHttpRequest实现HTTP协议下文件上传断点续传 (0.166)
- 使用wavesurfer.js显示mp3 audio音频的波形图 (RANDOM - 0.054)
jsmediatags.read(“./music-file.mp3”,
这种写法读取文件是会报错的,错误 提示如下:
No suitable file reader found for
这个是相关issues
https://github.com/aadsm/jsmediatags/issues/51
这个项目,我之前自己实现过。
首先,用js以二进制读取mp3、acc、flac等文件,校验文件类型。比如mp3开始的字节是49、44、33,即ID3。
其次,以循环读取字节的方式,读取信息。比如图片就是APIC(字节41、50、49、53)开头,标题就是TIT2开头。元数据的结尾各自不一样,需要根据情况确定。
第三,还要注意图片本身也有元数据,比如JFIF,读取字节的时候也要注意判断。
audio.addEventListener(‘ondurationchange’, ev=>{
console.log(ev.target.duration + ‘秒’);
})
↑ 取得音频时长的话,似乎这样做能稍快 1ms
大佬钓的鱼都放生了吗?
野钓的会放生,鱼塘钓的自己吃~
厉害了
打卡