Web Audio APIで作ったaudio/wav形式の音声を保存する
この(↓)のアプリを作っている間に得た知見
https://github.com/taku-o/myukkurivoice
Web Audio APIで作った音声を保存する方法は、調べると色々出てくるのですが、
- Recorder.js
- MediaStream Recording API
- ScriptProcessorNode
この記事では、自分にはこれが簡単そうだなと思った方法を書きます。
node wave-recorder を使う
node wave-recorder
https://www.npmjs.com/package/wave-recorder
このライブラリを使うと、おおよそこんな感じのコード(↓)で、Web Audio APIで加工した音声データをファイルに保存できます。
YATTAZE簡単!!
少なくとも他の方法よりは。そう見える。
var fs = require('fs'); function to_array_buffer(buf_wav) { var a_buffer = new ArrayBuffer(buf_wav.length); var view = new Uint8Array(a_buffer); for (var i = 0; i < buf_wav.length; ++i) { view[i] = buf_wav[i]; } return a_buffer; }; var a_buffer = to_array_buffer(buf_wav); var audioCtx = new window.AudioContext(); audioCtx.decodeAudioData(a_buffer).then( function(decodedData) { // source var sourceNode = audioCtx.createBufferSource(); sourceNode.buffer = decodedData; sourceNode.onended = function() { recorder.end(); // ここでend()しないと超巨大なファイルが出来る }; // gain var gainNode = audioCtx.createGain(); gainNode.gain.value = volume; // recorder var recorder = WaveRecorder(audioCtx, { // ← recorder作って channels: 1, // ← bitDepth: 16 // ← }); // ← recorder.pipe(fs.createWriteStream(wav_file_path)); // ← // connect and start sourceNode.connect(gainNode); gainNode.connect(recorder.input); // ← 繋げる sourceNode.start(0); });
でも、なんか作った音声ファイルの最後の方が切れるんだけど
ただし、良いことだけでなく、node wave-recorderを試してみると問題も見つかったのです。
作成した音声ファイルの、最後の方がファイルに保存されないのです。
(自分の技量の問題もあるでしょう)
# 音声 こんにちわ # ファイルに保存された状態 (最後の方が欠ける) こんにちw
下のコードで、音声データの加工が終わった時にファイルへの書き出しを閉じているのですが、
onendedイベントのタイミングでは、ストリームを閉じるのが少し早かったりするのでしょう。
// source var sourceNode = audioCtx.createBufferSource(); sourceNode.buffer = decodedData; sourceNode.onended = function() { recorder.end(); };
なお、これを見て、自分が取った解決策が↓である。
// source var sourceNode = audioCtx.createBufferSource(); sourceNode.buffer = decodedData; sourceNode.onended = function() { // onendedのタイミングでは出力が終わっていない setTimeout(function(){ recorder.end(); }, 100); };
汚い!!
でも、事件は現場で起きているんだ!!
(これは、時間があるときに解決を試みることにする)
おまけ。node-wav
node-wav
https://www.npmjs.com/package/node-wav
このようなライブラリも見つけた。wave-recorderから呼び出されていた。
このライブラリはWeb Audio APIで作った音を保存するものではない。
が、ストリームをファイルに保存する機能がある。
audio/wav形式のファイルのヘッダとか、フォーマットとか、その辺の処理をやってくれる。
加工した音声をストリームの形式に持っていけるなら、便利に扱えそうです。
良さそうだったが、今回は使用しなかった。
READMEにはその辺の機能の説明は載っていないが、
落としてみて、lib/file-writer.js とか読むと幸せになれそう。
おわり
最終的には、MediaStream Recording API に移行したい。