LoginSignup
5
11

More than 5 years have passed since last update.

electronでローカルファイルから音声再生を試してみる

Posted at

JavaScriptで音声再生完了タイミングを取得したい。
で音は鳴らせたので、それを試しにelectronで動かしてみる。
XMLHttpRequestではなくて
nodeのreadFileでローカルファイルを読んで音声鳴らしたい。

electronのインストール

npm install -g electron

プロジェクトの作成と初期設定

mkdir electron-test
cd electron-test
npm init -y

出来上がったpackage.jsonについて編集する。
mainをmain.jsとしておき
main.jsファイルを作成する

package.json
{
    ...
    "main": "main.js",
    ...
}
main.js
'use strict';

var electron = require('electron');
var app = electron.app;
var BrowserWindow = electron.BrowserWindow;

var mainWindow = null;

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

app.on('ready', function() {

  // ブラウザ(Chromium)の起動, 初期画面のロード
  mainWindow = new BrowserWindow({width: 800, height: 600});
  mainWindow.loadURL('file://' + __dirname + '/index.html');

  mainWindow.on('closed', function() {
    mainWindow = null;
  });
});

メインの処理の移植

index.html, 1.wav, 2.wavは
前回のものをそのままコピーする。
test.jsについてローカルファイルから読み込むように修正

test.js
'use strict';

var electron = require('electron');
var remote = electron.remote;
var fs = remote.require('fs');

window.AudioContext = window.AudioContext || window.webkitAudioContext; 
var context = new AudioContext();

var toArrayBuffer = function(buf){    
    return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
}
var schedule = [
    {"time":0, "file":"1.wav"},
    {"time":5, "file":"2.wav"}
];
var plans = []
var getAudioBuffer = function(schedule, index){
    if(index >= schedule.length){
        document.getElementById('btn').disabled = false;
        return;
    }
    plans[index] = {
        "time":schedule[index]['time'],
        "buffer":null
    };
    fs.readFile(schedule[index]['file'], function(err, data){
        context.decodeAudioData(toArrayBuffer(data), function(buffer){
            plans[index]['buffer'] = buffer;
        });
        getAudioBuffer(schedule, index+1);
    });
};

var planid = 0;
var playSound = function(){
    var source = context.createBufferSource();
    source.buffer = plans[planid]['buffer'];
    source.onended = function(){
        planid++;
        if(planid < plans.length){
            setTimeout(playSound, plans[planid]['time']*1000);
        }
    };
    source.connect(context.destination);
    source.start(0);
}

window.onload = function(){
    getAudioBuffer(schedule, 0);
    var btn = document.getElementById('btn');
    btn.onclick = function(){
        planid = 0;
        playSound();
    }
}

ローカルファイルの読み込み

fsライブラリを利用してfileの読み込みをするので
requireする。

var electron = require('electron');
var remote = electron.remote;
var fs = remote.require('fs');

remote.requireについては
electronはマルチプロセスで動いていて
electronの描画用のプロセスではなく
読み込んで表示するブラウザ側のプロセスで動かすものは
remote経由で読み込む必要があるとの事。
ブラウザ側で動かす話なので、remote付けてrequireしている。

ファイルの読み込みは、前回はXMLHttpRequestで行っていたが
同部分はfs.readFileに変更する。
decodeAudioDataに渡すには、ArrayBufferでないといけないので
受け取ったBufferをArrayBufferとして扱うようにする。
node 4.x以降ならBuffer.bufferでArrayBufferを取得できる様子。
それをsliceでオフセット考慮して中身取り出す形で対応。

var toArrayBuffer = function(buf){    
    return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
}
    fs.readFile(schedule[index]['file'], function(err, data){
        context.decodeAudioData(toArrayBuffer(data), function(buffer){
            plans[index]['buffer'] = buffer;
        });
        getAudioBuffer(schedule, index+1);
    });

実行

electron .

exeで纏めたりする等やることはまだ残っているけども
一応ローカルファイルを読み込んで音声再生はできた。

参考

Electronでアプリケーションを作ってみよう
Convert a binary NodeJS Buffer to JavaScript ArrayBuffer

5
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
11