Pepper が ogg 形式で録音してくれないので一手間かけた話

**「え？そんなの標準のボックスでできるでしょ？」**

タイトルを見てそう思ったあなた、あなたは騙されているかも知れませんよ！

# 環境
- Pepper 一般販売モデル
- NAOqi OS 2.5.5
- Choregraphe 2.5.5.5

# あらまし
こんにちは。ロボキュアという会社で Pepper アプリを作っているイシハッタです。
Pepper アプリを作っていて躓いた、というより見事にすっ転んだことがあったのでそのことを書いてみようと思います。

# 何があったかというと
## ogg で録音したい
いま開発しているアプリでは音声を録音してファイルに保存する必要があったりします。ただし、諸々の事情でファイルサイズはなるべく小さくしたかったりします。
Choregraphe の標準ボックスライブラリには Record Sound というボックスが含まれています。このボックスはその名の通り録音してファイルに保存する機能を提供しており、しかも録音形式として wav 以外に ogg も選択できるようになっています。だったらこれを使って ogg で録音＆保存すれば万事解決！と思ったわけです。

![RecordSoundBox.png](https://qiita-image-store.s3.amazonaws.com/0/176931/0332051d-ba03-f8eb-571f-3a3963f6846b.png)

で、実際動かしてみるとしっかり録音できますし、指定したファイル名（拡張子 ogg ）で保存されます。適当なプレーヤーソフトで再生すれば録音した音声がちゃんとに再生されます。

「おけ。問題なし」

だからそう思ったわけです。しかし認識が甘かった。チェックが甘かった。

## ファイルサイズおかしくね？
気づいたきっかけはファイルサイズでした。想定よりやたら大きいのです。
Record Sound ボックスでは内部で ALAudioDevice API の startMicrophonesRecording メソッドを使って録音しています。ドキュメントによるとこのメソッドは引数として保存先のファイルパスを受け取り、そのファイルパスの拡張子が ogg だった場合、16ビット、16kHz、モノラルの ogg ファイルを作ってくれることになっています（拡張子が wav の場合は16ビット、48kHz、4チャネルの wav ファイルになるようです）。

> `void ALAudioDeviceProxy::startMicrophonesRecording(const std::string& fileName)`
> This method records the signal collected on the microphones directly into the specified file.
> If the extension of the specified file is ‘wav’, data will be recored as a 16 bits, 48000Hz, 4 channels wav file.
> If the extension of the specified file is ‘ogg’, data will be recored as a 16 bits, 16000Hz, 1 channels ogg file.
> Parameters: fileName – Absolute path of the file
[ALAudioDevice API — Aldebaran 2.5.7.1 documentation.html](http://doc.aldebaran.com/2-5/naoqi/audio/alaudiodevice-api.html#ALAudioDeviceProxy::startMicrophonesRecording__ssCR)

ということは、たとえば10秒の音声を録音した場合、そのデータ量は無圧縮（リニアPCM）で 10×16,000×2=320,000バイトになります。これを Vorbis で圧縮すれば、条件にもよりますが少なくとも数分の1程度にはなるはずです。で、実際にやってみたところ…

![filesize.png](https://qiita-image-store.s3.amazonaws.com/0/176931/0ac9f419-3cea-73b0-57c4-b9d1fe4b5ab9.png)

小さくなってないじゃん！（微妙に小さくなってるけど、これはタイマー開始から実際に録音開始するまでのタイムラグによるものと思われます）
これはもしかしたら…と思い、保存された ogg （のはずの）ファイルをバイナリエディタで開いてみました。

![wavefmt.png](https://qiita-image-store.s3.amazonaws.com/0/176931/0798e4f2-c30d-3dc5-d906-e07bd69c930d.png)

**君はれっきとした WAV ファイルですね！**

# 原因はどこに？
おそらく NAOqi OS のバグです。
Record Sound ボックスの実装にはバグらしいものは見当たりませんでした。また、 ALAudioDevice API の代わりに ALAudioRecorder API を使って同様のこと（録音して ogg で保存）をやってみましたが、やはり保存されるファイルの中身は WAV でした（そもそも録音用の API がなぜ二つあるのかもよく分かりません）。

# ではどうするか？
仕方がないので録音したデータはいったん WAV ファイルに保存し、それを ffmpeg で ogg に圧縮することにしました。
Record Sound ボックスのコードを改造して動くようにしたのですが、ソースを全公開すると著作権的にどうなのか分からないので、ポイントだけ書いておきます。

- ALAudioDevice の代わりに ALAudioRecorder を使って明示的に16kHzモノラルの WAV ファイルを作る。
- 録音が終わったタイミングで ffmpeg で ogg に変換する（以下がそのコードです）。

```python
    def onUnload(self):
        if( self.bIsRecording ):
            self.ad.stopMicrophonesRecording()
            # oggへ変換
            if self.sExtension == ".ogg":
                out_file = self.filepath[0:-3] + "ogg"
                if os.path.exists(out_file):
                    os.remove(out_file)
                subprocess.call(["/usr/bin/ffmpeg", "-i", self.filepath, "-acodec", "libvorbis", "-f", "ogg", out_file])
                os.remove(self.filepath)
                self.filepath = out_file
            self.bIsRecording = False
        self.bIsRunning = False
```

# そもそも
ドキュメントには「 ogg ファイルにできる」とは書いてあるのですがコーデックが何なのか（ Vorbis とか）が書かれていない時点で何かおかしいなとは思ったのです・・・。