Electron Audio Player Sample - Node.js

  • 作成日:
  • 最終更新日:2025/10/11

ディレクトリ構成

  • example
    • audio
      • sample
        • sample1.wav
        • sample2.wav
    • css
      • style.css
    • node_modules
    • app.js
    • index.html
    • package-lock.json
    • package.json
    • preload.js
    • renderer.js

ファイル内容

app.js

const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('node:path');
const fs = require('fs');

const createWindow = () => {
  const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
  preload: path.join(__dirname, '/preload.js')
}
  })

  win.loadFile('index.html');
}

app.whenReady().then(() => {
  createWindow()

  app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
  createWindow()
}
  })
})

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
app.quit()
  }
})

ipcMain.handle('get-dir', (event, dirPath) => {
  const dir = fs.readdirSync(dirPath, { withFileTypes: true });
  return dir;
})

ipcMain.handle('get-file', (event, arr) => {
  const file = fs.readdirSync(arr[0] + arr[1]);
  return file;
})

index.html

<!DOCTYPE html>
<html>
  <head>
<meta charset="UTF-8" />
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'"/>
<script src="./script.js"></script>
<link rel="stylesheet" href="./css/style.css">
<title>Hello Electron</title>
  </head>
  <body>
<h1>Audio Player</h1>
<p><button type="button" id="start">start</button></p>
<p><button type="button" id="stop">stop</button></p>
<p><button type="button" id="cont">continue</button></p>
<p><input type="range" name="volume" id="volume" min="0.0" max="1.0" value="0.5" step=".1"><span id="volume-view"></span></p>
<p><button type="button" id="reset">reset</button></p>
<div id="dir">
  <ul id="dir-target">

  </ul>
</div>
<div id="file">
  <ul id="file-target">
    
  </ul>
</div>
  </body>
</html>

style.css

li {
  list-style: none;
}

preload.js

const { contextBridge, ipcRenderer } =  require('electron');

function checkCheckBox(filesName){
  let arr = [];
  for(let i = 0; i < filesName.length; i++){
if(filesName[i].checked) {
  arr.push(filesName[i].value);
}
  };
  return arr;
}

function checkedRadio(){
  const dirName = document.getElementsByName('dir');
  const len = dirName.length;
  let checkValue = '';

  for (let i = 0; i < len; i++){
if (dirName.item(i).checked){
  checkValue = dirName.item(i).value;
}
  }
  return checkValue;
}

function resetCheckBox(filesName){
  for(let i of filesName){
i.checked = false;
  }
}

contextBridge.exposeInMainWorld('myApi', {
  setup: async ()=>{
const file = document.getElementById('file');
const dirPath = "./audio/";
const start = document.getElementById('start');
const stop = document.getElementById('stop');
const cont = document.getElementById('cont');
const volume_view = document.getElementById('volume-view'); 
const volumeBar = document.getElementById('volume')
const filesName = document.getElementsByName('file');
const reset = document.getElementById('reset');
const fileTarget = document.getElementById('file-target');
const allDirents = await ipcRenderer.invoke('get-dir', dirPath);

const audio = new Audio();
audio.volume = volumeBar.value;
volume_view.innerHTML = volumeBar.value * 10;

for(let i of allDirents){
  document.getElementById('dir-target').innerHTML += `<li><label for="${i["name"]}"><input type="radio" name="dir" id="${i["name"]}" value="${i["name"]}">${i["name"]}</label></li>`;
}
  
const dirAll = document.querySelectorAll("input[name='dir']");
  
for(let element of dirAll) {
  element.addEventListener('change', async function(){
    if( this.checked ) {
      fileTarget.innerHTML = "";
      const files = await ipcRenderer.invoke('get-file', [dirPath, this.value]);
      for(let i of files){
        fileTarget.innerHTML += `<li><label for="${i}"><input type="checkbox" name="file" id="${i}" value="${i}">${i}</label></li>`;
      }
    }
  });
}
  
start.addEventListener('click', function(){
  let arr = checkCheckBox(filesName);
  let checkValue = checkedRadio();
  
  (async function(){
    for(let i of arr){
      await new Promise((resolve) => {
        audio.src = `${dirPath}${checkValue}/${i}`;
        audio.play();
        audio.addEventListener('ended',() => {
          resolve();
        });
      });
    }
  })();
});
  
volumeBar.addEventListener('input', (e) => {
  audio.volume = e.target.value;
  volume_view.innerHTML = audio.volume * 10;
});
  
stop.addEventListener('click', function(){
  if(!audio.paused) {
    audio.pause();
  }
});
  
cont.addEventListener('click', function(){
  audio.play();
});
  
reset.addEventListener('click', function(){
  audio.pause();
  audio.src = "";
  resetCheckBox(filesName);
});
   
  },
})

renderer.js

window.onload = function(){
  window.myApi.setup();
}