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
ファイルを作成する
{
...
"main": "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についてローカルファイルから読み込むように修正
'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