【初心者】YOLOv5を使ってみる #2 (RTMP中継サーバ経由でのリアルタイムでの映像物体検出)


1. 目的

2. やったこと

  • AWS上のYOLOv5サーバの隣に、中継サーバを構築する。
  • PC(OBS Studio) -> RTMP -> 中継サーバ -> HLS -> YOLOv5 の流れで、手元のPCからの映像をYOLOv5にて分析させる。

3. 構成図

4. 実施手順

4.1 中継サーバの構築

[centos@ip-10-0-0-124 ~]$ sudo yum update
[centos@ip-10-0-0-124 ~]$ sudo yum groupinstall "Development Tools"
[centos@ip-10-0-0-124 ~]$ sudo yum install git
[centos@ip-10-0-0-124 ~]$ sudo yum install pcre-devel zlib-devel openssl-devel

・nginx 及び nginx用のrtmpモジュールをインストールする。

[centos@ip-10-0-0-124 ~]$ git clone https://github.com/arut/nginx-rtmp-module.git
[centos@ip-10-0-0-124 ~]$ git clone https://github.com/nginx/nginx.git
[centos@ip-10-0-0-124 ~]$ cd nginx
[centos@ip-10-0-0-124 ~]$ ./auto/configure --add-module=../nginx-rtmp-module
[centos@ip-10-0-0-124 ~]$ make
[centos@ip-10-0-0-124 ~]$ sudo make install
  • nginx.conf を編集し、rtmpの受信、及びHLSの配信を行うように設定する。今回は「[CentOS7.6][nginx][HLS]ライブストリーミングサーバ構築」の記事内のnginx.confをベースとして使わせて頂いた。
  • 同記事内では、"hls_playlist_length"の値が1sだったが、本環境ではそれだと安定しなかったため30sに変更した。
  • 各パラメータの解説は公式のGitHubレポジトリの「Directives」にあるが、内容の深堀りはできていない。
/usr/local/nginx/conf/nginx.conf
#user  nobody;
worker_processes  auto;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
error_log  logs/error.log  info;

#pid        logs/nginx.pid;

events {
    worker_connections  1024;
}

rtmp_auto_push on;
rtmp {
    server {
          listen 1935;
          access_log logs/rtmp_access.log ;
          chunk_size 4096;

          application live1 {
                 live on;
                  wait_video on;
                  hls on;
                  hls_cleanup on;
                  hls_path /usr/local/nginx/html/hls;

                  hls_fragment 500ms;
                  hls_playlist_length 30s;
                  hls_type live;
                  hls_nested on;
          }
    }

}

http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
        listen       80;
        server_name  localhost;

        location /hls {
            types {
                   application/vnd.apple.mpegurl m3u8;
            }
            root   html;
            index  index.html index.htm;
        }

        location /dash {
            types {
                   application/vnd.apple.mpegurl mpd;
            }
            root   html;
            index  index.html index.htm;
        }
    }
}
  • nginx をバックグラウンドで起動する。
sudo /usr/local/nginx/sbin/nginx &

4.2 映像送信(OBS Studio)

  • 上記で構築した中継サーバに向けてrtmpで映像の送信を行う。
  • OBS Studioの「設定」- 「配信」で、配信先を以下のように設定する。
    • サーバー: rtmp://[中継サーバのグローバルIP]:1935/live1
    • ストリームキー: stream
  • 「live1」の値は自由に設定可能だが、nginx.conf の 「application」で設定した値と一致させる必要がある。
  • 「stream」の値は自由に設定可能。この値は後で受信を行う際に必要になる(URLの一部になるため)。

  • OBS Studio から映像を送信すると、中継サーバ内に映像のファイルが生成される。
[root@ip-10-0-0-124 stream]# pwd
/usr/local/nginx/html/hls/stream
[root@ip-10-0-0-124 stream]# ls
0.ts  1.ts  2.ts  3.ts  4.ts  5.ts  6.ts  index.m3u8
  • また、送信完了後にはログも出力される。
[root@ip-10-0-0-124 logs]# pwd
/usr/local/nginx/logs
[root@ip-10-0-0-124 logs]# more rtmp_access.log
x.x.x.x [25/Aug/2021:07:10:50 +0000] PUBLISH "live1" "stream" "" - 66766223 529 "" "FMLE/3.0 (compatible; FMSc/1.0)" (3m 21s)

4.3 映像受信(IE)

  • 中継サーバと同一Subnetに存在するインスタンス(Windows Server 2019)で、HLSで映像を受信する。
  • ブラウザ(IE) で再生できるよう、中継サーバ側にhtmlファイルを用意する。今回は「[CentOS7.6][nginx][HLS]ライブストリーミングサーバ構築」の記事内のhtmlファイルをベースとして使わせて頂いた。
  • 「player.setSrc」のところのIPアドレスは、今回は同一Subnet内でのアクセスになるため、中継サーバの実IP(プライベートIP)を設定する。
/usr/local/nginx/html/play.html
<!DOCTYPE html>
<html>
<head>
 <meta charset="utf-8">
 <title>MediaElement</title>
 <!-- MediaElement style -->
 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/mediaelemen
t/4.2.9/mediaelementplayer.css" />
</head>
<body>
 <!-- MediaElement -->
 <script src="https://cdnjs.cloudflare.com/ajax/libs/mediaelement/4.2.9/mediaele
ment-and-player.js"></script>
 <video id="player" />


</body>
<script type="text/javascript">
     var player = new MediaElementPlayer('player', {
       success: function(mediaElement, originalNode) {
         console.log("Player initialised");
       }
     });
     player.setSrc("http://10.0.0.124/hls/stream/index.m3u8");
</script>
</html>

4.4 映像受信/物体検出(YOLOv5)

  • 中継サーバと同一Subnetに存在するインスタンス(Windows Server 2019)にインストール済のYOLOv5で、中継サーバからHLSで映像を受信し物体検出を行う。
C:\Users\Administrator\yolov5>python detect.py --source "http://10.0.0.124/hls/stream/index.m3u8"
  • リアルタイムではないが、映像を継続的に処理し物体検出を行うことが可能。

4.5 簡易的な遅延の確認

  • OBS Studio では、カメラ(自分の顔)と、デジタル時計を並べて配信する。職場のインターネット(wifi)経由で、AWS東京リージョンの中継サーバへ映像を送信する。
  • 並行して、Windows Server 2019のインスタンスにRDPし、IEで映像を中継サーバ経由でそのまま受信した画面と、YOLOv5で物体検出を行っている画面を並べて表示する。YOLOv5ではきちんと自分の顔が「person」として検知される。
  • 配信しているリアルの時刻が16:41:10、IEでそのまま受信/再生している時刻が16:40:42、YOLOv5が物体検出した結果を表示している時刻が16:40:27となり、IEは約28秒遅れ、YOLOv5は約43秒遅れとなっている。中継サーバをチューニングしたり、YOLOv5のモデルを変えたりしたら速くなるのかもしれない。

5. 所感

  • 手元の映像を使用して物体検出を行うことができた。引き続き様々なトピック(他のモデルの利用など)にチャレンジしてみたい。