クラウドにAsterisk立てて[SIPクライアント-(WebRTC)-WEBブラウザ]間でビデオ通話した時のメモ


Asteriskはバージョン11からWebRTCでの音声通話に、バージョン12からビデオ通話にも対応しているらしいとどっかで読んだので試してみた。

特に外出先から事務所に電話するような場合を想定し、スマートフォン側はSIPクライアントアプリ、パソコン側はWebRTCに対応したWebアプリで通話できるか試してみたかった。

## 目的

* スマートフォン等のSIPクライアントどうしで、インターネット越しに通話してみたい。
* スマートフォン等のSIPクライアントと、パソコンのWEBブラウザでIP電話してみたい
* その時の通話品質を知りたい
* できたらビデオ通話もしてみたい


~~残念ながら今回はビデオ通話まではできなかった...orz~~
だがしかしSIPクライアント - WebRTC経由ブラウザ間での音声通話はバッチリできましたʕ•̫͡•ʔ

9月28日追記：
ビデオ通話もできました！

## サーバー環境

インストール対象OSは```Ubuntu 14.04 x64```。 [DigitalOcean](https://cloud.digitalocean.com/)のシンガポールに最小の仮想サーバーたてて、そこにセットアップした。

DigitalOceanは最も安い$5/月のサーバーでデータ転送1TB/月ついてくるので、まあ検証や身内で使う分には超えないと思う。

なお、インターネットにAsteriskをさらすとスマートフォンやPCを使ってどこからでも内線みたいな事ができるけど、当然セキュリティリスクがあるので、そこんとこは自己責任で！
今回はあくまで検証用に一時的にサーバーをクラウド上に立てました。

## 環境セットアップ

ビルドの為の環境一式を揃える。Asterisk12からlibjanssonが必要らしい。

```
$ apt-get install make automake gcc g++ ncurses-dev openssl libssl-dev
$ apt-get install libxml2 libxml2-dev sqlite3 libsqlite3-dev pkg-config
$ apt-get install libsrtp0 libsrtp0-dev
$ apt-get install libjansson4 libjansson-dev
```


WebRTCしたい場合はuuid関係も必要

```
$ apt-get install uuid uuid-dev
```

## PJPROJECTのインストール

Asteriskは12からPJPROJECTを別途インストールする必要があるらしい。
なので、まずはこれをインストールする。
[PJSIPのダウンロードページ](http://www.pjsip.org/download.htm)から最新のPJPROJECTのソースを落とす。

なお、PJPROJECTをインストールしなくても通常のSIPフォン同士での通話は可能。
ただし、WebRTCを使ったブラウザとの通話などはできない(ICEが使えない)ため、それをやりたい場合はインストールが必要。

```
$ tar xvjf pjproject-2.3.tar.bz2
$ cd pjproject-2.3
$ ./configure --prefix=/usr --enable-shared --disable-sound --disable-resample --disable-video --disable-opencore-amr
$ make dep
$ make
$ sudo make install
$ ldconfig
```

一応確認

```
$ ldconfig -p | grep pj
```

なお、pkg-configが入っていないと、インストールしたPJPROJECTをAsteriskのconfigure時に認識してくれない。僕はこれで３時間くらいはまりました... でもこれ、[公式ページ](https://wiki.asterisk.org/wiki/display/AST/Building+and+Installing+pjproject)にちゃんと書いてあるんですよね。ちゃんと読めってはなし。

## Asteriskのビルドとインストール

Asteriskのソースは以下から入手する。
[Asteriskダウンロードサイト](http://asterisk.org/downloads/asterisk/all-asterisk-versions)

今回は表題通り、WebRTCでVideo通話に対応した<code>Asterisk 12</code>を落とした。

僕はソースからインストールするときは```/usr/local/<アプリ名>/<バージョン名>```のようなパスにインストールする事にしているので、以下のように```--prefix```オプションでインストール先を指定。普通に```/usr/local```以下にインストールする場合は必要ない。

```
$ ./configure --prefix=/usr/local/asterisk/12
```


```./configure``` したら ```make menuselect``` して ```res_pjsip``` が認識されている事を確認する。

```
$ make menuselect
```

```Resource Modules``` -> ```res_pjsip_<ほにゃらら>``` が有効になっている事を確認。

```
[*] res_pjsip                                                 
[*] res_pjsip_acl                                                                  
[*] res_pjsip_authenticator_digest
[*] res_pjsip_caller_id
[*] res_pjsip_dialog_info_body_generator
[*] res_pjsip_diversion
[*] res_pjsip_dtmf_info
[*] res_pjsip_endpoint_identifier_anonymous
[*] res_pjsip_endpoint_identifier_ip
[*] res_pjsip_endpoint_identifier_user
[*] res_pjsip_exten_state 
[*] res_pjsip_header_funcs                                         
[*] res_pjsip_log_forwarder                                              
[*] res_pjsip_logger                                                                  
[*] res_pjsip_messaging                                              
[*] res_pjsip_multihomed                                                     [*] res_pjsip_mwi 
... More ...
```

上記のようになっていたらOK。
ビルド、インストールを行う。

```
$ make
$ sudo make install
```

設定ファイルのサンプルをインストールしたい場合は以下を実行

```
$ sudo make samples
```

## 自動起動の設定

以下を実行すると環境に合わせて自動起動の設定をしてくれるみたい。

```
$ sudo make config
```

## 起動

```
$ /etc/init.d/asterisk start
```

## 設定

例として以下のように設定する。

* ユーザー```2001```,```2002```,```2003```はスマートフォンなどのSIPフォンから使用するユーザー。
* ユーザー```2004```はパソコンのブラウザなどからWebRTC経由で使用するユーザー。

### sip.conf

上記prefixを指定している場合は```/usr/local/asterisk/12/etc/asterisk/sip.conf```を編集する。

以下の設定がコメントアウトされているので先頭の```;```を外して編集する。

```
icesupport = yes
allowguest=no
realm=sip.hogetara.co.jp
videosupport=yes

disallow=all
allow=gsm
allow=ulaw
allow=ilbc
allow=vp8 ; Video codec from here.
allow=h264
allow=h263
allow=h263p
```

ビデオ通話をする為には<code>videosupport=yes</code>が必要。

SIPフォンユーザーの設定```sip.conf```の末尾に追加。

contextを```sip.hogetara.co.jp```としてるけど、必要に応じて変えてほしい。

あとパスワードを```pass```としてるけど、ログを見てるとわかるけどクラウド使ったりしてインターネットにさらすと結構ボットによるアクセスと思われるものがあるので```pass```のままはまずいと思う。適当に変える。

```
[2001]
type=friend
defaultuser=2001
secret=pass
canreinvite=no
host=dynamic
context=sip.hogetara.co.jp
allow=vp8,h264
nat=yes

[2002]
type=friend
defaultuser=SOMEI Yoshino
secret=pass
canreinvite=no
host=dynamic
context=sip.hogetara.co.jp
allow=vp8,h264
nat=yes

[2003]
type=friend
defaultuser=2003
secret=pass
canreinvite=no
host=dynamic
context=sip.hogetara.co.jp
allow=vp8,h264
nat=yes
```

WebRTCユーザー

```
[2004]
type=friend
defaultuser=2004
username=2004   ; The Auth user for SIP.js
host=dynamic    ; Allows any host to register
secret=pass     ; The SIP Password for SIP.js
encryption=yes  ; Tell Asterisk to use encryption for this peer
avpf=yes        ; Tell Asterisk to use AVPF for this peer
icesupport=yes  ; Tell Asterisk to use ICE for this peer
context=sip.hogetara.co.jp ; Tell Asterisk which context to use when this peer is dialing
directmedia=no   ; Asterisk will relay media for this peer
transport=udp,ws ; Asterisk will allow this peer to register on UDP or WebSockets
force_avp=yes    ; Force Asterisk to use avp. Introduced in Asterisk 11.11
dtlsenable=yes   ; Tell Asterisk to enable DTLS for this peer
dtlsverify=no    ; Tell Asterisk to not verify your DTLS certs
dtlscertfile=/etc/asterisk/keys/asterisk.pem ; Tell Asterisk where your DTLS cert file is
dtlsprivatekey=/etc/asterisk/keys/asterisk.pem ; Tell Asterisk where your DTLS private key is
dtlssetup=actpass ; Tell Asterisk to use actpass SDP parameter when setting up DTLS
allow=vp8,h264
nat=yes
```

* ```nat=yes``` は非推奨ぽいけど、他の設定ではNAT越えでの通話がうまくいかなかった。ここんとこはもうちょっと調べる必要有り。
* <code>allow=vp8,h263</code>は各ユーザーの設定に書いておかないとビデオ通話できなかった。


### extensions.conf

適当なところに以下を追加

```
[sip.hogetara.co.jp]
exten => _200Z,1,Dial(SIP/${EXTEN},30)
exten => _200Z,2,Congestion
exten => _200Z,102,Busy
```

### rtp.conf

rtpstartとかは最初からこうなってたかもしれない...

```
rtpstart=10000
rtpend=20000
icesupport=yes
```

### http.conf

```
[general]
enabled=yes
bindaddr=0.0.0.0
bindport=8088
prefix=asterisk
```

### TLS証明書の作成

asteriskソースコードを解凍したディレクトリ以下(今回はasterisk-12.6.0)で以下のコマンドを実行

```
$ sudo mkdir -p /etc/asterisk/keys
$ sudo ./contrib/scripts/ast_tls_cert -C sip.hogetara.co.jp -O "HogeTara Company" -d /etc/asterisk/keys/
```

これによって```/etc/asterisk/keys```以下にasterisk.pemがつくられる。
なお、```sip.hogetara.co.jp```と```HogeTara Company```は自身のドメインと組織名で実行すること。


ここまで設定を保存したらasteriskを再起動。

```
$ sudo /etc/init.d/asterisk restart
```

## クライアント環境

* iPhoneのSIPクライアントは無料の[Zoiper](http://www.zoiper.com/en)を使用。
* ブラウザは[sipml5のデモアプリ](http://sipml5.org/call.htm)を使用。

sipml5のデモアプリは最初に```Expert mode?```をクリックして細かい設定を行っておきます。
<code>Disable Video</code>は、音声通話のみ試す場合はチェックを入れておきます。ビデオ通話を試す場合はチェックを外します。
![スクリーンショット 2014-09-26 19.57.53.png](https://qiita-image-store.s3.amazonaws.com/0/13835/c9d16d91-3401-f782-4cc6-7befd67f8e60.png "スクリーンショット 2014-09-26 19.57.53.png")


続いて```Registration```の設定に戻って以下のように
![スクリーンショット 2014-09-26 19.56.58.png](https://qiita-image-store.s3.amazonaws.com/0/13835/7fdf651b-6cf7-da58-0809-e463b0d67eca.png "スクリーンショット 2014-09-26 19.56.58.png")



```sip.hogetara.co.jp``` は適当なので接続先に応じて変更を。
```Login```ボタンをクリックして、このスクショの用に上部に```connected```とでたらOK。この状態から電話をかけることも、着信する事もできる。

あとはスマートフォン側のSIPクライアントも適当に設定して、SIPクライアントから```2004```に電話をかければブラウザで着信できる。
着信するとマイクの使用許可を求められるので許可して、```Answer```をクリックすれば通話がはじまる。

## 所感

Asteriskはドキュメントはしっかり作ってあるのでその点は助かりました。ただビルド時にuuid関係やPJSIPが入っていなかったりしてもとりあえずビルド・インストールできてしまい、実際試したときには通話が出来ずに、かつサーバーサイドではエラーが出ないなどの問題が発生するので、そういう時は原因を突き止めるまでに苦労しました。

そのようなとき、例えばWebRTCでうまく通話できないときは、sipml5デモサイトではExpert Settingでデバッグメッセージを有効にしてChromeのDeveloper Toolsに出力されるデバッグメッセージを注意深く見れば原因にたどり着けます。

SIPクライアントも今回使用したZoiperにはSIPメッセージのやりとりをトレースする機能があるので、それを使って原因を追いました。
闇雲に設定を変更するとどれが効いたのかわからなくなるので、上記のデバッグツールを有効に使って原因追及するのが近道だと思います。

音質ですが、スマートフォン同士でZoiperを使った場合は、双方WiFiの場合は電話と同等とまではいかないまでも十分な品質でした。また4Gでもかなり快適に話せましたが3Gではちょっと聞き取りづらくなりました。
また、MacBookのChromeとWebRTC経由で話した時は相手の喋っている内容が聞き取りづらかったです。この辺はなにか設定等で改善できるかもしれません。今後の課題です。

最後に、今回試したWebRTC経由での通話が出来れば、他のWebアプリと連携して、例えば社内システムと連携して電話をかけてきた人の情報をブラウザ画面上に表示するなど、色々と可能性が広がると感じました。今までであればかなり高いお金を払ってそういうシステムを購入する所ですが、頑張れば自社で電話と連携したシステムを組むのも現実的な選択肢になりうると思います。

それとやっぱりこういうのは面白いですw 淡々と書いてますがiPhoneのSIPクライアントからWebRTC経由でWebブラウザに着信して呼び出し音が鳴った時はかなり興奮しましたw 
~~あとはやっぱりビデオ通話したいです。引き続き色々やってみます。~~

9月28日追記:
色々と試してたらビデオ通話できました。といってもやるのは<code>sip.conf</code>に<code>videosupport=yes</code>および、各ユーザーに<code>allow=vp8,h263</code>を入れるだけです。これでビデオ通話に対応したSIPクライアント同士、SIPクライアントとWebRTC経由でブラウザとビデオ通話ができました。h263は画像もとびとびであまり実用的ではありませんでしたが、VP8でのビデオ通話は多少画像がボヤっとしているもののかなりスムーズで実用レベルだと感じました。