ラズパイ4BとUSBカメラでマイク音声も載せてFFmpegによるH264エンコードRTMPライブストリーミング(備忘録)

Raspberry Pi 4B とUSBカメラを使って、Ubuntu FFmpeg によるH264エンコードでマイク音声も載せてRTMPストリーミングする実験(備忘録) Raspberry Pi (ラズパイ)

久々の投稿です。
今回も Raspberry Pi 4 model B(ラズパイ4B) と USBカメラ を使った実験ですが、今回は初めて動画圧縮方式のH264エンコードを使ってライブ配信(ストリーミング)することに挑戦してみました。しかも、USBカメラ内蔵のマイクロフォンの音声も載せることができました。
FFmpegというソフトウェアを使いました。

スポンサーリンク

今までこのブログでは、動画ストリーミングについてはMotion JPEG over HTTP(MJPEG over HTTP) を使っていましたが、今回は初めてH264エンコードを扱ってみました。
FFmpegというフリーソフトウェアでH264エンコードするわけですが、オーディオも圧縮エンコードできるということを知り、せっかくマイク内蔵のUSBカメラを使うならマイク音声もエンコードしてみようと思ったわけです。

ところで、ラズパイ4Bには動画用のハードウェアアクセラレータがあって、H264のハードウェアエンコードができますが、なぜかRTMP方式ストリーミングではH264ソフトウェアエンコードしかできませんでした。
また、本来はブラウザで視聴したかったのですが、RTMP方式はブラウザではできなかったので、VLCプレーヤーを使うことになりました。

なお、RTMP方式とは別にHLS方式というのもあって、これ、実は既に実験済みで、H264ハードウェアエンコードもできて、ブラウザで視聴することもできましたが、それについては後日アップする記事で紹介したいと思います。

また、今回のWebサーバーはレンタルサーバー界隈でよく使われているNGINXを初めて使ってみました。いつか使ってみたいとは思っていたので、今回は良い機会でした。
環境設定方法が謎だらけでかなり戸惑いましたが、しばらく試行錯誤しているうちに勘所が段々わかってきました。

では、今回はRTMP方式に絞って、LAN(ローカルエリアネットワーク)内に限って自分の行った実験を紹介しようと思います。
因みに私はLinuxもラズパイもFFmpegもNGINXもH264も、全てド素人です。
このブログはあくまで個人の趣味の備忘録ですので、勘違いや誤りがあると思います。
もしお気づきの点があればコメント投稿でご連絡いただけると助かります。

    【目次】

  1. 今回の環境
  2. FFmpegについて
  3. RTMP方式とは
  4. NGINXのインストール
  5. VLC media playerのインストール
  6. FFmpeg本体をインストール
  7. RTMPライブ配信(ストリーミング)動作テスト
  8. FFmpeg コマンドオプションについて
  9. 音ズレ対策
  10. トラブルシューティング
  11. まとめ

1.今回の環境

使ったもの

今回使ったものは、下図の様に前回記事と同じ組み合わせです。
ラズパイ4BはSDカードを使わず、USB-SSDブートにしています。

(図01)

今回使ったものの写真

今回使ったものの写真

Raspberry Pi 4 model B

2020年頃にRSオンラインで購入した、OKdo製のRaspberry Pi 4 Model B 4GBの全部入りセットを使っています。

USB-SSD

BUFFALO (バッファロー)
【名称】 SSD 外付け 250GB 超小型 コンパクト ポータブル PS5/PS4対応(メーカー動作確認済) USB3.2Gen1 ブラック
【型式】 SSD-PUT250U3-B/N

USBカメラ

Logicool製 C920n

USB3.0ハブ

エレコム U3H-T410SBK

パソコン環境

Windows 10
Visual Studio Code/ SSHリモート使用
VLCプレーヤー

Raspberry Pi 4 model B のシステム環境

ブートローダバージョン

ラズパイ4BのEEPROMのブートローダのバージョンは以下です。
2022年1月からアップデートしていませんが、defaultバージョンがアップデートされていないのでそのままです。

$ sudo rpi-eeprom-update
BOOTLOADER: up to date
CURRENT: 2022年  1月 25日 火曜日 14:30:41 UTC (1643121041)
LATEST: 2022年  1月 25日 火曜日 14:30:41 UTC (1643121041)
RELEASE: default (/lib/firmware/raspberrypi/bootloader/default)
Use raspi-config to change the release.VL805_FW: Dedicated VL805 EEPROM
VL805: up to date
CURRENT: 000138a1
LATEST: 000138a1

OSバージョン(今回は Ubuntu Desktop)

今までUbuntu Serverを使っていましたが、Python-OpenCVでimshow関数が使えなかったので、結局はUbuntu Desktopを使うことにしました。
Ubuntu Serverに比べてメモリを多く消費するのは仕方ないところです。

~$ cat /etc/os-release
PRETTY_NAME="Ubuntu 22.04.3 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.3 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy

カーネルバージョン

ラズパイ4Bのカーネルのバージョンは以下です。

~$ cat /proc/version
Linux version 5.15.0-1043-raspi (buildd@bos01-arm64-028) (gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0, GNU ld (GNU Binutils for Ubuntu) 2.38) #46-Ubuntu SMP PREEMPT Mon Nov 13 15:08:58 UTC 2023

NGINXバージョン

今回使ったサーバー用ソフトウェアはNGINXです。
バージョンは以下です。

~$ nginx -V
nginx version: nginx/1.18.0 (Ubuntu)
built with OpenSSL 3.0.2 15 Mar 2022
TLS SNI support enabled

FFmpegバージョン

今回使用したFFmpegのバージョンは以下です。

~$ ffmpeg -version
ffmpeg version 4.4.2-0ubuntu0.22.04.1+esm3 Copyright (c) 2000-2021 the FFmpeg developers
built with gcc 11 (Ubuntu 11.4.0-1ubuntu1~22.04)

使用したネットワーク環境

今回は、ローカルエリアネットワークのみの実験です。
ラズパイ4Bとルーターは有線LANで接続し、スマホとルーターとはWi-Fiで接続しています。

2.FFmpegについて

FFmpegについてはこの記事を書く前まで全く知らなかったんです。
これはかなりメジャーなフリーソフトウェアで、WindowsでもMacでもAndroidでも使えて、多くの動画(ビデオ)系アプリケーションで使われているらしいです。
コマンドラインで動作させて、豊富なコーデックに対応していて、動画圧縮エンコードおよびデコードの他に、サウンド(音)の圧縮エンコードおよびデコードもできるんです。
そして、驚いたのは、Webカメラを接続すればライブ配信もできて、それがFFmpegだけでほぼ完結できてしまうという優れものだったんです。

【参考サイト】
https://ja.wikipedia.org/wiki/FFmpeg

ラズパイに接続したWebカメラで映像とマイク音をライブ配信(ストリーミング)する場合、一から自作でプログラミングするのはかなり難しいです。いろいろネットで調べてみましたが、結果的にFFmpegを使う事が最善の選択みたいでした。

3.RTMP方式とは

ネットで検索すると、FFmpegを使った動画ストリーミング配信はRTMP(Real Time Messaging Protocol)という方式が多くヒットすると思います。

私が試したところ、確かにRTMP方式が一番手っ取り早くWebカメラライブストリーミングを実現できました。

RTMP方式は、もともとAdobeのFlashプレーヤーとサーバー間でストリーミングするプロトコルですが、Flashプレーヤーは2020年12月でAdobeがサポート終了したようです。
また、視聴する側はVLCプレーヤーなどのソフトウェアを使う必要があり、ブラウザでは残念ながら視聴できませんでした。

先にも少し述べましたが、ブラウザで視聴するならばHLS方式などの別の方式を使います。
HLS方式については既に実験済みですが、それについては後日記事で紹介したいと思います。

4.NGINXのインストール

まずは、ラズパイOSにサーバー用ソフトウェアをインストールしなければなりません。
今回使ったサーバー用ソフトウェアは、NGINXというものを初めて扱ってみました。
NGINXは、オープンソースのフリーソフトウェアで、有料版はNGINX Plusだそうです。
これらは多くのレンタルサーバーでも使われているそうですね。

前回までの記事では、WebサーバーはPythonのBottleを使って簡易的に自作プログラミングしていましたが、NGINXはこのブログで使用しているレンタルサーバーでも使われていて、いつか試して動作を理解してみたいと思っていたので、今回はいい機会でした。

ここではネット上に多くある情報のとおり、HTTPではなく、まずはRTMP方式で試すために、nginx本体だけでなく、 libnginx-mod-rtmp というモジュールもインストールしますが、いくつか注意点がありました。

04-01. 必ず同時にNGINX本体とRTMPモジュールをインストールすべし

HTTPだけを使うNGINXサーバーだけならば、nginx本体をインストールするだけでOKですが、今回はRTMPモジュールもインストールします。
ただし、これは同時にインストールしないとうまく動いてくれないので注意です。
というわけで、以下のコマンドでインストールします。

sudo apt install nginx libnginx-mod-rtmp

因みに、libnginx-mod-rtmp とは、NGINX用の RTMP サポートパッケージとのことです。
これを後で別途インストールしてもRTMPモジュールが読み込まれないために必ず同時にインストールすることです。自分はこれに気付かず、かなり長い間ドロ沼にハマりました。

インストール後は自動的にNGINXサーバーが起動状態になりますが、手動で起動する場合は、以下のコマンドです。

sudo systemctl start nginx

また、事前にラズパイ4Bのファイアウォールでポートを開放しておきます。
まずは最低限としてポート80は開放しておきます。(RTMPを使う場合は1935ポートも開放しますが、後で説明します。)
Ubuntuならば、以下のコマンドです。

sudo ufw allow 80/tcp

そして、ufwを再起動します。

sudo ufw reload

そうしたら、ローカルエリアネットワーク上のパソコンやスマホのブラウザを起動し、URL入力欄に自分のラズパイ4BのローカルIPアドレスを入力します。
例として以下のように入力します。

http://192.168.0.10

このIPアドレスは、ルーターによって割り当てられた自分のラズパイ4BのIPアドレスです。
そして、ブラウザで以下のように表示されればOK。

(図04-01)

デフォルトのNGINXサーバーにブラウザからアクセスした様子

デフォルトのNGINXサーバーにブラウザからアクセスした様子

これでまずはNGINXの動作確認ができました。

なお、このHTMLソースはどこの場所のものを開いているのかというと、ルート配下の以下のアドレスです。

/var/www/html/index.nginx-debian.html

これの設定用ファイルは以下にあります。

/etc/nginx/sites-available/default

このdefault ファイルに記述してあるものを書き換えて/var/www/html以外の自分のユーザーフォルダに指定はできますが、ユーザーフォルダは外部からアクセスする時、アクセス制限がかかっていて、解除設定にするのは面倒です。
よって、結局はdefaultファイルを変更せず、/var/www/htmlフォルダ配下にsudo権限でHTMLファイルを作る方が楽だという結論に至りました。
環境設定については後で述べます。

04-02. NGINXサーバーの起動、停止、再起動コマンドについて

NGINXの環境設定を変えた場合など、NGINXを再起動する必要が出て来ます。
そのコマンドを紹介します。

状態確認

現在のnginxサーバーの状態を確認するには、以下のコマンドです。

systemctl status nginx

実行すると、以下のような感じになります。

~$ systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2023-11-20 18:58:04 JST; 10min ago
Docs: man:nginx(8)
-----------(以下略)----------------------

Active項目がactiveになっていれば、nginxサーバーが起動しているということです。

手動でサーバー起動

NGINXサーバーはデフォルト状態では自動起動になっていますが、手動で起動するには以下のコマンドです。

sudo systemctl start nginx

サーバー停止

NGINXサーバーを停止するには以下のコマンドです。

sudo systemctl stop nginx

サーバー自動起動を解除

ラズパイ4Bを起動すると、NGINXサーバーはデフォルト状態では自動起動になっています。
すると、セキュリティ的に都合が悪い場合や、別のサーバーを起動する可能性がある場合は、手動起動に切り替えたい場合があると思います。
自分の場合は手動起動にしたかったので、自動起動を解除しました。
そのコマンドは以下です。

sudo systemctl disable nginx

このコマンド後、次にラズパイを再起動したときにはサーバーは停止状態になっています。
サーバーを起動したい場合は、都度以下のコマンドを打てば良いです。

sudo systemctl start nginx

サーバー自動起動を有効

NGINXサーバーの自動起動を有効設定にするには、以下のコマンドです。

sudo systemctl enable nginx

サーバー再起動

NGINXの環境設定ファイルを変更した場合、以下のコマンドでNGINXサーバーを再起動します。

sudo systemctl restart nginx

そうすれば、環境設定ファイルが有効になります。

04-03. 一般的な環境設定について

NGINXにはいろんな環境設定用confファイルがあり、ネット上には色んな情報があって、どのファイルを修正するのが適切なのかイマイチよくわからないんですよね。
初めてNGINXを使った時は、ネットで取得した情報を鵜呑みにして環境設定していましたが、しばらく使っていると、原因不明のトラブルでNGINXを再インストールすることもしばしばありました。

そこで、以下のサイトを参考にさせていただき、環境設定ファイルについてやっと少し理解するに至りました。

【参考サイト】
https://yoshinorin.net/articles/2018/04/01/nginx-virtualhost-usingby-sitesavailable/

また、Debian系の以下の公式ドキュメントも参考にしました。

【参考サイト】
https://wiki.debian.org/Nginx/DirectoryStructure

ただ、自分はあくまでNGINXについてド素人なので、誤り等ありましたらコメント投稿でお知らせください。

環境設定ファイルおよびフォルダ群について

NGINX環境設定には以下のファイルおよびフォルダ群があります。
今後、個人設定を増やしたり、バーチャルサイトを増やしたりする場合、適切に使うようにしたいです。

/etc/nginx/nginx.conf

/etc/nginx/nginx.conf というファイルは、NGINXサーバーの全体の設定です。
ネット上ある多くの情報では、このnginx.confを修正する記述がありますが、基本的にこのファイルは修正しない方が良いようです。
自分自身も最初はこのファイルに追記したり修正したりしましたが、いろいろ実験していると、このファイルを修正する必要はなく、自分用の設定ファイルは別ファイルに記述した方が良いということに気付きました。

このファイルを開いて見ると、最後の行に以下の記述があります。

include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;

これからわかるように、nginx.confファイルを修正せずとも、必ず /etc/nginx/conf.d/*.conf や、/etc/nginx/sites-enabled/* にある設定ファイルを読み込むので、そこに記述した方が良いということです。

/etc/nginx/conf.d/*.conf

/etc/nginx/conf.d/*.conf というファイルは、/etc/nginx/nginx.conf ファイル中のhttpディレクティブ内のうち、自分用の設定を追記したい場合は、ここに新たなファイルを作成します。
すると、httpでアクセスする場合、NGINXサーバー全体の設定が上書き反映されます。
ただし、RTMP用の設定はここに記述しない方が良いです。なぜなら、HTTPとRTMPはプロトコルが異なるので、httpディレクディブの外側に置かなければなりません。それについては後で述べます。

/etc/nginx/sites-available/*

/etc/nginx/sites-available/ フォルダ内には、追加の仮想ホスト構成ファイルを記述したファイルを置きます。
つまりは、ドメインを複数持ちたい場合、ここに各ドメイン用の設定ファイルを置きます。
ファイル名は拡張子無しの好きな名前でOKです。
初期状態ではdefaultというファイルがあるので、それをコピーして修正すれば良いです。
ただし、ここに設定ファイルを作成しただけでは反映されません。
/etc/nginx/sites-enabled にシンボリックリンク(Windowsで言えばショートカットファイル)を作成すれば反映されます。

/etc/nginx/sites-enabled/*

/etc/nginx/sites-enabled/ というフォルダ内には、/etc/nginx/sites-available/に作成した各ドメイン設定ファイルのシンボリックリンク(Windowsで言えばショートカットファイル)を置きます。

なぜ、こんな面倒くさいことするのかというと、複数ドメインを作成して、複数の設定ファイルを作った場合、後で不要になったものは、設定ファイルを削除せずともシンボリックリンクを削除すれば済むわけで、いろいろこねくり回した設定ファイルを削除する必要がありません。あとで再びその設定ファイルを使う場合もありますからね。
特に私みたいにNGINXを初めて使って設定ファイルをいろいろ試したい場合は利点が多いです。
それにレンタルサーバーなど、多くのドメインを管理するならば、このようにした方が手っ取り早いですし、万が一、間違えて削除しても、シンボリックリンクだけなら直ぐに復旧可能ですね。

シンボリックリンクを削除するには、removeではなく、unlinkコマンドを使う事です。

sudo unlink /etc/nginx/sites-enabled/xxxxx

04-04. RTMP用のNGINX環境設定

RTMP用のNGINXの環境設定は、nginx.confファイルを修正せず、別ファイルで設定すれば、削除しても復旧は簡単です。

ただし、ネット上の殆どの情報では、nginx.confファイルにRTMP用の設定を追記するものばかりです。
例えば、以下の様にnginx.confファイルにRTMPディレクティブを最後に追記するような感じです。

user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
    worker_connections 768;
}

http {
---中省略----
}

rtmp {
    server {
        listen 1935;
        application app {
            live on;
        }
    }
}

確かにこれでも問題無く動きますが、先にも少し述べたように、nginx.conf ファイルは書き換えないでデフォルト状態のままの方が得策です。

ならば、別ファイルにするにはどうすれば良いのでしょうか?

RTMPモジュールのこちらのサイトに書いてあるように、nginx.confの中身をよく見てみると、httpディレクティブとrtmpディレクティブは同じ階層にあります。
つまり、別ファイルにするにはincludeで明記する必要があるわけです。
そこで、デフォルトのnginx.confファイルの最初の方の行を見てみると、以下のinclude文がありますね。

include /etc/nginx/modules-enabled/*.conf;

ならば、そこに自分用のRTMP設定ファイルを置けばいいのではないかと気付きました。
ただ、それについてネットの情報が見当たらなかったので、自己流の解釈で紹介したいと思います。

先にNGINXの環境設定で紹介したように、フォルダの名前に「enabled」が付くものはシンボリックリンクを置くフォルダのようです。現に、デフォルトで/etc/nginx/modules-enabled/フォルダ内に存在しているファイルはシンボリックリンクしかありません。
VSCode(Visual Studio Code)のエクスプローラー画面で見てみると、以下の様なマークになっていて、シンボリックリンクであることが分かると思います。

(図04-04-01)

Visual Studio Code(VSCode)のエクスプローラーにシンボリックリンクマークが表示されている

Visual Studio Code(VSCode)のエクスプローラーにシンボリックリンクマークが表示されている

また、ターミナルコマンドで見てみると、以下のようにシンボリックリンクしかないのが分かります。

/etc/nginx/modules-enabled$ ls -l
合計 8
lrwxrwxrwx 1 root root 55 11月 22 22:50 50-mod-http-geoip2.conf -> /usr/share/nginx/modules-available/mod-http-geoip2.conf
lrwxrwxrwx 1 root root 61 11月 22 22:50 50-mod-http-image-filter.conf -> /usr/share/nginx/modules-available/mod-http-image-filter.conf
lrwxrwxrwx 1 root root 60 11月 22 22:50 50-mod-http-xslt-filter.conf -> /usr/share/nginx/modules-available/mod-http-xslt-filter.conf
lrwxrwxrwx 1 root root 48 11月 22 22:50 50-mod-mail.conf -> /usr/share/nginx/modules-available/mod-mail.conf
lrwxrwxrwx 1 root root 48 11月 22 22:50 50-mod-rtmp.conf -> /usr/share/nginx/modules-available/mod-rtmp.conf
lrwxrwxrwx 1 root root 50 11月 22 22:50 50-mod-stream.conf -> /usr/share/nginx/modules-available/mod-stream.conf
lrwxrwxrwx 1 root root 57 11月 22 22:50 70-mod-stream-geoip2.conf -> /usr/share/nginx/modules-available/mod-stream-geoip2.conf

よって、/etc/nginx/modules-available に自分用のRTMP環境設定ファイルを置いて、/etc/nginx/modules-enabled/にシンボリックリンクを作ればよいわけです。
そうすれば、RTMP設定を読み込んでくれますし、不要になったらシンボリックリンクを削除するだけで、後でまた必要になったらシンボリックリンクを簡単に追加できます。

ということで、とりあえず、ファイル名をmy_rtmp.confとして、以下のコマンドでRTMP設定ファイルを新たに作成します。

sudo vi /etc/nginx/modules-available/my_rtmp.conf

そして、以下のテキストを入力して保存します。

rtmp {
    server {
        listen 1935;
        application stream {
            live on;
        }
    }
}

application stream のところの「stream」という名前は自分の好きな名前でよく、後にVLCプレーヤーで視聴する時に入力するURLの名前と一致させる必要があります。

次に、 /etc/nginx/modules-enabled/ 配下にシンボリックリンクを作成します。
ここで、ファイル名が要注意です。
シンボリックリンクを読み込む順番があって、かならずRTMPモジュールを読み込んでから、このRTMP設定を読み込むようにしないと、エラーが出て動かないという症状に悩むことになります。
RTMPモジュールのファイル名は、50-mod-rtmp.conf ですが、最初に50という数値となっていることから、それよりも後にしなければなりません。
頭文字がアルファベットならば数値より後で読み込むと思います。そして、拡張子は必ず .conf にします。

ということで、RTMP用設定シンボリックリンクのファイル名はここでは自分用に my_rtmp.conf として、以下のコマンドで作成します。

sudo ln -s /etc/nginx/modules-available/my_rtmp.conf /etc/nginx/modules-enabled/my_rtmp.conf

これで、以下のコマンドでnginxを再起動すれば、RTMP用のNGINX設定は完了です。

sudo systemctl start nginx

1935ポートを開放しておく

次に、忘れがちなのは、Ubuntuのファイアウォールufwを使っている場合、以下のコマンドでポート1935を開放しておくことです。

sudo ufw allow 1935/tcp

そして、ufwを再起動します。

sudo ufw reload

04-05. NGINXの完全削除(アンインストール)

自分の場合、NGINXの設定がゴチャゴチャになってしまい、一旦NGINXを削除して再インストールしたいことがありました。
ただし、通常削除の以下のコマンドでは完全に削除できませんでした。

sudo apt remove nginx

実は、このコマンドでは環境設定が残ってしまうのです。
そこで、以下のサイトを参考にさせていただきました。

【参考サイト】
https://blog.junpeko.com/ubuntu-nginx-uninstall

環境設定も含めてNGINXを完全削除する場合は、以下のコマンドです。

~$ sudo apt purge nginx nginx-common nginx-full

これにより、/etc/nginxフォルダのnginx.confファイルも全て削除されます。
ただ、/var/www内に新たに自分用のファイルを作成している場合は削除されません。

これで再インストールすれば、NGINXをデフォルト状態に戻すことができます。

5.VLC media playerのインストール

RTMP方式でストリーミング視聴するためには、VLC media player が必要です。
VLCプレーヤーって今回初めて知ったのですが、Linux系では標準のプレーヤーだったんですね。知らなかった…。
そんでもって、かなり多くのコンテナやコーデックに対応していてビビりました。
WindowsやMac、Linux、Androidなどに対応しているという優れものです。

インストールについて詳細は割愛しますが、以下のサイトからダウンロードして簡単にインストールできます。

https://www.videolan.org/vlc/index.ja.html

6.FFmpeg本体をインストール

では、まずはFFmpegというソフトウェアをインストールします。
Ubuntu の場合、以下のコマンドでインストールできます。

sudo apt install ffmpeg

たったこれだけです。

7.RTMPライブ配信(ストリーミング)動作テスト

では、いよいよFFmpegがちゃんと動いて、ライブストリーミングができるかテストしてみます。

07-01. USBカメラのマイクロフォンのサウンドカードIDとデバイスIDを調べる

まず、ラズパイ4BにUSBカメラを接続し、USBハブの電源を入れてからラズパイ4Bを起動します。
そのUSBカメラ付属のマイクロフォンのサウンドカードIDとデバイスIDを調べます。
以下のコマンドを打ちます。

arecord -l

すると、以下のように表示されました。

$ arecord -l
**** ハードウェアデバイス CAPTURE のリスト ****
カード 2: C920 [HD Pro Webcam C920], デバイス 0: USB Audio [USB Audio]
サブデバイス: 1/1
サブデバイス #0: subdevice #0

カード 2 がサウンドカードIDです。
デバイス 0 がデバイスIDです。

このカード番号は環境によって違いがあり、ラズパイ4B初期状態のカード番号は多分1番だと思われます。

このカード番号というものがクセ者で、ラズパイを起動する毎に番号が変わってしまうことがあります。
実は、alsa.confファイルを修正することで番号を固定にできますが、これについては後で詳しく述べます。

07-02. とりあえずのFFmpegコマンド実行

では、何はともあれまずはラズパイ4BとUSBカメラでライブストリーミング配信をテストしてみます。
先ほど紹介したUSBカメラマイクロフォンのサウンドカードID=2、デバイスID=0とし、ラズパイ4BのローカルIDアドレスが 192.168.0.10 の場合とすると、以下のFFmpegコマンドを入力してみます。

ffmpeg -f v4l2 -input_format mjpeg -s 640x480 -thread_queue_size 8192 -i /dev/video0 \
-f alsa -thread_queue_size 8192 -i hw:2,0 \
-c:v libx264 -pix_fmt yuv420p \
-c:a aac -ac 2 -ar 48k \
-f flv rtmp://192.168.0.10:1935/stream

最後の行のURL rtmp://192.168.0.10:1935/stream の「stream」という名前は、先ほどRTMP方式用のNGINX環境設定で紹介したように、自分用の設定ファイル my_rtmp.conf に記述した application の名前です。

そして、FFmpegのソフトウェアエンコーダ libx264 を使いました。
ただ、先でも述べたようにラズパイ4Bにはビデオ用のハードウェアアクセラレータがあって、H264ハードウェアエンコーダが使えるのですが、RTMPでは使えず、HLS方式でしか使えませんでした。よって、今回はソフトウェアエンコードで我慢します。

hw:2,0 というところは、
hw:サウンドカードID,デバイスID という意味です。

その他のコマンドの詳しい意味は後で述べます。とりあえず、ここでは動作チェックです。

このコマンドで走らせたら、次はパソコンのVLC media playerを起動します。

07-03. VLC media playerでRTMPストリーミング視聴する

では、ラズパイ4Bでストリーミングサーバーを走らせたので、VLCプレーヤーでアクセスして視聴してみます。

パソコンのVLC media playerを起動し、下図の様に「メディア」をクリックします。

(図07-02-01)

VLCプレーヤーを起動しメディアをクリック

VLCプレーヤーを起動しメディアをクリック

次に、下図の様に「ネットワークストリームを開く」をクリックします。

(図07-02-02)

VLCプレーヤーのネットワークストリームを開くをクリック

VLCプレーヤーのネットワークストリームを開くをクリック

次に、下図の様に「ネットワーク」タブを選択し、URL入力欄に

rtmp://192.168.0.10:1935/stream

と入力します。この stream という名前は先ほどRTMP用のNGINX環境設定のところで紹介した、/etc/nginx/modules-available/my_rtmp.confapplication名と一致する必要があります。

そして、下図の様に「再生」をクリックします。

(図07-02-03)

VLCのネットワーク欄にRTMP用のURLを入力して再生

VLCのネットワーク欄にRTMP用のURLを入力して再生

すると、数秒後にストリーミング開始されると思います。
RTMPは意外と遅延が少なく、フレームレートも高くてなかなか良い感じですよね。
ただ、RTMPはブラウザで再生できないのが個人的にはネックです。

8.FFmpeg コマンドオプションについて

それでは、FFmpegのコマンドオプション設定について紐解いてみます。
先に紹介したRTMP用のコマンドをもう一度見てみましょう。

ffmpeg -f v4l2 -input_format mjpeg -s 640x480 -thread_queue_size 8192 -i /dev/video0 \
-f alsa -thread_queue_size 8192 -i hw:2,0 \
-c:v libx264 -pix_fmt yuv420p \
-c:a aac -ac 2 -ar 48k \
-f flv rtmp://192.168.0.10:1935/stream

これを分解していくと以下のようになります。

(図08-01)

FFmpeg コマンドの入力および出力を分けて可視化

FFmpeg コマンドの入力および出力を分けて可視化

‘¥’という文字はバックスラッシュ’\’と同じで、改行してもコマンドは繋がっていることを意味しています。バックスラッシュで繋げれば、入力と出力でブロックとしてコマンドを分けて見やすくなりますね。
緑色が入力、紫色が出力コマンドです。

08-01. 映像入力が先か、オーディオ入力が先かによって出力結果が変わる

入力には、映像とオーディオの入力を続けて入力指定すれば、FFmpegで合成してくれます。
ただし、入力コマンドの指定について、映像が先か、オーディオが先かによって結果が異なるという謎動作があります。

ます、先に紹介したのは、映像コマンドが先で、オーディオコマンドが後で、出力した動画は音声と映像がピッタリ合って音ズレはありませんでした。

しかし、オーディオコマンドを先、映像コマンドを後にした以下のコード、

ffmpeg -f alsa -thread_queue_size 8192 -i hw:2,0 \
-f v4l2 -input_format mjpeg -s 640x480 -thread_queue_size 8192 -i /dev/video0 \
-c:v libx264 -pix_fmt yuv420p \
-c:a aac -ac 2 -ar 48k \
-f flv rtmp://192.168.0.10:1935/stream

この場合は、何故か音声が0.5秒ほど遅れました。これはほんと謎です。

08-02. 各コマンドオプションについて

では、上記のコマンドオプションについて自分なりに解釈したものを紹介します。

-f

入力や出力のフォーマットを、自動ではなく、明示的に指定することを意味します。

v4l2

v4l2 とは、Video for Linux 2 の略で、LinuxにおけるUSBカメラのデバイスドライバです。
それを -f オプションで明示的に指定します。

alsa

LinuxにはALSAという音声の入出力を扱うソフトウェアがあるそうです。
Advanced Linux Sound Architectureの略で、Linuxにおける高機能なサウンドシステムを提供するためのソフトウェア群とのこと。要するにデバイスドライバです。
これを -f オプションで明示的に指定するということです。

-input_format

カメラデバイスの入力フォーマットを指定します。ただ、後で紹介する -pix_fmt と混同しない様に注意です。自分は最初は勘違いしていて混同していました。

今回使用した C920n の使用可能なフォーマットは、以下のコマンドで調べられます。

ffprobe -hide_banner -f v4l2 -list_formats all -i /dev/video0

すると、以下のようになります。

~$ ffprobe -hide_banner -f v4l2 -list_formats all -i /dev/video0
[video4linux2,v4l2 @ 0xaaab032a2850] Raw       :     yuyv422 :           YUYV 4:2:2 : 640x480 160x90 160x120 176x144 320x180 320x240 352x288 432x240 640x360 800x448 800x600 864x480 960x720 1024x576 1280x720 1600x896 1920x1080 2560x1472
[video4linux2,v4l2 @ 0xaaab032a2850] Compressed:       mjpeg :          Motion-JPEG : 640x480 160x90 160x120 176x144 320x180 320x240 352x288 432x240 640x360 800x448 800x600 864x480 960x720 1024x576 1280x720 1600x896 1920x1080
/dev/video0: Immediate exit requested

以前に投稿したこちらの記事により、 USBカメラデバイスからの入力は、 yuyv422 よりも mjpeg の方が高速だということはわかっているので、今回も mjpeg を使います。
よって、

-input_format mjpeg

とします。

-s

入力に指定した場合、入力画像サイズを指定します。
これは、先ほど input_formatオプションのところでも紹介したように、以下のコマンドで対応可能な画角サイズを指定します。

ffprobe -hide_banner -f v4l2 -list_formats all -i /dev/video0

今回のUSBカメラ C920n の場合、デフォルトの画角が640x480なので、とりあえずそれを指定しておきます。
数値の間の’x’は英文字の小文字のエックスです。

-s 640x480

出力側に指定した場合は拡大縮小処理が施されます。

-thread_queue_size

このオプションは、とりあえず、-thread_queue_size 8192 くらいのサイズにしておきます。

これを映像入力側に指定しないと、私の環境の場合、VLCを初回に起動したときに映像が再生されませんでした。

また、オーディオ入力側に指定しないと、音声がまともに再生されませんでした。

よって、-thread_queue_size 8192 を映像とオーディオの両方の入力に指定します。
キャッシュ?というのかよくわかりませんが、デバイスから読み込む時にバッファに貯め込むパケットサイズらしいです。

-i

-i オプションは、入力デバイスを指定します。

映像入力ならば、v4l2-ctl --list-devices コマンドで事前に確認しておきます。

~$ v4l2-ctl --list-devices
bcm2835-codec-decode (platform:bcm2835-codec):
/dev/video10
/dev/video11
/dev/video12
/dev/video18
/dev/video31
/dev/media2bcm2835-isp (platform:bcm2835-isp):
/dev/video13
/dev/video14
/dev/video15
/dev/video16
/dev/video20
/dev/video21
/dev/video22
/dev/video23
/dev/media0
/dev/media1HD Pro Webcam C920 (usb-0000:01:00.0-1.1.2):
/dev/video0
/dev/video1
/dev/media3

このように、今回使うUSBカメラ C920n の場合は、 /dev/video0/dev/video1 があるので、/dev/video0 を指定します。video1では認識されませんでした。

オーディオ入力のマイクロフォンの場合は、後でも紹介しますが、 arecord -l コマンドで確認します。

~$ arecord -l
**** ハードウェアデバイス CAPTURE のリスト ****
カード 2: C920 [HD Pro Webcam C920], デバイス 0: USB Audio [USB Audio]
サブデバイス: 1/1
サブデバイス #0: subdevice #0

オーディオデバイスの hw というものは、

hw:カード番号,デバイス番号

という意味なので、この場合は hw:2,0 と指定します。

-c:v

出力側のビデオ(映像)コーデックを指定します。

対応可能なコーデックの一覧を表示するには、以下のコマンドです。

ffmpeg -codecs
~$ ffmpeg -codecs
ffmpeg version 4.4.2-0ubuntu0.22.04.1+esm3 Copyright (c) 2000-2021 the FFmpeg developers
-----------------------------------------------------------------
------------(中略)----------------------------------------------
-----------------------------------------------------------------
--enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared
libavutil      56. 70.100 / 56. 70.100
-------------------------------------------------------------------
------------------(中略)------------------------------------------
-------------------------------------------------------------------
DEV.L. h263p                H.263+ / H.263-1998 / H.263 version 2
DEV.LS h264                 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (decoders: h264 h264_v4l2m2m h264_cuvid ) (encoders: libx264 libx264rgb h264_nvenc h264_omx h264_v4l2m2m h264_vaapi nvenc nvenc_h264 )
-------------------------------------------------------------------
------------------(中略)------------------------------------------
-------------------------------------------------------------------
DES... webvtt               WebVTT subtitle
DES... xsub                 XSUB

これから、H264エンコードを使いたい場合、libx264 を指定します。他にもいろいろ試してみるのも良いと思います。因みにこれはソフトウェアエンコードです。

-pix_fmt

ピクセルフォーマットを指定します。
色空間YUV データの並び方、ビット深度、UV のサブサンプリング方式を指定するそうです。
H264エンコードの場合、以下の公式Wikiページも参照してみてください。

https://trac.ffmpeg.org/wiki/Encode/H.264

FFmpegが対応しているピクセルフォーマットの一覧は以下のコマンドで調べられます。

ffmpeg -pix_fmts
~$ ffmpeg -pix_fmts
ffmpeg version 4.4.2-0ubuntu0.22.04.1+esm3 Copyright (c) 2000-2021 the FFmpeg developers
built with gcc 11 (Ubuntu 11.4.0-1ubuntu1~22.04)
configuration: --prefix=/usr --extra-version=0ubuntu0.22.04.1+esm3 --toolchain=hardened --libdir=/usr/lib/aarch64-linux-gnu --incdir=/usr/include/aarch64-linux-gnu --arch=arm64 --enable-gpl

///////////////////(中略)/////////////////////////////////////////

libpostproc    55.  9.100 / 55.  9.100

Pixel formats:
I.... = Supported Input  format for conversion
.O... = Supported Output format for conversion
..H.. = Hardware accelerated format
...P. = Paletted format
....B = Bitstream format
FLAGS NAME            NB_COMPONENTS BITS_PER_PIXEL
-----
IO... yuv420p                3            12
IO... yuyv422                3            16
IO... rgb24                  3            24
IO... bgr24                  3            24
IO... yuv422p                3            16
IO... yuv444p                3            24
IO... yuv410p                3             9
IO... yuv411p                3            12
IO... gray                   1             8
IO..B monow                  1             1
IO..B monob                  1             1
I..P. pal8                   1             8
IO... yuvj420p               3            12
IO... yuvj422p               3            16
IO... yuvj444p               3            24

///////////////////(中略)/////////////////////////////////////////

I.... y210le                 3            20
IO... x2rgb10le              3            30
..... x2rgb10be              3            30

最初の’IO’という文字は、InおよびOutの略で、入力と出力の両対応という意味です。

H264の入力側の基本はyuv420pらしいのですが、今回使用するUSBカメラ C920n の場合、先の input_format オプションでも述べたように、 yuyv422mjpeg の2種類でした。

入力側の -pix_fmt yuv420p と指定した場合は、H264エンコード前段階でyuv420pに変換されますが、H264エンコードの場合、出力側に yuv420p と指定することが重要だと思われます。
個人的に実験した結果、入力側には指定無しで問題ありませんでした。

なぜ、出力側で -pix_fmt yuv420p と指定した方良いかと言うと、様々なプレーヤーで対応しているからだそうです。良く調べたわけではありませんが、QuickTimeを使う時には問題になるらしいです。
また、出力側に pix_fmt を指定しないと、VLCプレーヤーでは途中で動画が途切れる症状が出ました。

-c:a

出力側のオーディオコーデックを指定します。
ここでは多くのプレーヤーが対応している aac を使います。
これも映像と同様、対応コーデック一覧は、

ffmpeg -codecs

で確認できます。

-ac

オーディオのチャンネルを指定します。
1だとモノラル、2だとステレオです。

-ar

オーディオのサンプリングレートを指定します。
CD(コンパクトディスク)と同じサンプリングレートならば 44100 Hz、DVDならば 48k Hzとなります。

-itsoffset

映像とalsa入力のマイク音声を合わせる時に、マイク音声を遅延させたり、早めたりできます。
ただ、自分のやり方が誤っていたせいなのか、なぜか映像入力ではこのオプションは効果ありませんでした。
よって、入力で映像を先に指定したり、音声を先にしたりすれば、音声を遅らせるか早めるかをきめられるため、映像に指定しなくても音ズレを埋めることができます。

秒数で指定して、正の値ならば遅延、負の値ならば早めることができます。

-itsoffset 0.5 : 映像から音声を0.5秒遅延させて入力する。
-itsoffset -0.5 : 映像から音声を0.5秒早めて入力する。

例えば、先に紹介したように、オーディオ入力を以下の様に先に指定した場合、

ffmpeg -f alsa -thread_queue_size 8192 -i hw:2,0 \
-f v4l2 -input_format mjpeg -s 640x480 -thread_queue_size 8192 -i /dev/video0 \
-c:v libx264 -pix_fmt yuv420p \
-c:a aac -ac 2 -ar 48k \
-f flv rtmp://192.168.0.10:1935/stream

これは音声が0.5秒遅れたので、itsoffset指定してやります。
こんな感じです。

ffmpeg -f alsa -thread_queue_size 8192 -itsoffset -0.5 -i hw:2,0 \
-f v4l2 -input_format mjpeg -s 640x480 -thread_queue_size 8192 -i /dev/video0 \
-c:v libx264 -pix_fmt yuv420p \
-c:a aac -ac 2 -ar 48k \
-f flv rtmp://192.168.0.10:1935/stream

-r

ここでは使っていないのですが、 -r オプションはフレームレートを指定します。
ネット上の殆どの情報ではこのコマンドを使った例を上げています。

これは、入力側に指定する場合と、出力側に指定する場合で動作が異なります。

入力側の映像で指定した場合、例えば、-r 30 とすると、入力が30fpsより小さい場合、映像時間が実際より縮められて無理やり30fpsにしてしまいます。それを再生すると、映像のみが早送り状態になり、音声と合成すると、音声が大幅に遅れてしまうわけです。

また、出力側に -r 30 とした場合、入力側がこれより小さい場合はフレームを複製し、30fpsで出力し、逆に大きい場合は超過したフレームをドロップ(切り捨て)して30fpsで出力するという挙動になります。

ならば、今回のUSBカメラ C920n は可変フレームレートで映像が送られてくるので、その場合はどうしたら良いかというのが問題です。

私もこれにはかなりの時間悩まされました。これが音ズレの大きな原因だったからです。

結果的には、-r オプションを指定しないことが最良の結果でした。
つまり、入力も出力も可変フレームレートのままエンコードするということです。
-vf オプションも不要でした。
私の場合はこれで、音ズレが無くなりました。

9.音ズレ対策

今回はPythonのOpenCVを使っているわけではないので、音ズレ対策は比較的にやり易いです。
OpenCVを使うと音ズレ対策は難しくなってくるので、それについては後日アップ予定の記事で報告したいと思います。

09-01. 音声入力と映像入力の順番を入れ替える

先ほどでも述べましたが、FFmpegコマンドオプションで、オーディオ入力とビデオ入力の位置を逆にすると音ズレが生じました。

例えば、以下のコマンドでは、音声が映像よりも0.5秒遅延しました。

ffmpeg -f alsa -thread_queue_size 8192 -i hw:2,0 \
-f v4l2 -input_format mjpeg -s 640x480 -thread_queue_size 8192 -i /dev/video0 \
-c:v libx264 -pix_fmt yuv420p \
-c:a aac -ac 2 -ar 48k \
-f flv rtmp://192.168.0.10:1935/stream

このコマンドで音声のalsa入力と映像のv4l2入力をテレコにすると音ズレは無くなりました。

ffmpeg -f v4l2 -input_format mjpeg -s 640x480 -thread_queue_size 8192 -i /dev/video0 \
-f alsa -thread_queue_size 8192 -i hw:2,0 \
-c:v libx264 -pix_fmt yuv420p \
-c:a aac -ac 2 -ar 48k \
-f flv rtmp://192.168.0.10:1935/stream

09-02. 安易に -r オプションでフレームレート変換をしないこと

多くのネット情報では、コマンドオプションに -r を使う例が溢れています。
先の -r オプションの解説でも紹介しましたが、これは、入力側が完全固定のフレームレートが保証されているならば特に問題ありませんが、そうでない場合は音ズレに悩まされることになります。私自身もかなり長い間ドロ沼にハマりました。

USBカメラやWebカメラの場合、多くは可変フレームレートで出力されてくると思われるので、入力側は -r オプションは使わず、そのままの状態でH264エンコードすべきだと思います。
入力側にそれを使ってしまうと、音声の時間はそのままなのに、映像だけが時間が縮まったり長くなったりとグチャグチャになります。

また、入力側では -r オプションを使わず、出力側だけに使う例もありましたが、それでも長く視聴していると段々音ズレが生じました。
出力側に置けば、可変フレームレートでもフレームをドロップしたり複製したりして固定フレームレートにしてくれますが、私が実験した場合はやはり音ズレが生じました。
結局は出力側も -r オプションは使わずに可変フレームレートのまま出力することが得策だという結論に至りました。

09-03. -itsoffset を使う

このオプションはストリームを初回読み込みから遅延させたり早めたりすることができます。
ただ、私の場合はなぜか映像(ビデオ)入力側では効果無しでした。音声のalsa入力に対しては有効でした。

値は秒数で、正の値ならば遅延、負の値ならば早めることができます。
例えば、以下ならば、0.8秒遅延させます。

-itsoffset 0.8

以下ならば0.8秒早めることができます。

-itsoffset -0.8

10.トラブルシューティング

10-01. RTMPのNGINXトラブルシューティング

とりあえず、私が遭遇したトラブルシューティングを紹介します。

Job for nginx.service failed because the control process exited with error code というエラー

NGINXの環境設定ファイルを修正して、sudo systemctl restart nginx コマンドを使ってNGINXを再起動したところ、以下のエラーが出ました。

Job for nginx.service failed because the control process exited with error code.
See "systemctl status nginx.service" and "journalctl -xeu nginx.service" for details.
【原因】

このエラーが起きたのは、先に紹介したnginxを完全消去、つまり環境設定も全て削除した後、以下のコマンドで、nginxだけ再インストールし、
sudo apt install nginx
その後にRTMPモジュールを別途インストールしました。
sudo apt install libnginx-mod-rtmp

その後、nginx.confファイルにrtmp用の設定を書き込んだ後、NGINXを再起動したらそういうメッセージが出たというわけです。
原因を突き止めるために、以下のコマンドを実行しました。

sudo nginx -t

すると、以下のエラーメッセージが出ていました。

~$ sudo nginx -t
nginx: [emerg] unknown directive "rtmp" in /etc/nginx/nginx.conf:85
nginx: configuration file /etc/nginx/nginx.conf test failed

つまり、原因は、NGINXとRTMPモジュールを別々にインストールしたことによるものでした。
それによって、RTMPモジュールがロード(読み込み)されていないようです。

【対策1】

一番手っ取り早い対策は、先に紹介したように、以下のコマンドで一旦nginxを完全削除します。

~$ sudo apt purge nginx nginx-common nginx-full

そして、nginxとRTMPモジュールを再インストールします。
注意点は、必ず同時にインストールすることです。

sudo apt install nginx libnginx-mod-rtmp

これで、RTMPモジュールがロード(読み込み)される設定ファイルもインストールされていると思います。

【対策2】

別の対策として、わざわざ再インストールしなくても、以下のサイトにヒントがありました。

https://groups.google.com/g/nginx-rtmp/c/QTnhK75DNsM?pli=1

まず、/etc/nginx/modules-enabled 内にあるモジュールのロード設定されているシンボリックリンクのリストを見てみます。

/etc/nginx/modules-enabled$ ls -1
50-mod-http-geoip2.conf
50-mod-http-image-filter.conf
50-mod-http-xslt-filter.conf
50-mod-mail.conf
50-mod-stream.conf
70-mod-stream-geoip2.conf

このように、RTMPモジュールの設定ファイルが見当たりません。
RTMP設定の場合は、本来、50-mod-rtmp.conf という名前のシンボリックリンクがあるはずです。

ならば、次に、 /usr/lib/nginx/modules 内にRTMPモジュールが存在するか確認してみます。

usr/lib/nginx/modules$ ls -1
ngx_http_geoip2_module.so
ngx_http_image_filter_module.so
ngx_http_xslt_filter_module.so
ngx_mail_module.so
ngx_rtmp_module.so
ngx_stream_geoip2_module.so
ngx_stream_module.so

このように、ngx_rtmp_module.so というファイルがあれば、RTMPモジュールは存在していて、無ければ、以下のコマンドでRTMPモジュールをインストールします。

sudo apt install libnginx-mod-rtmp

そうしたら、nginx.conf内に以下の記述を追加します。

load_module modules/ngx_rtmp_module.so;

これでうまくいかない場合はフルパスを記入します。

load_module /usr/lib/nginx/modules/ngx_rtmp_module.so;

これをnginx.conf内に記述する場合、記述する場所がポイントです。
一番良いのは、最初の行付近にある、
include /etc/nginx/modules-enabled/*.conf;
というところの直ぐ下行に記述すると良いと思います。

これで、nginxを再起動すればRTMPモジュールを読み込んで、エラーが消えるはずです。

ただし、先にも述べたように、nginx.conf ファイルを書き換えるのは得策ではありません。
nginx.confファイルはデフォルトのまま書き換えずに、/etc/nginx/modules-available フォルダに例えば、mod-rtmp.conf というファイル名で、以下のテキストを入力して保存します。

load_module modules/ngx_rtmp_module.so;

そうしたら、/etc/nginx/modules-enabled フォルダにそのファイルのシンボリックリンクを50-mod-rtmp.conf というファイル名で作成しておきます。

ln -s /etc/nginx/modules-available/mod-rtmp.conf /etc/nginx/modules-enabled/50-mod-rtmp.conf

これで、nginxを再起動します。

sudo systemctl restart nginx

これでRTMPモジュールは読み込むと思います。

10-02. VLCプレーヤーでうまく再生されない

いろいろ修正したのに、なぜかVLCプレーヤーで再生できない場合があります。
その場合、VLCプレーヤーのキャッシュを削除してみると治る場合があります。
VLCプレーヤーのキャッシュ削除はWindows 10の場合はスタートメニューにありました。
以下の感じです。

(図10-02)

Windowsの場合のVLCキャッシュ消去

Windowsの場合のVLCキャッシュ消去

このように、
VLC media player - reset preferences and cache files
というアプリをクリックすると、一瞬ウィンドウが表示されて直ぐ消えます。
これでキャッシュが削除できていると思います。

10-03. ALSAデバイスのマイクが認識しない

自分の場合、ラズパイを起動する度にサウンドカード番号が認識したりしなかったり、はたまた番号が変わってしまうことが頻繁に起こりました。
FFmpegコマンドを実行すると、以下のエラーが出ました。

cannot open audio device hw:1,0 (No such file or directory) hw:1,0: Input/output error

一時的に対処するには、先に述べたように arecord -l でマイクロフォンデバイスIDを調べて、hw の値を書き換えればOKです。

ただし、ラズパイを起動する度にデバイス番号が変わってしまうのは避けたいですね。

そこで以下のコマンドでログを調べます。

cat /var/log/syslog

そして、ログから snd-usb-audio というワードを検索します。
すると、以下のような文言が見つかりました。

snd-usb-audio 1-1.1.2:1.2: cannot find the slot for index 0

オーディオのUSBデバイスが認識していない様です。

ということで、これを解決するには、 /etc/modprobe.d/alsa-base.conf というファイルを書き換えます。
ファイルが無い場合は新規作成すれば良いです。

以下の公式サイトを参考にしていきます。

【参考サイト】
https://wiki.archlinux.jp/index.php/Advanced_Linux_Sound_Architecture

そのサイトの「デフォルトサウンドカードの設定」という項目のところを参照します。
とりあえず、以下のコマンドで alsa-base.conf ファイルを編集します。

sudo vi /etc/modprobe.d/alsa-base.conf

そして、以下の項目を見ます。

options snd-usb-audio index=-2

これは2か所ありました。

index-2 にすることで ALSA にカードを優先的に使わせないようにすることも可能とのこと。
つまり、自動的にカードID番号を割り当てる設定です。
起動の度に番号が変わってしまうのはこれが原因です。よって、これを書き換えます。

ただ、要注意は今回の私の場合のようにUSBハブを使ったりする場合は index を2以上にした方が良いかもしれません。
1にした場合、最初は問題無かったのですが、数週間経過すると、カードが認識しない状態に落ち入りました。
apt upgradeする度にそのカード番号では都合が悪くなったのかも?
0にした場合は全く認識しなくなりました。

これについては以下のサイトにヒントがありました。

https://unix.stackexchange.com/questions/303471/alsa-audio-device-reordering-cannot-find-the-slot-for-index-0-range-0-1-erro

たぶん、0や1だと、システムがデフォルトで設定する番号と競合するのかも?
よって、以下のように index=2 に設定しました。
因みに以下の設定は2か所修正するところがありました。

options snd-usb-audio index=2

これで、ラズパイを再起動したら、今のところ特に問題なく、順調に動いています。

11.まとめ

今回は初めてNGINXサーバーを使ってみましたが、最初の環境設定ではネットの情報にかなり惑わされましたね。
でも、いろいろ設定をこねくり回しているうちに、やっとこれがたぶん正解だろうという設定方法にたどり着いたことは収穫でした。

また、FFmpegで初めて動画圧縮のH264エンコードを扱ってみましたが、オーディオのエンコードもできて、色んなオプションがあって、改めてFFmpegっていうのは優れものだなと感心しました。

そして、トラブルシューティングとして、環境設定を修正したのに反映されない場合はプレーヤーのキャッシュを削除することが重要ということも勉強になりました。
また、長い間悩まされた音ズレについては最近ようやく納得できる対策ができました。

今回はRTMPでしたが、やっぱりブラウザでストリーミングしたいですよね。
実はそれが可能なHLS方式については既に実験済みで、Python-OpenCVによる加工動画も再生できましたよ。
それについては次回の記事でアップしようと思います。

ではまた…。

コメント

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