環境構築手順 を追加
@@ -0,0 +1,943 @@
|
|||||||
|
# サーバー環境構築
|
||||||
|
|
||||||
|
## 概要
|
||||||
|
|
||||||
|
このページでは `nizika_broadcast` V1 を Ubuntu 26.04 LTS 上で稼働させるための環境構築手順を記載する。
|
||||||
|
|
||||||
|
現在の運用対象は V1。
|
||||||
|
|
||||||
|
`nizika_broadcast_v2` は deprecated とし、今回の環境構築では使用しない。
|
||||||
|
|
||||||
|
本番構成:
|
||||||
|
|
||||||
|
```text
|
||||||
|
nizika_broadcast
|
||||||
|
│
|
||||||
|
├─ pygame
|
||||||
|
├─ nizika_ai
|
||||||
|
├─ nizika_nico
|
||||||
|
│
|
||||||
|
├─ Xvfb :99
|
||||||
|
│
|
||||||
|
├─ PulseAudio
|
||||||
|
│ └─ stream
|
||||||
|
│ └─ stream.monitor
|
||||||
|
│
|
||||||
|
├─ AqKanji2Koe
|
||||||
|
├─ AquesTalk2 Eva
|
||||||
|
│
|
||||||
|
└─ ffmpeg
|
||||||
|
│
|
||||||
|
└─ YouTube RTMPS
|
||||||
|
```
|
||||||
|
|
||||||
|
repository:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/opt/nizika_broadcast
|
||||||
|
```
|
||||||
|
|
||||||
|
service user:
|
||||||
|
|
||||||
|
```text
|
||||||
|
nizika
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 1. service user
|
||||||
|
|
||||||
|
```bash
|
||||||
|
useradd --system \
|
||||||
|
--home /var/lib/nizika \
|
||||||
|
--create-home \
|
||||||
|
--shell /usr/sbin/nologin \
|
||||||
|
nizika
|
||||||
|
```
|
||||||
|
|
||||||
|
確認:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
id nizika
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 2. repository
|
||||||
|
|
||||||
|
信頼できる Gitea の最新 `main` を取得し、
|
||||||
|
|
||||||
|
```text
|
||||||
|
/opt/nizika_broadcast
|
||||||
|
```
|
||||||
|
|
||||||
|
へ配置する。
|
||||||
|
|
||||||
|
旧サーバーの working directory をそのままコピーしない。
|
||||||
|
|
||||||
|
関連 repository:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/opt/nizika-nico
|
||||||
|
```
|
||||||
|
|
||||||
|
`nizika_ai` もコードおよび DB 接続上の依存として利用される。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 3. OS package
|
||||||
|
|
||||||
|
```bash
|
||||||
|
apt update
|
||||||
|
|
||||||
|
apt install -y \
|
||||||
|
git curl unzip \
|
||||||
|
ffmpeg \
|
||||||
|
xvfb \
|
||||||
|
pulseaudio \
|
||||||
|
pulseaudio-utils \
|
||||||
|
python3 \
|
||||||
|
python3-pip \
|
||||||
|
python3-pygame \
|
||||||
|
python3-opencv \
|
||||||
|
python3-numpy \
|
||||||
|
python3-ephem \
|
||||||
|
python3-emoji
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 4. Python package
|
||||||
|
|
||||||
|
この環境では venv を使用せず system Python を使用する。
|
||||||
|
|
||||||
|
pip install 前:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
umask 022
|
||||||
|
export HOME=/root
|
||||||
|
```
|
||||||
|
|
||||||
|
必要 package:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -m pip install \
|
||||||
|
--break-system-packages \
|
||||||
|
'requests==2.32.5' \
|
||||||
|
'pytchat==0.5.5' \
|
||||||
|
'httpx[http2]==0.27.2' \
|
||||||
|
pydub \
|
||||||
|
audioop-lts \
|
||||||
|
simplejson \
|
||||||
|
'eloquent==0.5' \
|
||||||
|
'mysqlclient==2.2.8'
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 5. Python 3.14 の注意
|
||||||
|
|
||||||
|
Python 3.14 では標準 `audioop` が削除されている。
|
||||||
|
|
||||||
|
`pydub` を利用するため:
|
||||||
|
|
||||||
|
```text
|
||||||
|
audioop-lts
|
||||||
|
```
|
||||||
|
|
||||||
|
を追加する。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 6. pip permission の注意
|
||||||
|
|
||||||
|
pip install 時に `umask 077` が設定されていると、
|
||||||
|
|
||||||
|
```text
|
||||||
|
/usr/local/lib/python3.14/dist-packages
|
||||||
|
```
|
||||||
|
|
||||||
|
配下が:
|
||||||
|
|
||||||
|
```text
|
||||||
|
drwx------
|
||||||
|
-rw-------
|
||||||
|
```
|
||||||
|
|
||||||
|
となる場合がある。
|
||||||
|
|
||||||
|
この状態では `nizika` user から package が正常に見えず、
|
||||||
|
|
||||||
|
```text
|
||||||
|
No module named 'pytchat.core'
|
||||||
|
module 'httpx' has no attribute 'Client'
|
||||||
|
```
|
||||||
|
|
||||||
|
等の不可解な error が発生する場合がある。
|
||||||
|
|
||||||
|
確認:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
find /usr/local/lib/python3.14/dist-packages \
|
||||||
|
-type d ! -perm -005 -o -type f ! -perm -004 \
|
||||||
|
-print \
|
||||||
|
| head -100
|
||||||
|
```
|
||||||
|
|
||||||
|
必要なら:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chmod -R a+rX \
|
||||||
|
/usr/local/lib/python3.14/dist-packages
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 7. Python import test
|
||||||
|
|
||||||
|
```bash
|
||||||
|
runuser -u nizika -- python3 - <<'PY'
|
||||||
|
mods = [
|
||||||
|
"httpx",
|
||||||
|
"pytchat",
|
||||||
|
"pydub",
|
||||||
|
"eloquent",
|
||||||
|
"MySQLdb",
|
||||||
|
"pygame",
|
||||||
|
"cv2",
|
||||||
|
"numpy",
|
||||||
|
]
|
||||||
|
|
||||||
|
for mod in mods:
|
||||||
|
try:
|
||||||
|
m = __import__(mod)
|
||||||
|
print(f"{mod}: OK {getattr(m, '__file__', None)}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"{mod}: NG {type(e).__name__}: {e}")
|
||||||
|
PY
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 8. AqKanji2Koe
|
||||||
|
|
||||||
|
repository 内の:
|
||||||
|
|
||||||
|
```text
|
||||||
|
aques
|
||||||
|
```
|
||||||
|
|
||||||
|
は `libAqKanji2Koe.so.4` を利用する。
|
||||||
|
|
||||||
|
旧サーバーの binary をコピーせず、A-Quest 公式 Linux package から取得する。
|
||||||
|
|
||||||
|
64bit library を `/usr/local/lib` へ配置する。
|
||||||
|
|
||||||
|
最終的に:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/usr/local/lib/libAqKanji2Koe.so.4.1
|
||||||
|
/usr/local/lib/libAqKanji2Koe.so.4
|
||||||
|
/usr/local/lib/libAqKanji2Koe.so
|
||||||
|
```
|
||||||
|
|
||||||
|
となるよう symlink を作成する。
|
||||||
|
|
||||||
|
反映:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ldconfig
|
||||||
|
```
|
||||||
|
|
||||||
|
動作確認:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /opt/nizika_broadcast
|
||||||
|
|
||||||
|
printf 'こんにちは\n' | ./aques
|
||||||
|
```
|
||||||
|
|
||||||
|
`aques` は WAV generator ではなく、漢字仮名交じり文から AquesTalk 用の音声記号列を生成する。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 9. AquesTalk2 Eva
|
||||||
|
|
||||||
|
`aques.py` は:
|
||||||
|
|
||||||
|
```text
|
||||||
|
libAquesTalk2Eva.so
|
||||||
|
```
|
||||||
|
|
||||||
|
を利用する。
|
||||||
|
|
||||||
|
A-Quest 公式 Linux evaluation package から取得する。
|
||||||
|
|
||||||
|
配置例:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/usr/local/lib/libAquesTalk2Eva.so.2.3
|
||||||
|
/usr/local/lib/libAquesTalk2Eva.so.2
|
||||||
|
/usr/local/lib/libAquesTalk2Eva.so
|
||||||
|
```
|
||||||
|
|
||||||
|
反映:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ldconfig
|
||||||
|
```
|
||||||
|
|
||||||
|
この環境では:
|
||||||
|
|
||||||
|
```dotenv
|
||||||
|
LD_LIBRARY_PATH=/usr/local/lib
|
||||||
|
```
|
||||||
|
|
||||||
|
も設定する。
|
||||||
|
|
||||||
|
確認:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
LD_LIBRARY_PATH=/usr/local/lib \
|
||||||
|
python3 - <<'PY'
|
||||||
|
from ctypes import cdll
|
||||||
|
|
||||||
|
cdll.LoadLibrary('libAquesTalk2Eva.so')
|
||||||
|
|
||||||
|
print('libAquesTalk2Eva: OK')
|
||||||
|
PY
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 10. PulseAudio
|
||||||
|
|
||||||
|
directory:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p /etc/nizika/pulse
|
||||||
|
|
||||||
|
chmod 755 \
|
||||||
|
/etc/nizika \
|
||||||
|
/etc/nizika/pulse
|
||||||
|
```
|
||||||
|
|
||||||
|
以下を作成:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/etc/nizika/pulse/default.pa
|
||||||
|
```
|
||||||
|
|
||||||
|
内容:
|
||||||
|
|
||||||
|
```text
|
||||||
|
#!/usr/bin/pulseaudio -nF
|
||||||
|
|
||||||
|
load-module module-native-protocol-unix
|
||||||
|
load-module module-device-restore
|
||||||
|
load-module module-stream-restore
|
||||||
|
load-module module-card-restore
|
||||||
|
load-module module-augment-properties
|
||||||
|
load-module module-default-device-restore
|
||||||
|
load-module module-always-sink
|
||||||
|
|
||||||
|
load-module module-null-sink sink_name=stream sink_properties=device.description=StreamSink
|
||||||
|
|
||||||
|
set-default-sink stream
|
||||||
|
set-default-source stream.monitor
|
||||||
|
```
|
||||||
|
|
||||||
|
権限:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chmod 644 \
|
||||||
|
/etc/nizika/pulse/default.pa
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 11. pulseaudio-headless.service
|
||||||
|
|
||||||
|
作成:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/etc/systemd/system/pulseaudio-headless.service
|
||||||
|
```
|
||||||
|
|
||||||
|
内容:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[Unit]
|
||||||
|
Description=Nizika virtual audio
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=nizika
|
||||||
|
Group=nizika
|
||||||
|
|
||||||
|
Environment=HOME=/var/lib/nizika
|
||||||
|
Environment=XDG_RUNTIME_DIR=/run/nizika
|
||||||
|
Environment=PULSE_SERVER=unix:/run/nizika/pulse/native
|
||||||
|
|
||||||
|
RuntimeDirectory=nizika
|
||||||
|
RuntimeDirectoryMode=0700
|
||||||
|
|
||||||
|
ExecStart=/usr/bin/pulseaudio \
|
||||||
|
--daemonize=no \
|
||||||
|
--exit-idle-time=-1 \
|
||||||
|
--log-target=journal \
|
||||||
|
-nF /etc/nizika/pulse/default.pa
|
||||||
|
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=2
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
```
|
||||||
|
|
||||||
|
反映:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
systemctl enable \
|
||||||
|
pulseaudio-headless.service
|
||||||
|
|
||||||
|
systemctl start \
|
||||||
|
pulseaudio-headless.service
|
||||||
|
```
|
||||||
|
|
||||||
|
確認:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl --no-pager --full status \
|
||||||
|
pulseaudio-headless.service
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 12. PulseAudio device 確認
|
||||||
|
|
||||||
|
sink:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
runuser -u nizika -- env \
|
||||||
|
HOME=/var/lib/nizika \
|
||||||
|
XDG_RUNTIME_DIR=/run/nizika \
|
||||||
|
PULSE_SERVER=unix:/run/nizika/pulse/native \
|
||||||
|
pactl list short sinks
|
||||||
|
```
|
||||||
|
|
||||||
|
期待:
|
||||||
|
|
||||||
|
```text
|
||||||
|
stream
|
||||||
|
```
|
||||||
|
|
||||||
|
source:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
runuser -u nizika -- env \
|
||||||
|
HOME=/var/lib/nizika \
|
||||||
|
XDG_RUNTIME_DIR=/run/nizika \
|
||||||
|
PULSE_SERVER=unix:/run/nizika/pulse/native \
|
||||||
|
pactl list short sources
|
||||||
|
```
|
||||||
|
|
||||||
|
期待:
|
||||||
|
|
||||||
|
```text
|
||||||
|
stream.monitor
|
||||||
|
```
|
||||||
|
|
||||||
|
headless 環境では PulseAudio が cookie や D-Bus 警告を表示する場合がある。
|
||||||
|
|
||||||
|
service が `active` で、`pactl` から `stream` と `stream.monitor` が取得できていれば、この構成では致命的ではない。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 13. Xvfb
|
||||||
|
|
||||||
|
作成:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/etc/systemd/system/xvfb.service
|
||||||
|
```
|
||||||
|
|
||||||
|
内容:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[Unit]
|
||||||
|
Description=Nizika virtual display
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=nizika
|
||||||
|
Group=nizika
|
||||||
|
|
||||||
|
Environment=HOME=/var/lib/nizika
|
||||||
|
|
||||||
|
ExecStart=/usr/bin/Xvfb \
|
||||||
|
:99 \
|
||||||
|
-screen 0 480x360x16 \
|
||||||
|
-nolisten tcp \
|
||||||
|
-noreset \
|
||||||
|
-dpi 96 \
|
||||||
|
-extension RANDR \
|
||||||
|
-extension RENDER \
|
||||||
|
-extension DAMAGE \
|
||||||
|
-extension COMPOSITE \
|
||||||
|
-extension GLX
|
||||||
|
|
||||||
|
Restart=always
|
||||||
|
RestartSec=1
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
```
|
||||||
|
|
||||||
|
反映:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
systemctl enable \
|
||||||
|
xvfb.service
|
||||||
|
|
||||||
|
systemctl start \
|
||||||
|
xvfb.service
|
||||||
|
```
|
||||||
|
|
||||||
|
確認:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl --no-pager --full status \
|
||||||
|
xvfb.service
|
||||||
|
```
|
||||||
|
|
||||||
|
この設定では RANDR を無効化しているため:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Xlib: extension "RANDR" missing on display ":99".
|
||||||
|
```
|
||||||
|
|
||||||
|
という warning が出る場合がある。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 14. broadcast environment
|
||||||
|
|
||||||
|
作成:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/etc/nizika-broadcast.env
|
||||||
|
```
|
||||||
|
|
||||||
|
内容:
|
||||||
|
|
||||||
|
```dotenv
|
||||||
|
NIZIKA_AI_MYSQL_USER=...
|
||||||
|
NIZIKA_AI_MYSQL_PASS=...
|
||||||
|
|
||||||
|
NIZIKA_NICO_MYSQL_USER=...
|
||||||
|
NIZIKA_NICO_MYSQL_PASS=...
|
||||||
|
|
||||||
|
NIZIKA_NICO_DIR=/opt/nizika-nico
|
||||||
|
|
||||||
|
BROADCAST_CODE=...
|
||||||
|
|
||||||
|
LD_LIBRARY_PATH=/usr/local/lib
|
||||||
|
```
|
||||||
|
|
||||||
|
権限:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chown root:root \
|
||||||
|
/etc/nizika-broadcast.env
|
||||||
|
|
||||||
|
chmod 600 \
|
||||||
|
/etc/nizika-broadcast.env
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 15. foreground smoke test
|
||||||
|
|
||||||
|
systemd 化する前に確認する。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /opt/nizika_broadcast
|
||||||
|
|
||||||
|
set -a
|
||||||
|
. /etc/nizika-broadcast.env
|
||||||
|
|
||||||
|
export HOME=/var/lib/nizika
|
||||||
|
export DISPLAY=:99
|
||||||
|
export SDL_AUDIODRIVER=pulse
|
||||||
|
export XDG_RUNTIME_DIR=/run/nizika
|
||||||
|
export PULSE_SERVER=unix:/run/nizika/pulse/native
|
||||||
|
|
||||||
|
set +a
|
||||||
|
|
||||||
|
timeout 20s \
|
||||||
|
runuser -u nizika \
|
||||||
|
--preserve-environment \
|
||||||
|
-- \
|
||||||
|
python3 main.py
|
||||||
|
|
||||||
|
rc=$?
|
||||||
|
|
||||||
|
echo "exit=$rc"
|
||||||
|
```
|
||||||
|
|
||||||
|
期待:
|
||||||
|
|
||||||
|
```text
|
||||||
|
exit=124
|
||||||
|
```
|
||||||
|
|
||||||
|
`124` は application crash ではなく、20 秒後に `timeout` が終了させたことを意味する。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 16. nizika_broadcast.service
|
||||||
|
|
||||||
|
作成:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/etc/systemd/system/nizika_broadcast.service
|
||||||
|
```
|
||||||
|
|
||||||
|
内容:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[Unit]
|
||||||
|
Description=Deerjika Broadcasting System
|
||||||
|
|
||||||
|
After=network-online.target mysql.service pulseaudio-headless.service xvfb.service
|
||||||
|
|
||||||
|
Wants=network-online.target mysql.service
|
||||||
|
|
||||||
|
Requires=pulseaudio-headless.service xvfb.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
|
||||||
|
User=nizika
|
||||||
|
Group=nizika
|
||||||
|
|
||||||
|
WorkingDirectory=/opt/nizika_broadcast
|
||||||
|
|
||||||
|
EnvironmentFile=/etc/nizika-broadcast.env
|
||||||
|
|
||||||
|
Environment=HOME=/var/lib/nizika
|
||||||
|
Environment=DISPLAY=:99
|
||||||
|
Environment=SDL_AUDIODRIVER=pulse
|
||||||
|
Environment=XDG_RUNTIME_DIR=/run/nizika
|
||||||
|
Environment=PULSE_SERVER=unix:/run/nizika/pulse/native
|
||||||
|
|
||||||
|
ExecStartPre=/bin/bash -lc 'for i in {1..50}; do pactl list short sources | grep -Fq stream.monitor && exit 0; sleep 0.2; done; echo "stream.monitor not found" >&2; exit 1'
|
||||||
|
|
||||||
|
ExecStartPre=/bin/bash -lc 'for i in {1..50}; do test -S /tmp/.X11-unix/X99 && exit 0; sleep 0.2; done; echo "Xvfb :99 not ready" >&2; exit 1'
|
||||||
|
|
||||||
|
ExecStart=/usr/bin/python3 \
|
||||||
|
/opt/nizika_broadcast/main.py
|
||||||
|
|
||||||
|
Restart=always
|
||||||
|
RestartSec=2
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
```
|
||||||
|
|
||||||
|
反映:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
systemctl enable \
|
||||||
|
nizika_broadcast.service
|
||||||
|
|
||||||
|
systemctl start \
|
||||||
|
nizika_broadcast.service
|
||||||
|
```
|
||||||
|
|
||||||
|
確認:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl --no-pager --full status \
|
||||||
|
nizika_broadcast.service
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 17. YouTube stream key
|
||||||
|
|
||||||
|
stream key は source code や systemd unit へ直接記載しない。
|
||||||
|
|
||||||
|
作成:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/etc/nizika-stream.env
|
||||||
|
```
|
||||||
|
|
||||||
|
内容:
|
||||||
|
|
||||||
|
```dotenv
|
||||||
|
YOUTUBE_STREAM_KEY=...
|
||||||
|
```
|
||||||
|
|
||||||
|
権限:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chown root:root \
|
||||||
|
/etc/nizika-stream.env
|
||||||
|
|
||||||
|
chmod 600 \
|
||||||
|
/etc/nizika-stream.env
|
||||||
|
```
|
||||||
|
|
||||||
|
stream key をログや Wiki に記載しない。
|
||||||
|
|
||||||
|
漏洩した場合は古い key を無効化して新規発行する。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 18. ffmpeg systemd service
|
||||||
|
|
||||||
|
作成:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/etc/systemd/system/nizika.service
|
||||||
|
```
|
||||||
|
|
||||||
|
内容:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[Unit]
|
||||||
|
Description=Nizika YouTube Stream
|
||||||
|
|
||||||
|
After=network-online.target pulseaudio-headless.service xvfb.service nizika_broadcast.service
|
||||||
|
|
||||||
|
Wants=network-online.target
|
||||||
|
|
||||||
|
Requires=pulseaudio-headless.service xvfb.service nizika_broadcast.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
|
||||||
|
User=nizika
|
||||||
|
Group=nizika
|
||||||
|
|
||||||
|
WorkingDirectory=/opt/nizika_broadcast
|
||||||
|
|
||||||
|
EnvironmentFile=/etc/nizika-stream.env
|
||||||
|
|
||||||
|
Environment=HOME=/var/lib/nizika
|
||||||
|
Environment=DISPLAY=:99
|
||||||
|
Environment=XDG_RUNTIME_DIR=/run/nizika
|
||||||
|
Environment=PULSE_SERVER=unix:/run/nizika/pulse/native
|
||||||
|
|
||||||
|
ExecStartPre=/bin/bash -lc 'for i in {1..50}; do pactl list short sources | grep -Fq stream.monitor && exit 0; sleep 0.2; done; echo "stream.monitor not found" >&2; exit 1'
|
||||||
|
|
||||||
|
ExecStartPre=/bin/bash -lc 'for i in {1..50}; do test -S /tmp/.X11-unix/X99 && exit 0; sleep 0.2; done; echo "Xvfb :99 not ready" >&2; exit 1'
|
||||||
|
|
||||||
|
ExecStart=/usr/bin/ffmpeg \
|
||||||
|
-nostdin \
|
||||||
|
-f x11grab \
|
||||||
|
-video_size 480x360 \
|
||||||
|
-framerate 6 \
|
||||||
|
-draw_mouse 0 \
|
||||||
|
-i :99 \
|
||||||
|
-f pulse \
|
||||||
|
-i stream.monitor \
|
||||||
|
-c:v libx264 \
|
||||||
|
-preset ultrafast \
|
||||||
|
-pix_fmt yuv420p \
|
||||||
|
-b:v 100k \
|
||||||
|
-maxrate 100k \
|
||||||
|
-bufsize 200k \
|
||||||
|
-g 12 \
|
||||||
|
-r 6 \
|
||||||
|
-c:a aac \
|
||||||
|
-b:a 18k \
|
||||||
|
-ar 11025 \
|
||||||
|
-f flv \
|
||||||
|
rtmps://a.rtmps.youtube.com:443/live2/${YOUTUBE_STREAM_KEY}
|
||||||
|
|
||||||
|
Restart=always
|
||||||
|
RestartSec=5
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
```
|
||||||
|
|
||||||
|
反映:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
systemctl enable \
|
||||||
|
nizika.service
|
||||||
|
|
||||||
|
systemctl start \
|
||||||
|
nizika.service
|
||||||
|
```
|
||||||
|
|
||||||
|
確認:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl --no-pager --full status \
|
||||||
|
nizika.service
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 19. stream key と process list
|
||||||
|
|
||||||
|
ffmpeg の RTMPS URL は process argv に含まれる。
|
||||||
|
|
||||||
|
したがって:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl status nizika.service
|
||||||
|
```
|
||||||
|
|
||||||
|
や:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ps
|
||||||
|
```
|
||||||
|
|
||||||
|
の出力に stream key が表示される場合がある。
|
||||||
|
|
||||||
|
外部へログを共有する際は必ず stream key を伏せる。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 20. 全 service 確認
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl --no-pager --full status \
|
||||||
|
pulseaudio-headless.service \
|
||||||
|
xvfb.service \
|
||||||
|
nizika_broadcast.service \
|
||||||
|
nizika.service
|
||||||
|
```
|
||||||
|
|
||||||
|
すべて:
|
||||||
|
|
||||||
|
```text
|
||||||
|
active (running)
|
||||||
|
```
|
||||||
|
|
||||||
|
であることを確認する。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 21. 自動起動
|
||||||
|
|
||||||
|
確認:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl is-enabled \
|
||||||
|
pulseaudio-headless.service \
|
||||||
|
xvfb.service \
|
||||||
|
nizika_broadcast.service \
|
||||||
|
nizika.service
|
||||||
|
```
|
||||||
|
|
||||||
|
すべて:
|
||||||
|
|
||||||
|
```text
|
||||||
|
enabled
|
||||||
|
```
|
||||||
|
|
||||||
|
であれば、通常の reboot 後に systemd が自動起動する。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 22. reboot test
|
||||||
|
|
||||||
|
最終的には一度再起動して確認する。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
reboot
|
||||||
|
```
|
||||||
|
|
||||||
|
再ログイン後:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl is-active \
|
||||||
|
pulseaudio-headless.service \
|
||||||
|
xvfb.service \
|
||||||
|
nizika_broadcast.service \
|
||||||
|
nizika.service
|
||||||
|
```
|
||||||
|
|
||||||
|
すべて:
|
||||||
|
|
||||||
|
```text
|
||||||
|
active
|
||||||
|
```
|
||||||
|
|
||||||
|
が目標。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 23. nullsink.service
|
||||||
|
|
||||||
|
旧環境で使用していた:
|
||||||
|
|
||||||
|
```text
|
||||||
|
nullsink.service
|
||||||
|
```
|
||||||
|
|
||||||
|
は移行しない。
|
||||||
|
|
||||||
|
PulseAudio の:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/etc/nizika/pulse/default.pa
|
||||||
|
```
|
||||||
|
|
||||||
|
内で:
|
||||||
|
|
||||||
|
```text
|
||||||
|
load-module module-null-sink sink_name=stream
|
||||||
|
```
|
||||||
|
|
||||||
|
を実行しているため、独立した null sink 用 service は不要。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 24. 関連 repository
|
||||||
|
|
||||||
|
## nizika_ai
|
||||||
|
|
||||||
|
AI 関連処理と `nizika_ai` DB を利用する。
|
||||||
|
|
||||||
|
environment variable:
|
||||||
|
|
||||||
|
```text
|
||||||
|
NIZIKA_AI_MYSQL_USER
|
||||||
|
NIZIKA_AI_MYSQL_PASS
|
||||||
|
```
|
||||||
|
|
||||||
|
## nizika_nico
|
||||||
|
|
||||||
|
共通処理や DB を利用する。
|
||||||
|
|
||||||
|
配置:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/opt/nizika-nico
|
||||||
|
```
|
||||||
|
|
||||||
|
environment variable:
|
||||||
|
|
||||||
|
```text
|
||||||
|
NIZIKA_NICO_MYSQL_USER
|
||||||
|
NIZIKA_NICO_MYSQL_PASS
|
||||||
|
NIZIKA_NICO_DIR
|
||||||
|
```
|
||||||
新しいイシューから参照
ユーザーをブロックする