ライブストリーミングサーバーを構築

スポンサーリンク

Live streaming Serverを構築します。動的コンテンツを自分のブログに掲載したり、スマホで配信するなど色々用途は考えられます。Oracle Linux 8にインストールします。スペックはCPU4つ、メモリ24GBの仮想マシンです。

それでは作業をしていきましょう。
まずはSELinuxを無効にします。これが不要というわけではなく、作業途中で原因不明のエラーに悩まされたことが多々あったからです。
仮想マシンは作成したばかりの状態ですがSELinuxの状態を確認します。

getenforce

どうやら有効なので一時的に無効にします。

setenforce 0

再起動後も無効にしたいときは次のファイルを編集します。

vi /etc/selinux/config

SELINUX=enforcingをSELINUX=disableに変更します。

ここからは、NGINX公式ブログを参考にしてNGINXをソースからインストールします。

Enabling Video Streaming for Remote Learning with NGINX and NGINX Plus - NGINX
During the COVID-19 pandemic, remote learning via video has become the new normal for many educational institutions. Here we show how to set up live video strea...

NGINXをコンパイルする前に、autoconf、gcc、git、makeなどの基本的なビルドツールをインストールする必要があります。

dnf groupinstall "Development Tools"
dnf install git

依存関係をダウンロードしてインストールする簡単な方法は、パッケージマネージャーを使用することです。

dnf groupinstall pcre-devel zlib-devel openssl-devel

Module or Group ‘pcre-devel’ is not available.
Module or Group ‘zlib-devel’ is not available.
Module or Group ‘openssl-devel’ is not available.

記述通りおこなったが、エラーでインストール出来ないので、通常のインストールに変更します。

dnf install pcre-devel zlib-devel openssl-devel

RTMP Module付きでNGINXをコンパイルします。ビルドを完了するには、RTMPとNGINXのGitHubリポジトリのクローンを作成します。

GitHub - arut/nginx-rtmp-module: NGINX-based Media Streaming Server
NGINX-based Media Streaming Server. Contribute to arut/nginx-rtmp-module development by creating an account on GitHub.
cd /tmp
git clone https://github.com/arut/nginx-rtmp-module.git
git clone https://github.com/nginx/nginx.git
cd nginx
./auto/configure --add-module=../nginx-rtmp-module
make
make install

インストール状況を見ると/usr/local/nginxが重要なディレクトリということがわかります。

[root@instance-20220107-1707 nginx]# ./auto/configure –add-module=../nginx-rtmp-module
checking for OS

  • Linux 5.4.17-2136.301.1.3.el8uek.aarch64 aarch64
    checking for C compiler … found
  • using GNU C compiler
  • gcc version: 8.5.0 20210514 (Red Hat 8.5.0-4.0.1) (GCC)
    checking for gcc -pipe switch … found
    checking for -Wl,-E switch … found
    checking for gcc builtin atomic operations … found
    checking for C99 variadic macros … found
    checking for gcc variadic macros … found
    checking for gcc builtin 64 bit byteswap … found
    checking for unistd.h … found
    checking for inttypes.h … found
    checking for limits.h … found
    checking for sys/filio.h … not found
    checking for sys/param.h … found
    checking for sys/mount.h … found
    checking for sys/statvfs.h … found
    checking for crypt.h … found
    checking for Linux specific features
    checking for epoll … found
    checking for EPOLLRDHUP … found
    checking for EPOLLEXCLUSIVE … found
    checking for eventfd() … found
    checking for O_PATH … found
    checking for sendfile() … found
    checking for sendfile64() … found
    checking for sys/prctl.h … found
    checking for prctl(PR_SET_DUMPABLE) … found
    checking for prctl(PR_SET_KEEPCAPS) … found
    checking for capabilities … found
    checking for crypt_r() … found
    checking for sys/vfs.h … found
    checking for nobody group … found
    checking for poll() … found
    checking for /dev/poll … not found
    checking for kqueue … not found
    checking for crypt() … not found
    checking for crypt() in libcrypt … found
    checking for F_READAHEAD … not found
    checking for posix_fadvise() … found
    checking for O_DIRECT … found
    checking for F_NOCACHE … not found
    checking for directio() … not found
    checking for statfs() … found
    checking for statvfs() … found
    checking for dlopen() … not found
    checking for dlopen() in libdl … found
    checking for sched_yield() … found
    checking for sched_setaffinity() … found
    checking for SO_SETFIB … not found
    checking for SO_REUSEPORT … found
    checking for SO_ACCEPTFILTER … not found
    checking for SO_BINDANY … not found
    checking for IP_TRANSPARENT … found
    checking for IP_BINDANY … not found
    checking for IP_BIND_ADDRESS_NO_PORT … found
    checking for IP_RECVDSTADDR … not found
    checking for IP_SENDSRCADDR … not found
    checking for IP_PKTINFO … found
    checking for IPV6_RECVPKTINFO … found
    checking for TCP_DEFER_ACCEPT … found
    checking for TCP_KEEPIDLE … found
    checking for TCP_FASTOPEN … found
    checking for TCP_INFO … found
    checking for accept4() … found
    checking for int size … 4 bytes
    checking for long size … 8 bytes
    checking for long long size … 8 bytes
    checking for void * size … 8 bytes
    checking for uint32_t … found
    checking for uint64_t … found
    checking for sig_atomic_t … found
    checking for sig_atomic_t size … 4 bytes
    checking for socklen_t … found
    checking for in_addr_t … found
    checking for in_port_t … found
    checking for rlim_t … found
    checking for uintptr_t … uintptr_t found
    checking for system byte ordering … little endian
    checking for size_t size … 8 bytes
    checking for off_t size … 8 bytes
    checking for time_t size … 8 bytes
    checking for AF_INET6 … found
    checking for setproctitle() … not found
    checking for pread() … found
    checking for pwrite() … found
    checking for pwritev() … found
    checking for strerrordesc_np() … not found
    checking for sys_nerr … found
    checking for localtime_r() … found
    checking for clock_gettime(CLOCK_MONOTONIC) … found
    checking for posix_memalign() … found
    checking for memalign() … found
    checking for mmap(MAP_ANON|MAP_SHARED) … found
    checking for mmap(“/dev/zero”, MAP_SHARED) … found
    checking for System V shared memory … found
    checking for POSIX semaphores … not found
    checking for POSIX semaphores in libpthread … found
    checking for struct msghdr.msg_control … found
    checking for ioctl(FIONBIO) … found
    checking for ioctl(FIONREAD) … found
    checking for struct tm.tm_gmtoff … found
    checking for struct dirent.d_namlen … not found
    checking for struct dirent.d_type … found
    checking for sysconf(_SC_NPROCESSORS_ONLN) … found
    checking for sysconf(_SC_LEVEL1_DCACHE_LINESIZE) … found
    checking for openat(), fstatat() … found
    checking for getaddrinfo() … found
    configuring additional modules
    adding module in ../nginx-rtmp-module
  • ngx_rtmp_module was configured
    checking for PCRE2 library … found
    checking for OpenSSL library … found
    checking for zlib library … found
    creating objs/Makefile

Configuration summary

  • using system PCRE2 library
  • using system OpenSSL library
  • using system zlib library nginx path prefix: “/usr/local/nginx”
    nginx binary file: “/usr/local/nginx/sbin/nginx”
    nginx modules path: “/usr/local/nginx/modules”
    nginx configuration prefix: “/usr/local/nginx/conf”
    nginx configuration file: “/usr/local/nginx/conf/nginx.conf”
    nginx pid file: “/usr/local/nginx/logs/nginx.pid”
    nginx error log file: “/usr/local/nginx/logs/error.log”
    nginx http access log file: “/usr/local/nginx/logs/access.log”
    nginx http client request body temporary files: “client_body_temp”
    nginx http proxy temporary files: “proxy_temp”
    nginx http fastcgi temporary files: “fastcgi_temp”
    nginx http uwsgi temporary files: “uwsgi_temp”
    nginx http scgi temporary files: “scgi_temp”

ファイアウォールの状態を確認すると有効になっているので停止するか、ポート開放をします。nginxが使用するポートは80にする予定なので追加しておきます。SSLもあとから必要になるかもしれないので追加しておきました。また、oracle cloudのイングレスルールにも記述しておきます。

systemctl status firewalld
firewall-cmd --list-all --zone=public
firewall-cmd --add-port=80/tcp --zone=public --permanent
firewall-cmd --add-port=443/tcp --zone=public --permanent
systemctl restart firewalld

yumやdnfによるインストールと違いnginxのサービスは無いのでコマンド入力で起動します。

/usr/local/nginx/sbin/nginx

一度ブラウザでサンプルページが表示されるか確認します。

停止する時は次のコマンドを入力します。

/usr/local/nginx/sbin/nginx -s quit

次はnginx.confを編集します。とはいえ何を記述すべきかわからなかったので下記のサイトの記述例を使用させていただきました。ソースからインストールするとconfファイルは下記のディレクトリにあります。

[CentOS7.6][nginx][HLS]ライブストリーミングサーバ構築 | 名古屋でシステム開発WEB制作なら | トランソニックソフトウェア

/usr/local/nginx/conf

cd /usr/local/nginx/conf
vi 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 1s;
                  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;
        }
    }
}

ここまででサーバーの設定は完了しました。今度は配信するPCの設定をします。使用するソフトはOBS studioを利用して設定していきます。
OBSの設定をクリックし、配信項目でサーバーとストリームキーを入力するだけです。


入力完了後に配信開始ボタンをクリックします。しかし、接続できないエラーが発生しました。
どうやら、rtmpで使用するポートの開放が必要なようですのでサーバーに戻り、ファイアウォールにポート番号1935の受信を許可します。さらにOracle Cloudのイングレスルールにも記述します。

firewall-cmd --add-port=1935/tcp --zone=public --permanent
systemctl restart firewalld

再度配信します。今度は接続ができました。配信を開始すると下記のディレクトリの下の階層にストリームキーと同じ名前のディレクトリが作成され、数個の.tsファイルとindex.m3u8が作成されています。配信を停止するとディレクトリとファイルは消えるみたいです。

cd /usr/local/nginx/html/hls
ls

この配信の状況をリアルタイムにみれるサンプルのHTMLファイルを作成して動作確認します。

cd /usr/local/nginx/html
vi index.html

[記述内容]

<!DOCTYPE html>
<html>
<head>
 <meta charset="utf-8">
 <title>MediaElement</title>
 <!-- MediaElement style -->
 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/mediaelement/5.0.4/mediaelementplayer.css" />
</head>
<body>
 <!-- MediaElement -->
 <script src="https://cdnjs.cloudflare.com/ajax/libs/mediaelement/5.0.4/mediaelement-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://129.213.138.187/hls/test/index.m3u8");
</script>
</html>

記述にあるクラウドフレアのURLはCDNというらしく便利なものです。詳しいことはわかりません。

mediaelement - Libraries - cdnjs - The #1 free and open source CDN built to make life easier for developers
HTML5 audio and video players in pure HTML and CSS. MediaElementPlayer.js uses the same HTML/CSS for all players. - Simple. Fast. Reliable. Content delivery at ...

スマホにもOBS mobileというアプリがあったので同じようにサーバーとストリームキーを入力すると配信できました。

ただし、このままでは誰でも配信可能なので制限をかけることもできます。

方法1
nginx.confに次の記述を追加する。IPアドレスが222.222.222.222のみ許可。

allow 222.222.222.222;
deny all;

方法2
Oracle cloudのイングレスルールで特定のIPアドレスからのみ許可する。

方法3
nginx.confでrtmpの設定にあるlive1をわかりにくい文字列にする。

タイトルとURLをコピーしました