一、基本常识

音频文件不仅仅有音频采样数据,还包含很多源信息,还是叫元信息的。

这些元信息内容非常丰富,有作者名字、专辑信息、封面、编码格式、音轨信息等。

@本地MP3封面图、时长等信息的JS读取 « 张鑫旭 鑫空间 鑫生活 20240710184623561

然而,我们在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数据,不能直接作为图片显示,如下图所示:

@本地MP3封面图、时长等信息的JS读取 « 张鑫旭 鑫空间 鑫生活 20240710184623564

有两种方法可以转成图片地址。

  1. 转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)}`;

不过此方法有些啰嗦。

  1. 转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

例如,从本地选择个如下图所示的音乐文件:

@本地MP3封面图、时长等信息的JS读取 « 张鑫旭 鑫空间 鑫生活 20240710184937013

随后JS执行上面一小节提到的巴拉巴拉实现,然后把获取到的信息再一渲染,当~效果有了,如下图所示:

@本地MP3封面图、时长等信息的JS读取 « 张鑫旭 鑫空间 鑫生活 20240710184943161

四、短小精悍结束语

貌似最近的文章都是围绕音视频开发,还有视觉特效展开的,其实都属于前端非常规的业务开发分支,在大厂都是有专门的岗位的,分别是富媒体方向和视觉表现方向,虽小众,但积累到一定程度,还是很有竞争力的,是个香饽饽。

下个月开发,文章应该会回到CSS、HTML和JavaScript上,继续介绍新特性,例如CSS新出的@scope规则,这也是好东西。