VoIP Linphone install on Orange Pi PC

Orange Pi PCには、デフォルトでマイク・IR受光部が備わっています。これを活用したIP電話をOrange Pi PCで構築します。ここではインストールから稼働するまでの問題とその対処法を時系列で掲載します。VoIPサービスにはLinphoneを採用します。

linphone-cli
https://pkgs.org/download/linphone-cli

Linphone | Linphone

Linphone is an open source SIP Phone, available on mobile and desktop environments (iOS, Android, Windows Phone 8, GNU/Linux, Windows Desktop, MAC OSX) and on web browsers.

オープンソースで各OSに対応していること、ターミナル上でのコマンド制御ができること、サービスの歴史などが採用理由です。

VoIP LinphoneをOrange Pi PCにインストール

sudo apt-get install linphone

起動コマンド

linphonec

以下エラーメッセージへの対応。

https://lists.nongnu.org/archive/html/linphone-developers/2009-07/msg00018.html

ortp-error-snd_pcm_avail_update: Broken pipe
ortp-error-*** alsa_can_read fixup, trying to recover
ALSA lib pcm.c:7843:(snd_pcm_recover) overrun occurred

設定ファイル ~/.linphonerc 内の
各コーディックセクション (pcmu、pcmaは除く) named audio_codec_%i を enable=0 とします。

.linphonerc設定ファイルのヒント

SIPセクション
ポートの設定によりSIPによるユーザ認証ができない場合があります。

[sip]
sip_port=0  --->"0" means inactive 
sip_tcp_port=5060
sip_tls_port=0

または、

[sip]
sip_port=5060
sip_tcp_port=0
sip_tls_port=0

デーモンでの起動に設定ファイルを使用する場合。
linphonecsh init -c <path to config file>

参照マニュアル
http://www.linphone.org/technical-corner/linphone/documentation

サウンドセクションヒント
オーディオ再生中にリングトーンが再生しない場合に注意。
ALSAのミキサーセッティングも必要。
<— … の箇所はコメントのため削除して下さい。

[sound]
ringer_dev_id=ALSA: default device
playback_dev_id=ALSA: audiocodec <--- default device or audiocodec
capture_dev_id=ALSA: audiocodec
echocancellation=0
ec_delay=0
ec_tail_len=60
ec_frame_size=128
#alsadev=audiocodec <----コメントアウト
remote_ring=/usr/share/sounds/linphone/ringback.wav
local_ring=/usr/share/sounds/linphone/rings/nokia_tune_2014.wav
playback_gain_db=10 <--- arbitrary value
mic_gain_db=10 <--- arbitrary value

ALSAマルチ音声出力対応

/etc/asound.conf を作成してマルチ音声に対応します。

まず以下コマンドでサウンドデバイスを確認します。

aplay -l

**** List of PLAYBACK Hardware Devices ****
card 0: audiocodec [audiocodec], device 0: SUNXI-CODEC sndcodec-0 []
  Subdevices: 0/1
  Subdevice #0: subdevice #0
card 1: sndhdmi [sndhdmi], device 0: SUNXI-HDMIAUDIO sndhdmi-0 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0

3.5mmオーディオジャック出力はデバイス名がaudiocodec, card 0, device 0 となります。

この場合、以下のasound.confにはhw:0,0と指定します。hw:[card],[device]

HDMIの場合はhw:1,0となります。

3.5mmオーデイオジャックのみで音声の同時再生をする場合は、/etc/asound.confは以下のようになります。

pcm.!default {
  type plug
  slave.pcm "dmixer"
}

pcm.dmixer  {
  type dmix
  ipc_key 1024
  slave {
    pcm "hw:1,0" # "hw:1,0" means HDMI change to "hw:0,0" for analog lineout jack output
    period_time 0
    period_size 1024
    buffer_size 4096
    rate 44100
  }
  bindings {
    0 0
    1 1
  }
}

ctl.dmixer {
  type hw
  card 0
}

ctl.!default {
    type hw
    card 0
}

<参考>
https://wiki.archlinux.org/index.php/Advanced_Linux_Sound_Architecture/Troubleshooting#Simultaneous_playback_problems

ソフトボリュームの追加

https://wiki.archlinuxjp.org/index.php/Advanced_Linux_Sound_Architecture/トラブルシューティング

 pcm.!default {
   type plug
   slave.pcm "softvol"
 }
 pcm.dmixer {
      type dmix
      ipc_key 1024
      slave {
          pcm "hw:0,0"
          period_time 0
          period_size 4096
          buffer_size 131072
          rate 50000
      }
      bindings {
          0 0
          1 1
      }
 }
 pcm.dsnooper {
      type dsnoop
      ipc_key 1024
      slave {
          pcm "hw:0,0"
          channels 2
          period_time 0
          period_size 4096
          buffer_size 131072
          rate 50000
      }
      bindings {
          0 0
          1 1
      }
 }
 pcm.softvol {
      type softvol
      slave { pcm "dmixer" }
      control {
          name "Master"
          card 0
      }
 }
 ctl.!default {
   type hw
   card 0
 }
 ctl.softvol {
   type hw
   card 0
 }
 ctl.dmixer {
   type hw
   card 0
 }

Linphone起動スクリプト作成

sudo pico /etc/init.d/linphonecsh

#!/bin/sh
### BEGIN INIT INFO
# Provides:          linphone
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Starts Linphone daemon.
# Description:       Linphone is used to call and receive message on VoIP System.
### END INIT INFO
sudo linphonecsh init -c /to_configfile_dir/.linphonerc

実行権の付与

sudo chmod +x /etc/init.d/linphonecsh

起動時スクリプトの登録

sudo update-rc.d linphonecsh defaults

マイクが備わっていないRaspberry Piへのインストールの際には[sound]設定が異なります。3.5mmオーディオジャックではマイクを使用できないためUSBマイクを使用します。以下コマンドでUSBマイクデバイス名を確認し、それをlinphonercの[sound]の項目に記述して下さい。

$ cat /proc/asound/cards

 0 [ALSA           ]: bcm2835 - bcm2835 ALSA
                      bcm2835 ALSA
 1 [Device         ]: USB-Audio - USB PnP Sound Device
                      C-Media Electronics Inc. USB PnP Sound Device at usb-3f980000.usb-1.4, full spe

以下コマンドを実行することで音声入力・出力デバイスの設定、デバイス名の確認ができます。

alsamixer

linphonercの[sound]項目を変更

[sound]
ringer_dev_id=ALSA: default device または bcm2835 ALSA
playback_dev_id=ALSA: default device  または bcm2835 ALSA
capture_dev_id=ALSA: USB PnP Sound Device
#alsadev=audiocodec コメントアウト

補足:USBマイクテスト

マイクの確認

$ arecord -l

**** List of CAPTURE Hardware Devices ****
card 1: Device [USB PnP Sound Device], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

マイクテスト:録音 デバイス1—>plughw:1,0 <----- card 1, device 0

$ arecord --device=plughw:1,0 -d 10 /tmp/test-mic.wav

マイクテスト:再生

$ aplay /tmp/test-mic.wav

Linphoneサービスを開始してユーザ認証されているか確認します。

Linphoneの起動

$ sudo service linphone start 

ユーザ認証の確認

$ sudo linphonecsh generic "proxy list"

ユーザ登録はSIP Proxyサーバにて行われるため、SIP Proxyサーバとユーザ名を指定します。

****** Proxy 0 - this is the default one - *******
sip address: <sip:sip.linphone.org>
route: sip:sip.linphone.org
identity: sip:xxxxxxx@sip.linphone.org
register: yes
expires: 3600
registered: yes --->NGの場合noとなります。

registered: no の場合は .linphonerc 設定ファイルのポートの箇所を再確認して下さい。

linphonecがシステムデーモンとして起動している場合にはlinphonecshコマンドが便利です。

linphonecsh - Sends a command to a linphonec running in daemon mode, and exits.

SYNTAX
       linphonecsh init  <optional linphonec args>
       linphonecsh exit linphoneを終了します。
       linphonecsh generic  <linphonec command line surrounded by quotes> linphonecコマンドを" "で囲み実行します。
       linphonecsh register  --username <username> --host <proxy> --password <password>
       linphonecsh unregister
       linphonecsh dial <sip address or number>
       linphonecsh status <domain = one of 'register', 'hook', 'autoanswer'>
       linphonecsh --help

linphonecコマンド
http://www.linphone.org/technical-corner/linphone/documentation

ALSA asound.conf 修正
モノマイクのため以下の設定に修正。
(/etc/asound.confで設定している場合には必要ありません。ユーザレベルの設定である.asoundrcとシステムレベルの設定である/etc/asound.confとの内容重複は避けて下さい。)

またシステムユーザと他のユーザでdmixをシェアする設定はコメントアウトします。

#   ipc_key_add_uid false   # let multiple users share
#   ipc_perm 0666           # IPC permissions for multi-user sharing (octal, default 0600)

/etc/asound.conf

 pcm.!default {
   type asym
   playback.pcm "plug:softvol"
   capture.pcm "plug:dsnooper"
 }
 pcm.dmixer {
      type dmix
      ipc_key 321456 #any unique value
      # ipc_key_add_uid true マルチユーザでシェアするかどうかの設定です。コメントアウトした方がいいかもしれません。
      slave {
          pcm "hw:0,0"
          period_time 0
          period_size 4096
          buffer_size 16384
          rate 48000
      }
      bindings {
          0 0
          1 1
      }
 }
 pcm.dsnooper {
      type dsnoop
      ipc_key 821456
      slave {
          pcm "hw:0,0"
	  channels 2
          period_time 0
          period_size 4096 
          buffer_size 16384
          rate 48000
      }
 }
 pcm.softvol {
      type softvol
      slave { pcm "dmixer" }
      control {
          name "Master"
          card 0
      }
 }
 ctl.softvol {
   type hw
   card 0
 }
 ctl.!default {
   type hw
   card 0
 }

呼出に反応しない場合のトラブルシュートです。
https://www.pks.mpg.de/~mueller/docs/suse10.1/suselinux-manual_en/manual/sec.linphone.trouble.html

DTMFを有効にすることで改善するかもしれません。use_rfc2833=1、またはuse_info=1にして改善するかどうか試してみて下さい。

##SIP settings
[sip]
..........
........
#Use SIP INFO to send DTMFs (digits)
use_info=0
#Use RFC2833 (out of band DTMFs) to send digits
use_rfc2833=1

ユーザ登録されない際のトラブルシュート

ユーザ登録の確認は以下コマンドでできますが、registered:no となっている場合には登録できていない状態です。原因はポート設定にあるようです。(デフォルトポート5060が他のサービスで使用中の場合)

sudo linphonecsh generic "proxy list"
****** Proxy 0 *******
sip address: <sip:sip.linphone.org>
route: sip:sip.linphone.org
identity: sip:userXXXX@sip.linphone.org
register: yes
expires: 36000
registered: no --->登録できない状態

linphonercの設定で他のポートを設定します。

sip:sip.linphone.org が使用しているポートは、

- SIP: 5060, 5228
- SIPS: 5061, 5223, 587.

tls の場合は 5061 または 5223tcp の場合は 5060 か 5228 を指定します。

sip_port=0
sip_tcp_port=0
sip_tls_port=5061

ポートの確認コマンドは、

$ sudo linphonecsh generic “ports”

sip port = 5061
audio rtp port = 7078
video rtp port = 9078

ARMBIAN 5.70 stable Debian GNU/Linux 9 (stretch) 4.19.13-sunxi

ドライバ変更に伴いLinphoneの設定ファイルを変更します。下記コマンドでサウンドデバイスを確認します。(ALSAの標準再生・録音ソフトによる)

$ aplay -l

または

$ arecord -l

**** List of PLAYBACK Hardware Devices ****
card 0: Codec [H3 Audio Codec], device 0: CDC PCM Codec-0 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0

上記アップデートによるlinphonercの[sound]内容の変更

[sound]
ringer_dev_id=ALSA: default device
playback_dev_id=ALSA: Codec
capture_dev_id=ALSA: Codec
echocancellation=0
remote_ring=/usr/share/sounds/linphone/ringback.wav
local_ring=/usr/share/sounds/linphone/rings/nokia_tune_2014.wav
playback_gain_db=0.000000
mic_gain_db=1.000000

LinphoneをRaspberry PIなどのコンピュータボードでデーモンとして常駐させ、SSH接続でコンソールから遠隔操作するのであれば、linphone-nogtkではなく linphone-cli を利用します。

ホストマシン:OS
Orangepi PC : Armbian 22.11.4 Bullseye with Linux 5.15.89-sunxi

インストール

$ sudo apt install linphone-cli

:bangbang: Linphoneの各種設定を書出す設定ファイル .linphonerc とユーザ登録に必要なデータベース用ディレクトリ /home/USER/.local/share/linphone を作成します。

$ mkdir -p /home/USER/.local/share/linphone
$ touch .linphonerc

ログファイル出力(オプション)を指定して起動

$ sudo -H -u username linphonecsh init -c /home/USER/linphone/.linphonerc -d 6 -l /tmp/linphone-log.txt

予めLinphoneのホームページで登録したユーザでSIPサーバへログインします。このユーザはデフォルトユーザとしてLinphoneアプリの設定ファイルとデータベースに登録されます。

$ linphonecsh register --host sip.linphone.org --username user_name --password xxxxxxx

SIPサーバ側でユーザ認証されたかどうか確認して下さい。

$ linphonecsh status register
registered, identity=sip:user_name@sip.linphone.org duration=3600

システムデーモンとして登録するためのスクリプトを作成

/etc/init.d/linphonecsh

#!/bin/sh
### BEGIN INIT INFO
# Provides:          linphone
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Starts Linphone daemon.
# Description:       Linphone is used to call and receive message on VoIP System.
### END INIT INFO
sudo -H -u username linphonecsh init -c /home/USER/.linphonerc -d 6 -l /tmp/linphone-log.txt

実行権の付与

$ sudo chmod +x /etc/init.d/linphonecsh

起動時スクリプトの登録

$ sudo update-rc.d linphonecsh defaults

Ubuntu Manpage: update-rc.d - install and remove System-V style init script links


動作チェック

呼出音の設定以外は $ linphonecsh generic " ~ " コマンドで設定。動作中のLinphoneに対して設定を上書きします。

サウンド設定追加

$ linphonecsh generic "soundcard list"
0: ALSA: default
1: ALSA: H3 Audio Codec
2: ALSA: sun9i-hdmi

$ linphonecsh generic "soundcard use 0"
Using sound device ALSA: default

STUNサーバを指定、firewallコマンドで有効化

$ linphonecsh generic "stun stun.linphone.org"
Stun server: stun.linphone.org (disabled - use 'firewall stun' to enable)
$ linphonecsh generic "firewall stun"

firewallコマンド

$ linphonecsh generic "help firewall"
'firewall'        : show current firewall policy.
'firewall none'   : use direct connection.
'firewall nat'    : use nat address given with the 'nat' command.
'firewall stun'   : use stun server given with the 'stun' command.
'firewall ice'    : use ice.
'firewall upnp'   : use uPnP IGD.

ICEを有効化

$ linphonecsh generic "firewall ice"
Using ice with stun server �a to discover firewall address

IPv6有効化の確認

$ linphonecsh generic "ipv6 status"
ipv6 use enabled: true

受信音の設定

受信時の再生音に関してはデフォルトでも未設定のため、Linphone停止後、受信時の再生音のディレクトリとファイル名を以下の[sound]セクションに追加する必要があります。

local_ring=/usr/share/sounds/linphone/toy-mono.wav

.linphonerc

[sound]
remote_ring=/usr/share/sounds/linphone/ringback.wav
local_ring=/usr/share/sounds/linphone/toy-mono.wav
playback_gain_db=0.000000
mic_gain_db=0.000000
ringer_dev_id=ALSA: default
playback_dev_id=ALSA: default
capture_dev_id=ALSA: default