Monacaでボイスレコーディングアプリを作る（その2：音声録音とファイルストアへのアップロード）

NCMBとMonacaを使ってボイスレコーディングアプリを作ります。HTML APIだけを使うので、プラグインを使わずに開発できます。録音した音声をNCMBのファイルストアへアップロードし、逆にダウンロードして再生できるアプリです。

[前回の記事では画面の説明とSDKの導入まで進めました](https://qiita.com/goofmint/items/cd1993c5921d4a160f0e)ので、今回は音声録音処理と、NCMBのファイルストアへアップロードする処理を実装します。

## コードについて

今回のコードは[NCMBMania/monaca\-voice\-recorder](https://github.com/NCMBMania/monaca-voice-recorder)にアップロードしてあります。実装時の参考にしてください。

## 今回の処理について

今回の処理はすべて `www/pages/home.html` に記述しています。

## 必要な変数の用意

まず録音関係で必要な変数を準備します。

```js
// 録音系のオブジェクト
let recorder, audioExtension;
let audioData = [];
// 録音状態
let status = 'ready';
// 既存の録音データが入る配列
let files = [];
```

## 録音ボタンを押した際の処理

録音ボタンを押した際には `start` 関数を呼び出します。

```html
$h`<button class="button button-large button-fill" @click=${start}>録音開始</button>` :
```

以下の処理は `start` 関数の中に記述します。

```js
// 録音開始ボタンを押した時の処理
const start = async (e) => {
	e.preventDefault();
	// この中に記述する
}
```

### 初期化

すでに録音を行っている場合もありますので、録音データを初期化します。

```js
// 初期化
audioData = [];
```

### オーディオ入力用ストリームを作成

録画用のオーディオ入力用ストリームを作成します。 `{ audio: true }` を指定することで、録音のみ行うようになります。

```js
// オーディオ入力用ストリームを作成
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
// MediaRecorderを作成
recorder = new MediaRecorder(stream);
```
![IMG_1175.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/621d7475-f4f7-96a4-3211-262df9f25a0a.png)


### イベントの設定

録音中、録音終了時のイベントをそれぞれ指定します。

```js
// 録音中に呼ばれるイベント
recorder.addEventListener('dataavailable', _dataavailable);
// 録音終了時に呼ばれるイベント
recorder.addEventListener('stop', _stop);
```

### 録音開始

準備が終わったので録音を開始します。

```js
// 録音開始
recorder.start();
```

### 画面表示更新

`status` を変更して、画面表示に反映します。

```js
// 画面表示用にステータス変更
status = 'recording';
// 画面更新
$update();
```

## 録音時の処理

録音が実行されていると、常時 `_dataavailable` が呼び出されます。

このタイミングで、データのフォーマットから拡張子を指定します。例えばiOSの場合は `audio/mp4` で、 Androidは `audio/webm;〜` などとなります。拡張子は正規表現で取得します。

```js
const _dataavailable = (e) => {
	// 送られてくるデータを追加
	audioData.push(e.data);
	// 拡張子を設定
	audioExtension = e.data.type.match(/audio\/(.*?)($|;)/)[1];
}
```

## 録音終了時のイベント

録音を終了させるのは `stop` 関数を呼び出す時です。これはHTML画面で録音終了ボタンを押した際のイベントになります。

```html
$h`<button class="button button-large button-fill" @click=${stop}>録音終了</button>`
```

この `stop` 関数ではレコーダーの処理をストップさせるだけです。そして、録音状態をリセットして、画面表示に反映させます。

```js
const stop = (e) => {
	e.preventDefault();
	// 録音停止
	recorder.stop();
	// ステータスリセット
	status = 'ready';
	$update();
}
```

録音状態が停止すると、 `_stop` 関数が呼ばれます。これは元々レコーダーに対して指定していたイベントです。

```js
// 録音終了時に呼ばれるイベント
recorder.addEventListener('stop', _stop);
```

## 録音終了時の処理

以下は `_stop` 関数の内容です。

```js
const _stop = async (e) => {
	// この中に記述
}
```

### 蓄積した録音データをBlobオブジェクトに変換

録音データをNCMBで扱えるBlobオブジェクトに変換します。

```js
// 録音データをBlobに変換
const audioBlob = new Blob(audioData);
```

### ファイル名を生成

ファイル名を生成します。今回はタイムスタンプを使っているだけですが、複数人で同時に使う可能性がある場合にはランダムな文字列を生成する方が良いでしょう。

```js
// ファイル名生成（タイムスタンプを利用）
const d = new Date();
const fileName = `record_${d.getTime()}.${audioExtension}`;
```

### NCMBへのファイルアップロード

最後にファイルアップロードを行います。

```js
// NCMBへアップロード
const file = await ncmb.File.upload(fileName, audioBlob);
```

### 結果を配列に追加する

返ってきたファイルオブジェクトを配列に追加して、画面を更新します（一覧表示については次回の記事で解説します）。

```js
// 一覧に追加
files.push(file);
// 描画更新
$update();
```

## まとめ

今回はボイスレコーディングアプリの録音とファイルストアへのアップロード処理について解説しました。次は[ファイルストアの検索と一覧表示、録音データの再生までを実装](https://qiita.com/goofmint/items/583889bcf4466ca123fb)します。