加入我们一起学习,天天进步

来源:kerin

https://segmentfault.com/a/1190000037613988

源码在此,戳这里Github :https://github.com/Kerinlin/localMusicPlayer

为什么要做?


女朋友工作是音频后期,平常会收集一些音频音乐,需要看音频的频谱波形,每次用au这种大型软件播放音乐看波形,很不方便,看到她这么辛苦,身为程序猿的我痛心疾首,于是,就有了这么一个小软件,软件涉及到的技术主要为electron,vue,node,波形的展示主要通过wavesurfer生成。

从零开始-搭建项目


项目通过vue脚手架搭建的,所以需要安装cli工具,如果已经装了,可以跳过这一步.

npm install -g @vue/cli

# OR

yarn global add @vue/cli

装好后,通过脚手架搭建项目

vue create music

vue需要与electron集成,这里社区已经有比较成熟的vue插件了,Vue CLI Plugin Electron Builder。

vue add electron-builder

懒人可以直接去clone我的搭建好得架子直接开发, 戳这里 :https://github.com/Kerinlin/simple-electron-vue-template 。

从零开始-项目开发


首先先明确下这个播放器的功能需求,主要有这几个

  • 不添加文件目录,加载任意的本地文件系统内的音频文件,直接调用播放器播放

  • 前一首后一首功能

  • 声音音量控制

  • 自定义软件窗口

如何关联播放

如何实现关联播放?因为对electron不是很熟,查了很久 electron 的资料,终于找到了配置项,需要配置 fileAssociations

fileAssociations: [

{

ext: [“mp3”, “wav”, “flac”, “ogg”, “m4a”],

name: “music”,

role: “Editor”

}

],

配置好后,通过 electron 的open-file事件,获取打开的音频文件的本地路径。对于 windows , 需要通过 process.argv ,来获取文件路径。

const filePath = process.argv[1];

如何加载本地音频文件

上一步通过配置拿到文件的本地路径后,下一步就是通过路径读取音频文件的信息。由于音频的插件无法解析绝对路径,所以需要通过node的文件系统,通过fs.readFileSync读取到文件的buffer信息。

let buffer = fs.readFileSync(diskPath); //读取文件,并将缓存区进行转换

读取后需要将buffer转换成node可读流

const stream = this.bufferToStream(buffer);//将buffer数据转换成node 可读流

转换方法 bufferToStream

bufferToStream(binary) {

const readableInstanceStream = new Readable({

read() {

this.push(binary);

this.push(null);

}

});

return readableInstanceStream;

}

转换成流后需要将音频流转换成blob对象来加载,实现方法

module.exports = streamToBlob

function streamToBlob (stream, mimeType) {

if (mimeType != null && typeof mimeType !== ‘string’) {

throw new Error(‘Invalid mimetype, expected string.’)

}

return new Promise((resolve, reject) => {

const chunks = []

stream

.on(‘data’, chunk => chunks.push(chunk))

.once(‘end’, () => {

const blob = mimeType != null

? new Blob(chunks, { type: mimeType })

: new Blob(chunks)

resolve(blob)

})

.once(‘error’, reject)

})

}

转blob

let fileUrl; // blob对象

streamToBlob(stream)

.then(res => {

fileUrl = res;

// console.log(fileUrl);

//将blob对象转成blob链接

let filePath = window.URL.createObjectURL(fileUrl);

// console.log(filePath);

this.wavesurfer.load(filePath);

// 自动播放

this.wavesurfer.play();

this.playing = true;

})

.catch(err => {

console.log(err);

});

这样就实现了加载本地文件播放了

上一首下一首功能

这里的上一首下一首的功能是基于上面获取到的文件的绝对路径,通过node的path模块,path.dirname获取到文件的父级目录。

const dirPath = path.dirname(diskPath);

然后通过fs.readdir读取目录下所有文件,会返回一个文件名数组,找到该目录下正在播放的文件的下标,通过数组下标判断前一首和后一首歌曲的名称,然后再组装成绝对路径,读取资源播放

playFileList(diskPath, pos) {

let isInFiles;

let fileIndex;

let preIndex;

let nextIndex;

let fullPath;

let dirPath = path.dirname(diskPath);

let basename = path.basename(diskPath);

fs.readdir(dirPath, (err, files) => {

isInFiles = files.includes(basename);

if (isInFiles && pos === “pre”) {

fileIndex = files.indexOf(basename);

preIndex = fileIndex - 1;

fullPath = path.resolve(dirPath, files[preIndex]);

this.loadMusic(fullPath);

}

if (isInFiles && pos === “next”) {

fileIndex = files.indexOf(basename);

nextIndex = fileIndex + 1;

fullPath = path.resolve(dirPath, files[nextIndex]);

this.loadMusic(fullPath);

}

});

},

声音音量控制

音量控制需要通过监听input的键入事件,获取到range的值,然后通过设置样式background-image,动态计算百分比,然后调用wavesurfer的setVolume方法调节音量

:style=“background-image:linear-gradient( to right, ${fillColor}, ${fillColor} ${percent}, ${emptyColor} ${percent})

改变音量changeVol事件

changeVol(e) {

let val = e.target.value;

let min = e.target.min;

let max = e.target.max;

let rate = (val - min) / (max - min);

this.percent = 100 * rate + “%”;

console.log(this.percent, rate);

this.wavesurfer.setVolume(Number(rate));

},

自定义标题栏

个人觉得系统自带的菜单栏太丑了,就给设置了无边框再自己加上最小化,关闭的功能。最小化,关闭是通过ipc通信,渲染进程监听到有点击操作后,通知主进程进行相应的操作。

渲染进程

close() {

ipcRenderer.send(“close”);

},

minimize() {

ipcRenderer.send(“minimize”);

}

主进程

ipcMain.on(“close”, () => {

win.close();

app.quit();

});

ipcMain.on(“minimize”, () => {

win.minimize();

});

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

最后

资料过多,篇幅有限,需要文中全部资料可以点击这里免费获取前端面试资料PDF完整版!

自古成功在尝试。不尝试永远都不会成功。勇敢的尝试是成功的一半。

[外链图片转存中…(img-ct4kQPWG-1713483169824)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

[外链图片转存中…(img-MTHBwZHc-1713483169824)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

[外链图片转存中…(img-hScB6HNm-1713483169824)]

最后

[外链图片转存中…(img-gCGTo0mR-1713483169824)]

[外链图片转存中…(img-l14Q5CmP-1713483169825)]

资料过多,篇幅有限,需要文中全部资料可以点击这里免费获取前端面试资料PDF完整版!

自古成功在尝试。不尝试永远都不会成功。勇敢的尝试是成功的一半。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐