WPP
ラズベリーパイの RUSTDESK をヘッドレスで使う

ちょっとYAMAHA ルーターの実験をするのに、LAN の向こう側約として Raspberry PI を使っていました。

それはどうでもいいのですが、RUSTDESK をインストールし vnc をアンインストールすると、RUSTDESK で接続できなくなってしまいました。

RUSTDESK に限らず、Linux で動くリモートデスクトップ系のアプリにはよくあるのですが自分が起動したときにデスクトップ環境のディスプレイが存在しないと接続に失敗してそのまま終わるという現象ですね。

VNC の場合も基本同じ設定でいけますがラズパイの場合、インストーラと raspi-config がよしなにしてくるのでこの設定は必要ない。

参考の von的部落格 でも Wayland から X11 に変更してが、たまたまそうなっていたのでそこはスルーする。

lightdm は使っていないのでここもスルー。

dummy ビデオドライバ?をインストールする。

$ sudo apt install xserver-xorg-video-dummy

; ダミーの xorg.conf を作成する
$ sudo /etc/X11/xorg.conf.d/xorg.conf 

ファイルの中身は以下のようにした。von的部落格 のサイトではもっと多くの解像度が定義されていたがうちにはそんな大きなモニタはないので外している。

Section "ServerFlags"
  Option "DontVTSwitch" "true"
  Option "AllowMouseOpenFail" "true"
  Option "PciForceNone" "true"
  Option "AutoEnableDevices" "false"
  Option "AutoAddDevices" "false"
  Option "IgnoreABI" "true"
EndSection

Section "InputDevice"
  Identifier "virtual_mouse"
  Option "CorePointer" "true"
  Driver "void"
EndSection

Section "InputDevice"
  Identifier "virtual_keyboard"
  Option "CoreKeyboard" "true"
  Driver "void"
EndSection

Section "Device"
  Identifier "virtual_videocard"
  Driver "dummy"
  VideoRam 192000
EndSection

Section "Monitor"
  Identifier "virtual_monitor"
  HorizSync   5.0 - 2000.0
  VertRefresh 5.0 - 200.0
  Modeline "1920x1440" 69.47 1920 1960 2152 2384 1440 1441 1444 1457
  Modeline "1920x1080" 23.53 1920 1952 2040 2072 1080 1106 1108 1135
  Modeline "1600x1200" 22.04 1600 1632 1712 1744 1200 1229 1231 1261
  Modeline "1440x900" 30.66 1440 1472 1584 1616 900 921 924 946
  Modeline "1280x1024" 31.50 1280 1312 1424 1456 1024 1048 1052 1076
  Modeline "1280x800" 24.15 1280 1312 1400 1432 800 819 822 841
  Modeline "1024x768" 18.71 1024 1056 1120 1152 768 786 789 807
EndSection

Section "Screen"
  Identifier "virtual_screen"
  Device "virtual_videocard"
  Monitor "virtual_monitor"
  SubSection "Display"
    Depth 24
    Modes "1920x1440" "1920x1080" "1600x1200" "1440x900" "1280x1024" "1366x768" "1280x800" "1024x768" "800x600" 
  EndSubSection
EndSection

Section "ServerLayout"
  Identifier   "virtual_layout"
  Screen       "virtual_screen"
  InputDevice  "virtual_mouse"
  InputDevice  "virtual_keyboard"
EndSection

RUSTDESK を初めてヘッドレスにする際は以下も必要になる。

$ sudo rustdesk --option allow-linux-headless Y
$ sudo rustdesk --get-id
$ sudo rustdeskt --password XXXXXX

rustdesk はデフォルトだと接続先の画面に表示されている接続ID とワンタイムパスワードをみながら接続する必要があるが、当然ヘッドレスだとそれができないので接続ID を取得して、固定パスワードに変更している。

$ DISPLAY=:0 xrandr --output DUMMY0 --mode 1024x768

は今回は必要なかったが、解像度変えたいときは使用すればいいってことか?

以上で無事接続できた。ディスプレイがなくても接続できる nomachine のほうがやっぱりかんたんかも。

参考

用RustDesk連線到headless的樹莓派Linux伺服器 · Ivon的部落格
中国語でしんどい、けど基本コピペでいけた

no display? · rustdesk/rustdesk · Discussion #1615 · GitHub

RUSTDESK がいい感じ

これまで linux での VNC の設定がいまだによくわからないので、nomachine をリモートデスクトップ接続に使用していました。

数あるリモートデスクトップアプリの中でも nomachine は linux, Mac, Raspberry pi, Windows に対応し都合が良かったからです。

一方で Windows ドメイン (Active Directory) に参加している Windows にリモート PC からアクセスすると度々認証まわりのエラーで接続できないことが多くちょっと面倒だとおもっていました。
具体的には設定等を変更していないのに、あるときは接続に失敗したり、別のときは成功したりといった現象にわずらわされていました。これは推測ですが、Windows ドメイン認証は、社内ネットワークに接続していない状態でPC にログインできるように認証情報がキャッシュされる仕組みがあったはずです。このキャッシュでの認証できる状態だとどうやらログインできている気がする。(反対向きにいうとネットワーク経由でログインしたときは、どうもnomachine で必要な権限が許可されていないようだ。)

話がながくなったが、上に閉口して移転先を探してみた。

候補としては、X2Go、RUSTDESK、Dayon が見つかったが今回は RUSTDESK を使用することにした。

Windows でのインストール

scoop にパッケージがあったので `> scoop install rustdesk` でインストールした。

Linux でのインストール

LM22 では デフォルトのアプリストアに flatpak で掲載されていたので flatpak でインストールした。

2025-3-25 追記:

LM22 で RUSTDESK をインストールしただけの状態では、デスクトップセッション(X11)を開いてからしか使えないようなので、自動ログインするように設定した上で、 [Startup Applications] で RUSTDESK を起動するようにした。

Raspberry pi でのインストール

参考ページの Pi-Apps というのを経由して入れてみた。RUSTDESK 自身は github にあるんですが、Version-Upの度に手動インストールは結構だるいので、Pi-Apps を使ってみることにした。

使用方法

説明を明確にするための用語の定義

リモート PC: リモートからアクセスさせたいPC (画面なしPC や手元以外のPC)

ローカル PC: 自画面に外部PC の画面を表示してコントロールする PC

  1. リモート PC で RUSTDESK を起動する。
    • この PC をヘッドレス運用したい場合は、固定パスワードを指定する。
    • リモートPC の ID とパスワード をメモる (メモらなくてもいいがこの PC の ID でリモートから接続する)
  2. ローカル PC でも同じように RUSTDESK を起動する。
  3. リモート PC の ID で接続開始する。
  4. リモート PC のワンタイムパスワードか固定パスワードで認証要求をかける
  5. リモート PC の画面が表示される。

あくまで体感でしかないが、nomachine や VNC よりもキビキビと動いているきがする。画面表示もクッキリなきがしていいかもしれない。

当面はこれを使っていこう。

参考

Install RustDesk on Raspberry Pi | Pi-Apps

rustdesk/rustdesk: An open-source remote desktop application designed for self-hosting, as an alternative to TeamViewer.

ラズベリーパイに eza をインストール

eza は ls の代替コマンドでいい感じに表示してくれるやつ。LM22 や Ubuntu では気に入って使用しているが RaspberryOS ではデフォルトではインストールできないようだ。

公式の説明では以下の通りだが、RaspberryOS (bullseye) では 若干ディレクトリ構成がことなるので調整する。

$ sudo mkdir -p /etc/apt/keyrings
$ wget -qO- https://raw.githubusercontent.com/eza-community/eza/main/deb.asc | sudo gpg --dearmor -o /etc/apt/keyrings/gierens.gpg
$ echo "deb [signed-by=/etc/apt/keyrings/gierens.gpg] http://deb.gierens.de stable main" | sudo tee /etc/apt/sources.list.d/gierens.list
$ sudo chmod 644 /etc/apt/keyrings/gierens.gpg /etc/apt/sources.list.d/gierens.list
$ sudo apt update
$ sudo apt install -y eza

gpg キー用のフォルダが /etc/apt/trusted.gpg.d となり keyrings とは異なっていたので変更。

gpg キーファイル、ソースストのファイル名も eza.gpg と eza.list にそれぞれに変更した。もとの gierens という名前だと後で見たとき恐らく何ために入れたかわからなくなりそうなので変えた。
これは好みの問題で、そのままで変える必要はない。

$ wget -qO- https://raw.githubusercontent.com/eza-community/eza/main/deb.asc | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/eza.gpg
$ echo "deb [signed-by=/etc/apt/trusted.gpg.d/eza.gpg] http://deb.gierens.de stable main" | sudo tee /etc/apt/sources.list.d/eza.list
$ sudo chmod 644 /etc/apt/trusted.gpg.d/eza.gpg /etc/apt/sources.list.d/eza.list
$ sudo apt update
$ sudo apt install -y eza

eza という名前を忘れるのでエイリアスを ~/.barshrc や~/ .bash_aliases に書き込む。書き込んだら . (source コマンド) で反映させる。

$ alias ls='eza'
$ . ~/.bashrc

参考

eza/INSTALL.md at main · eza-community/eza

arm64 ROS2 環境を podman で動かす

いろいろと紆余曲折ありましたが、最終的に podman で動かすことで落ち着きそうなので記事にします。

d最近の私のお供は Claude なのですが早速聞いてみますとつらつらと Dockerfile を提示してきます。多少アレンジしてますが骨子はそのままです。

FROM --platform=linux/arm64 ubuntu:22.04


ENV DEBIAN_FRONTEND=noninteractive

RUN rm /var/lib/dpkg/info/libc-bin.* && apt-get clean

# 日本のミラーに向ける
RUN sed -i 's@archive.ubuntu.com@ftp.jaist.ac.jp/pub/Linux@g' /etc/apt/sources.list

RUN apt-get update && \
    apt-get install -y wget \
    curl \
    git \
    vim \
    lsb-release \
    build-essential python3-pip python3-setuptools python3-dev \
    gnupg2 xterm x11-apps

# ROSのセットアップ(ここでは例としてROS 2 Humbleを使用)
RUN curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
RUN echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | tee /etc/apt/sources.list.d/ros2.list > /dev/null
RUN apt-get update && apt-get install -y \
    ros-humble-ros-base \
    ros-humble-rqt* \
    ros-humble-rviz2 \
    python3-colcon-common-extensions

# 作業ディレクトリの作成
RUN mkdir -p /workspace
WORKDIR /workspace

# 環境変数の設定
RUN echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc

変更かけたのは、 sed で日本のミラーに向けたところと、rm /var/lib/dpkg/info/libc-bin.* でファイルを削除した箇所です。

特にこの libc-bin.* の削除をしないと、apt-get でのパッケージインストールにことごとく失敗するします。なんとなく削除するのは良くないような気もするのですが、 Stack Overflow でもいくつか Good がついているので大丈夫じゃないかと。

setup.bash もすでに読み込み済みなので起動すると即 ros2 コマンドが実行できる状態になっています。

ビルドと起動は下のようにします。

Claud は気が利いているのどうなのかこの状態で GUI アプリも動作出来るようにしてくれているようでコンテナを実行するにはこうするみたいです。

$  ls ./Dockerfile
./Dockerfile

$ podman build -t ros2-arm64 .

$ podman run --platform linux/arm64 \
  -v /tmp/.X11-unix:/tmp/.X11-unix \
  -e DISPLAY=$DISPLAY \
  -v $HOME/.Xauthority:/root/.Xauthority \
  -v $HOME/ros2_ws:/workspace \
  --net=host \
  -it localhost/ros2-arm64

起動のたびにこのコマンド打つのはしんどいのでシェルスクリプトかなんかにしたほうがよさげ。

でコンテナの中で動作確認するには、下のようにしろと Claude が言うので試してみる。

; ホストに 目玉アプリが表示される。
in-contailner: # xeyes

; ホストに ros2 の rqt が表示される
in-contailner: # rqt 

ちゃんと計測したわけではないが qemu-system でエミュレーションより少し早い気がする。

にしても Claude に言われるがままだな。

参考

Dockerのイメージビルド中でapt-getを高速化するたった1つの方法 | ゲンゾウ用ポストイット
souces.list のミラーを日本の jaist に向ける設定

ruby on rails – Docker build fails because unable to install libc-bin – Stack Overflow
libc-bin のエラー回避

Pi 5 温度の取得とシェルの小ネタ

よく忘れるのでメモ。

前回記事で、Pi5 PoE+ HAT のことを書きましたが、こいつにはファンがついていて温度設定でコントロールできるようになっています。

設定方法は、WaveShare の wiki でみればいいのですが、(多分これ Raspberry 公式と同じ内容なはずです。) ふと温度の確認方法はどうだっけと思い検索しました。

; 
$ vcgencmd measure_temp
#temp=40.1'C

; 普通に cat すると 1000 倍の値が取れる
$ echo  cat /sys/class/thermal/thermal_zone0/temp
47950

;  単純に 1 / 1000 にすると切り捨てられる
$ echo $(($(cat /sys/class/thermal/thermal_zone0/temp) / 1000))
47

; こうすると、小数点以下が生きる
$ cat /sys/class/thermal/thermal_zone0/temp |awk '{print $1 /1000}'
47.95

参考

RaspberryPi(Raspbian)のCPUの温度をcatを使わないで取得してみた #Bash – Qiita

Pi5 に PoE+ HAT で NVME 起動するように設定する

先日から始まった ROS2 関連のエントリになります。

とりあえず ROS2 を Raspberry Pi で動かしているのですが、Pi 4 が 1 台だけだと心もとないので Pi 5 用の POE+ ハットを購入して動かすことにしました。

買ったのは WaveShare の PoE M.2 HAT+ という商品です。日本だと 4,000 から 5,000 円くらいで入手できると思います。自分は WaveShare 公式から買いました。

そんなことはどうでもいいのですが、この HAT には M.2 NVME ソケットがついていて SSD を接続するとそこから Pi 5 を起動できるようになります。というのも ROS2 のモジュールを作る際、ビルドが早い環境があったほうが何かと都合がいいので SSD 起動を試します。

基本、参考セクションの公式のページ通りにやれば何も問題は起きないはずです。が、自分の場合はなぜか pcie デバイスとして認識しない事態になりました。

というのもこの HAT のケーブル向きがあるんです !

写真は最終的に成功したときの様子です。

Pi5 + WaveShare PoE M.2 HAT+ 接続全体

接続がうまく行っているときは右上の赤枠の通り、電源 LED が点灯し、緑のアクセスランプが適宜点灯(要するに点滅)します。

で前述のケーブルの向きですが、こうなります。

PoE M.2 HAT+ ではケーブル向きを上の写真のように三角の位置を揃える必要があるってことです。

これ普通に公式 Wiki 見ていればきづくはずですが、フラットケーブルの端子面は気にしていたのですが、見落としてました。

一般的に片面にしか端子がないフラットケーブルはひっくり返すと通電しません。(コネクタ側も片面しか端子がないので、当たり前です。)

さらに、この HAT の場合には、三角マークの部分で左右非対称になっているようで三角の位置を合わせないとダメでした。つまりこのケーブルは、Pi 5 に挿す側と HAT に挿す側が予め決まっており、裏表も正しく挿す必要がありました。

同様の事態になる人は少ないと思いますが、自戒の意味を込めて晒します。

あとは、まあ公式通りです。

/boot/firmware./config.txt に dtparam の行を追加します。

$ sudo vi /boot/firmware/config.txt
[all]
dtparam=pciex1
dtparam=pciex1_gen=3
:wq

動画かなにかで [cm4] セクションに書いている例もありましが、なんとなく気持ち悪いので [all] セクションに書きました。正直無名セクションや、pi0 系のセクション以外ならで良いとおもいますが。。。

再起動して lspci で SM2263 が表示されれば OKです。

次に rpi-eeprom-config –edit でブートオーダーを変更します。

$ sudo rpi-eeprom-config -edit
BOOT_ORDER=0xf416

あとは、”SD Card Copier” でコピーするなり、”Raspberry Pi Imager” で SSD にOSを書き込めば起動します。

参考

PoE M.2 HAT+ – Waveshare Wiki

Raspberry Pi 5をNVMe SSD起動でデスクトップPC化

Ubuntu 22.04 で Unable update “Snap Store”: といわれアップデートできない

先週から ROS2 をラズパイ 4 で動かし始めています、ROS2 の対応 OS が Ubuntu 22.04 なので RaspberryOS を諦めて素直に U22 にしています。

同じ Debian 系とはいえ普段使っている Linux Mint とも RaspberryOS ともビミョーに異なり、困らないもののストレスフルな毎日です。

表題ですが Snap Store (Ubuntu Software) で Snap Store のアップデートがあるので更新しようとしてもエラーメッセージ「Unable update “Snap Store”: snap … 」とでてアップデートできません。試しに再起動を試みましたが現象変わらず。

以下のコマンドで回避できました。

$ killall snap-store
$ sudo snap refresh snap-store

Ubuntu は多分 Gnome でつかっているんだけどやっぱり遅くてあまり好きになれない。ROS2 動かす GUI はいらないのだけど、カメラのデータを扱いたいのでぱっと確認しやすい GUI ありのがいいのよね。

参考

How to close the Snap Store to allow Snapd to update it – Project Discussion / Snap Store – Ubuntu Community Hub

DietPi で mdns をアクティブにする

ROCK64 に入れた DietPi だが、外からは .local で応答してくれるが、DietPi の中では、.local の名前解決に失敗していたので以下を追加でインストールした。

$ sudo apt install libnss-mdns

# 名前解決できるか確認してみる
$ ping rock64.local
PING rock64.local (192.168.1.250) 56(84) bytes of data.
64 bytes from 192.168.1.250 (192.168.1.250): icmp_seq=1 ttl=64 time=0.157 ms
64 bytes from 192.168.1.250 (192.168.1.250): icmp_seq=2 ttl=64 time=0.163 ms
....

無事に、.local 名を名前解決できるようになった

DietPi で SBC の LED 設定を変更する

小ネタです。

自宅で動いている ROCK64 という SBC (Single Board Computer) では DietPi という軽い SBC 向けディストリビューションを動かしています。

SBC でよくあるように ROCK64 にも LED がいくつかあり自分の状態を表示しています。

DietPi  + ROCK64 の場合は、led-1 (電源コネクタと反対側の端) が動作中はずっとハートビートする設定になっています。設置している場所が寝室なので夜間はかなり煩わしく感じていました。

internet を検索してみると、ブラウザの検索結果の脇で Copilot が教えてくれました。自分で検索結果を読み取るよりよっぽど早かったことには感動。

Copilot によると dietpi-config で設定できるとのこと。実際にやってみると

  1. sudo dietpi-config
  2. 『1: Display Options』
  3. 『 14: LED Control』
  4. 変更したいLEDを選び(今回は led-1)
  5. 表示したい機能を選択する

こんな感じでできる

ラズパイカメラ + nginx で hls(RTMP)サーバ

ここのところカメラでストリーミングの実験をいろいろしているのですが、今回は hls サーバの実験です。RTMPサーバと呼ぶべきなのかもしれませんが何となくあやふやです。

内容的には IoT PLUS さんの内容のほぼまんまですが、ffmpegのパラメータとsystemd での起動に変更したのでさらします。
まあ、誰かの役に立つかもしれないがわからない。

それにしても ffmpeg のコマンドラインは私にとって鬼門です。ドキュメント読む気にイマイチならないのよ。誰か分かりやすい解説ページつくってくれないでしょうか ?

手順

必要な物は、ffmpeg と nginx です。apache は追ってないですが nginx に rtmp モジュールがあってお手軽なのでその例があるのだと思います。

自分の例では http basic auth も設定していないので apache2-utils は不要です。php-fpm も入れません。

インストール

$ sudo apt update
$ sudo apt install ffmpeg nginx libnginx-mod-rtmp

出力フォルダの準備

こちらも丸パクリですが、/dev/shm のリンクを作成します。

$ sudo mkdir -p /var/www/html/live
$ cd /var/www/html/live
$ sudo ln -s /dev/shm hls

index.html の準備

/var/www/html/index.html を作成します。中身はとりあえずパクリです。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8"/>
  <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
</head>

<body>
  <video id="video" controls width="100%"></video>
  <script>
    if(Hls.isSupported()) {
      var video = document.getElementById('video');
      var hls = new Hls();
      hls.loadSource('live/hls/stream.m3u8');
      hls.attachMedia(video);
      hls.on(Hls.Events.MANIFEST_PARSED,function() {
      video.play();
    });
   }
  </script>
<p>
  iPhoneなどで再生されない場合は、<a href="live/hls/stream.m3u8">こちら</a>をクリック。
</p>
</body>
</html>

nginx の設定

/etc/nginx/rtmp.conf ファイルを作成し、そいつを /etc/nginx/nginx.conf でインクルードしてやります。

もともと nginx.conf のなかで. conf.d の中にある *.conf ファイルは読み込まれるのですが、設定ファイルの位置的にまずいらしくエラーになるのでこの構成にしてます。

更に、/var/www/html のロケーションのハンドラを /etc/nginx/conf.d/default.conf に書きます。

rtmp {
    server {
        listen 1935;
        chunk_size 4096;
        allow play all;
        access_log /var/log/nginx/rtmp_access.log;

        application live {
            live on;
            hls on;
            record off;
            hls_path /var/www/html/live/hls;
            hls_fragment 1s;
            hls_type live;
        }
    }
}

これを下の nginx.conf でインクルードしてやります。

events {
----
}
http {
----
}

# http ブロックの外になるように以下の行を追加
include /etc/nginx/rtmp.conf;

/etc/nginx/conf.d/default.conf はこうなります。リッスンポートは 8080 に変更してます。

server {
    listen 8080;
    proxy_set_header   X-Forwarded-For     $proxy_add_x_forwarded_for;
    access_log /var/log/nginx/access.log combined;
    error_log /var/log/nginx/error.log warn;

    location = /favicon.ico {
        access_log off;
        empty_gif;
        expires 30d;
    }

    location / {
        #auth_basic "Web Cam Streaming";
        #auth_basic_user_file /var/www/.htpasswd;

        root /var/www/html;
        index index.html;
        set_real_ip_from    127.0.0.1;
        real_ip_header      X-Forwarded-For;
    }
}

nginx を起動しておきます

$ sudo systemctl daemon-reload
$ sudo systemctl restart nginx

ffmpeg の起動テスト

一旦、ffmpeg で動画を見れるかテストします。今回の環境ではマイクがないので、音声関連のパラメータはざっくり削除しています。

$ ffmpeg -f v4l2 -thread_queue_size 8192 -s 720x480 -i /dev/video0 \
    -r 15 -c:v h264_omx -b:v 512k \
    -vf "rotate=180*PI/180" \
    -f flv rtmp://localhost/live/stream

パラメータの説明

-s 720×480: 解像度
-r 15: フレームレート(15 フレーム / sec)
-vf “rotate=180*PI/180”: 画像を 180度 ローテーションする。(ラジアンに変換)

すべてがうまくいっていれば、こんなふうにブラウザに動画が表示されます。

systemd の設定

参考にしたページでは起動スクリプトで終わっていましたが、systemd に登録することにします。まずは先ほどの ffmpeg 起動コマンドをスクリプト化します。

さっきは、直打ちしていたパラメータを環境変数に逃がしてあげます。更にちょっと乱暴ですが起動時に ffmpeg のプロセスを一旦全部殺します。ロックファイルで制御するのが丁寧だとおもいますが、面倒なのでよしとします。

#!/bin/bash 

ROTATE=180
BITRATE=512k
FRATE=15
RES=720x480
# RES=1920x1080


# kill other instances of ffmpeg
pkill ffmpeg

# start camera server
ffmpeg -f v4l2 -thread_queue_size 8192 -s $RES -i /dev/video0 -r $FRATE \
    -c:v h264_omx -b:v $BITRATE \
    -vf "rotate=$ROTATE*PI/180" \
    -f flv rtmp://localhost/live/stream > /dev/null 2>&1 </dev/null&

これを呼び出す systemd ユニットを作成します。名前はrtmp-camera.service としましたが好きなものに変えて構いません。

ExecStart に 上のシェルスクリプトのフルパスを指定します。systemd unit ファイルでは フルパスを指定します。そうでないとサービス起動時にエラーになります。

パスはシェルスクリプトを作成した場所に適宜変更してください。

[Unit]
Description=RTMP camera server with ffmpeg.

[Service]
ExecStart=/opt/rtmp/start.sh
Restart=always
#Type=simple
Type=oneshot
RemainAfterExit=yes
User=pi

[Install]
WantedBy=multi-user.target

2024-4-12 Type=oneshot に修正し、RemainAfterExit=yes を追加。

systemctl で有効にしていきます。

$ sudo systemctl enable /opt/rtmp/rtmp-camera.service
$ sudo systemctl daemon-reload
$ sudo systemctl start rtmp-camera.service

daemon-reload はもしかしたら不要かもしれません。とにかく enable した後、ちゃんと起動しているか確かめてください。上手く動いていればブラウザでカメラで撮影している動画が流れているはずです。

参考

超簡単! ffmpeg + rtmp + nginxを使ってraspberry pi + webカメラのストリーミング環境を作る(raspbian buster版) | IoT PLUS

子供の笑顔と笑い声を聞く為に ffmpeg + Nginx + RTMP on RaspberryPI – 長生村本郷Engineers’Blog

【ffmpeg】簡単ネットワークカメラの作り方
ここの例は、hls ではなく jpg 画像を更新し続けているのでクライアントからすると motionJPEG 形式になるのだと思う。