はじめに
「WebRTCを利用した複数人でのビデオ通話サンプル(Mesh)」をMojolicious::Liteに移植しました。
環境
TLSサポートにはIO::Socket::SSLが要求されます。
IO::Socket::SSLはNet::SSLeayに依存しています。
Net::SSLeayのインストールには
- DebianとUbuntuでは、libssl-devとzlib1g-dev
- Red Hat Enterprise LinuxとFedoraでは、openssl-develとzlib-devel
が必要になります。
インストール
webrtc_mesh_server.pl
public
+ mesh.html
+ webrtc_mesh.js
Ubuntu
sudo apt install libssl-dev
sudo apt install zlib1g-dev
CentOS(CentOS6.4上でMojolicious+WebSocket+SSL環境構築)
sudo yum install openssl-devel
sudo yum install zlib-devel
IO::Socket::SSLとMojoliciousをインストールします。
cpanm IO::Socket::SSL
cpanm Mojolicious
開発サーバーを起動します。
morbo -l https://*:8443 webrtc_mesh_server.pl
サーバー
webrtc_mesh_server.jsの移植はリアルタイムチャット (Mojolicious::Lite)を参考にしました。
サーバーから3分ごと、クライアントから30秒ごと接続確認をしていましたが、3時間に延命してますのでお兄さん許して。
webrtc_mesh_server.pl
use strict;
use warnings;
use Mojo::JSON 'encode_json';
use Mojolicious::Lite;
# 接続リスト
my @connections = ();
# WebSocket処理
websocket '/' => sub {
my $self = shift;
$self->inactivity_timeout(10800);
my $log = $self->log;
# Receive message
$self->on('json' => sub {
my ($self, $json) = @_;
if ($json->{join}) {
$log->info($self->{tx}->remote_address
. ': join room='
. $json->{join}{room} . ', id='
. $json->{join}{id});
# 同一IDが存在するときは古い方を削除
@connections = grep {
!($_->{room} eq $json->{join}{room} && $_->{id} eq $json->{join}{id})
} @connections;
# 接続情報を保存
push(@connections,
{room => $json->{join}{room}, id => $json->{join}{id}, ws => $self});
foreach my $data (@connections) {
if ( $data->{room} eq $json->{join}{room}
&& $data->{id} ne $json->{join}{id})
{
# 新規参加者を通知
$data->{ws}->send(encode_json({join => $json->{join}{id}}));
}
}
return;
}
# Peerを検索
foreach my $data (@connections) {
if ( $data->{room} eq $json->{room}
&& $data->{id} eq $json->{dest})
{
# メッセージの転送
$data->{ws}->send(encode_json($json));
last;
}
}
});
# Finish
$self->on('finish' => sub {
@connections = grep {
if ($_->{ws} != $self) { 1; }
else {
$log->info($self->{tx}->remote_address
. ': part room='
. $_->{room} . ', id='
. $_->{id});
foreach my $roomData (@connections) {
if ( $_->{room} eq $roomData->{room}
&& $_->{id} ne $roomData->{id})
{
# 退出を通知
$roomData->{ws}->send(encode_json({part => 1, src => $_->{id}}));
}
}
}
} @connections;
});
};
app->start;
クライアント
mesh.htmlとwebrtc_mesh.jsは省略します。
(pc._remoteVideoはstartPeerConnectionだけで参照され、pcのプロパティに追加する必要はないので、ローカル変数として宣言してもよいのでは?と思います)