欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Electron+vue從零開始打造一個本地播放器的方法示例

 更新時間:2020年10月27日 09:26:24   作者:kerin  
這篇文章主要介紹了Electron+vue從零開始打造一個本地播放器的方法示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

為什么要做?

女朋友工作是音頻后期,平常會收集一些音頻音樂,需要看音頻的頻譜波形,每次用au這種大型軟件播放音樂看波形,很不方便,看到她這么辛苦,身為程序猿的我痛心疾首,于是,就有了這么一個小軟件,軟件涉及到的技術(shù)主要為electron,vue,node,波形的展示主要通過wavesurfer生成。

從零開始-搭建項目

項目通過vue腳手架搭建的,所以需要安裝cli工具,如果已經(jīng)裝了,可以跳過這一步.

npm install -g @vue/cli
# OR
yarn global add @vue/cli

裝好后,通過腳手架搭建項目

vue create music

vue需要與electron集成,這里社區(qū)已經(jīng)有比較成熟的vue插件了,Vue CLI Plugin Electron Builder

vue add electron-builder

懶人可以直接去clone我的搭建好得架子直接開發(fā), 戳這里。

從零開始-項目開發(fā)

首先先明確下這個播放器的功能需求,主要有這幾個

  • 不添加文件目錄,加載任意的本地文件系統(tǒng)內(nèi)的音頻文件,直接調(diào)用播放器播放
  • 前一首后一首功能
  • 聲音音量控制
  • 自定義軟件窗口

如何關(guān)聯(lián)播放

如何實現(xiàn)關(guān)聯(lián)播放?因為對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的文件系統(tǒng),通過fs.readFileSync讀取到文件的buffer信息。

let buffer = fs.readFileSync(diskPath); //讀取文件,并將緩存區(qū)進行轉(zhuǎn)換

讀取后需要將buffer轉(zhuǎn)換成node可讀流

const stream = this.bufferToStream(buffer);//將buffer數(shù)據(jù)轉(zhuǎn)換成node 可讀流

轉(zhuǎn)換方法 bufferToStream

  bufferToStream(binary) {
   const readableInstanceStream = new Readable({
    read() {
     this.push(binary);
     this.push(null);
    }
   });
   return readableInstanceStream;
  }

轉(zhuǎn)換成流后需要將音頻流轉(zhuǎn)換成blob對象來加載,實現(xiàn)方法

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)
 })
}

轉(zhuǎn)blob

 let fileUrl; // blob對象
 streamToBlob(stream)
  .then(res => {
   fileUrl = res;
   // console.log(fileUrl);

   //將blob對象轉(zhuǎn)成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);
  });

這樣就實現(xiàn)了加載本地文件播放了

上一首下一首功能

這里的上一首下一首的功能是基于上面獲取到的文件的絕對路徑,通過node的path模塊,path.dirname獲取到文件的父級目錄。

const dirPath = path.dirname(diskPath);

然后通過fs.readdir讀取目錄下所有文件,會返回一個文件名數(shù)組,找到該目錄下正在播放的文件的下標(biāo),通過數(shù)組下標(biāo)判斷前一首和后一首歌曲的名稱,然后再組裝成絕對路徑,讀取資源播放

  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);
    }
   });
  },

聲音音量控制

音量控制需要通過監(jiān)聽input的鍵入事件,獲取到range的值,然后通過設(shè)置樣式background-image,動態(tài)計算百分比,然后調(diào)用wavesurfer的setVolume方法調(diào)節(jié)音量

: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));
  },

自定義標(biāo)題欄

個人覺得系統(tǒng)自帶的菜單欄太丑了,就給設(shè)置了無邊框再自己加上最小化,關(guān)閉的功能。最小化,關(guān)閉是通過ipc通信,渲染進程監(jiān)聽到有點擊操作后,通知主進程進行相應(yīng)的操作。

渲染進程

  close() {
   ipcRenderer.send("close");
  },
  minimize() {
   ipcRenderer.send("minimize");
  }

主進程

ipcMain.on("close", () => {
 win.close();
 app.quit();
});

ipcMain.on("minimize", () => {
 win.minimize();
});

打開多個實例的問題

在實際測試的過程中發(fā)現(xiàn)會出現(xiàn),打開一首新的音樂播放,就會出現(xiàn)重新開一個實例的現(xiàn)象,不能實現(xiàn)覆蓋播放,后面查閱資料發(fā)現(xiàn)electron有一個second-instance事件,可以監(jiān)聽是否打開了第二個實例。當(dāng)?shù)诙€實例被執(zhí)行并且調(diào)用 時,這個事件將在應(yīng)用程序的首個實例中觸發(fā),并且會返回第二個實例的相關(guān)信息,然后通過主進程通知渲染進程,告知渲染進程第二個實例的本地絕對路徑,渲染進程接收到信息后,立馬加載第二個實例的資源。app.requestSingleInstanceLock(),表示應(yīng)用程序?qū)嵗欠癯晒θ〉昧随i。 如果它取得鎖失敗,可以假設(shè)另一個應(yīng)用實例已經(jīng)取得了鎖并且仍舊在運行,所以可以直接關(guān)閉掉,這樣就避免了打開多個實例的問題

主進程

const gotTheLock = app.requestSingleInstanceLock();
if (gotTheLock) {
 app.on("second-instance", (event, commandLine, workingDirectory) => {
  // 監(jiān)聽是否有第二個實例,向渲染進程發(fā)送第二個實例的本地路徑
  win.webContents.send("path", `${commandLine[commandLine.length - 1]}`);
  if (win) {
   if (win.isMinimized()) win.restore();
   win.focus();
  }
 });

 app.on("ready", async () => {
  createWindow();
 });
} else {
 app.quit();
}

渲染進程

 ipcRenderer.on("path", (event, arg) => {
  const newOriginPath = arg;

  // console.log(newOriginPath);
  this.loadMusic(newOriginPath);
 });

自動更新

需求的起因是,在很興奮的給女朋友成品的時候,尷尬的被女朋友試出很多bug(捂臉ing),然后頻繁的修改打包,然后通過私發(fā)傳給她。特別麻煩,所以這個需求很急迫。最后查了資料,通過electron-updater實現(xiàn)了這個需求.

安裝electron-updater

yarn add electron-updater

發(fā)布設(shè)置

  electronBuilder: {
   builderOptions: {
    publish: ['github']
   }
  }

主進程監(jiān)聽

autoUpdater.on("checking-for-update", () => {});
autoUpdater.on("update-available", info => {
 dialog.showMessageBox({
  title: "新版本發(fā)布",
  message: "有新內(nèi)容更新,稍后將重新為您安裝",
  buttons: ["確定"],
  type: "info",
  noLink: true
 });
});

autoUpdater.on("update-downloaded", info => {
 autoUpdater.quitAndInstall();
});

生成Github Access Token

因為是用github作為更新站,所以本地需要相應(yīng)的操作權(quán)限,去這里生成token,戳這,生成后,在powershell中設(shè)置

[Environment]::SetEnvironmentVariable("GH_TOKEN","<YOUR_TOKEN_HERE>","User")
# 例如 [Environment]::SetEnvironmentVariable("GH_TOKEN","sdfdsfgsdg14463232","User")

打包上傳Github

yarn electron:build -p always

完成上面步驟后軟件會自動上傳打包后的文件到release,然后編輯下release就可以直接發(fā)布了,軟件是基于版本號更新的,所以記得一定要改版本號

從零開始-結(jié)束

作為程序猿最開心的事莫過于得到女朋友的夸獎,雖然這是一個小程序,實現(xiàn)難度也不高,但是最后做出最小可用的版本呈現(xiàn)在女朋友面前的時候,看到女盆友感動的眼神,我想,這應(yīng)該是我作為程序猿唯一感到欣慰的時候。軟件還有很多可以改進的地方,源碼在此,戳這里Github

到此這篇關(guān)于Electron+vue從零開始打造一個本地播放器的方法示例的文章就介紹到這了,更多相關(guān)Electron+vue本地播放器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論