Web Audio APIを使えば音声データをブラウザ上で流したり、それにフィルタをかけたり色々なことができます。録音ももちろんできますがファイルとして保存したり、ArrayBuffer
にしてバックエンドに渡したい場合などは少々手順が必要です。なので、TypeScriptで書いたMediaRecorder
のWrapperクラスをここにまとめておきます。
declare const MediaRecorder: any; // 2018年6月5日現在では型宣言が自前で必要
class Recorder {
// インスタンス作成時にMediaRecorderを初期化
private recorder = navigator.mediaDevices.getUserMedia({
audio: true,
video: false,
}).then((stream) => new MediaRecorder(stream));
public startRecording = async (): Promise<void> => {
const recorder = await this.recorder;
if (recorder.state === "recording") {
throw new Error("duplicate recording");
}
recorder.start();
}
public stopRecording = async (): Promise<AudioBuffer> => {
const recorder = await this.recorder;
const blob: Promise<Blob> = new Promise((resolve) =>
recorder.ondataavailable = ({ data }) => resolve(data));
recorder.stop(); // この時点でrecorder.ondataavailableコールバックが呼ばれる
// Blob -> ArrayBuffer
const reader = new FileReader();
const buffer: Promise<ArrayBuffer> = new Promise((resolve) =>
reader.onload = () => resolve(reader.result));
reader.readAsArrayBuffer(await blob); // loadイベントが発動しreader.resultにblobの中身が書き込まれる
// ArrayBuffer -> AudioBuffer
return await (new AudioContext()).decodeAudioData(await buffer);
}
}
因みに、録音した音声を再生したいというだけであればもっと簡単です。MediaRecorder
を使用せずnavigator.mediaDevices.getUserMedia()
から返されたMediaStream
を引数にAudioContext.createMediaStreamSource
からSourceNodeを作るだけです。詳細はここ。