LXDコンテナにKonomiTVセットアップ

VMの場合、チューナーはパススルーしてゲスト側で認識するため、ドライバはホスト側には不要でゲスト側でインストールすればよかったのですが、コンテナの場合はホストのリソースを共有するため、ホスト側で認識している必要があります。

コンテナVM
カーネルホストと共有独立
ドライバホスト側に必要VM側に必要
オーバーヘッド軽量重い
独立性低い高い

ホストにドライバを適用したら、認識しているか確認します。

sudo dmesg | grep -i dvb
sudo dmesg | grep -i isdbt
sudo dmesg | grep -i digibest

このチューナーデバイスをコンテナ側にパススルーする必要があります。今回はpx4_drvなどの専用ドライバ特有の形式デバイスの例です。まずホスト側で確認します。

ls /dev/isdb2056*

確認できたデバイスを、コンテナに対して追加します。

lsusb -v 2>/dev/null | grep -A2 "ISDBT2056"

または

ls /dev/bus/usb/001/002

LXDコンテナにUSBデバイスを追加

lxc config device add コンテナ名 usb-tuner usb \
  vendorid=<vendorid> \
  productid=<productid>

vendoridとproductidは以下で確認できます。

lsusb
# 例: Bus 001 Device 002: ID 0511:0045 N'Able Technologies ISDBT2056
#                            ^^^^:^^^^
#                         vendorid:productid
lxc config device add コンテナ名 isdb2056 unix-char \
  source=/dev/isdb2056video0 \
  path=/dev/isdb2056video0

dvbデバイスノードも追加(チューナーに必要)

# まずホスト側でdvbデバイスを確認
ls /dev/dvb/

dvbデバイスが見えた場合、コンテナに追加します。

lxc config device add コンテナ名 dvb unix-char \
  source=/dev/dvb/adapter0/frontend0 \
  path=/dev/dvb/adapter0/frontend0

adapter0以外にも複数あれば同様に追加が必要です。これはWeb画面でも設定出来ます。

フィールド
TypeUSB
Bus number001
Device number002
GID0のまま
Mode0660のまま
Product ID004b

先ほどのCustom deviceと同じ画面で、今度は以下のように設定します。

フィールド
TypeUnix Char
Path/dev/isdb2056video0
Source/dev/isdb2056video0

また、GPUをパススルーするには、GPU項目で「Attach GPU」をクリックして追加します。

Mirakurun、EDCB、KonomiTVをインストール

インストールスクリプトは、コンテナ内でrootとして実行してください。install_dtv.shとして保存し、実行権限を付けて実行します。

nano install_dtv.sh
chmod +x install_dtv.sh
sudo ./install_dtv.sh
#!/bin/bash
# =============================================================
# DTV環境セットアップスクリプト
# 対応環境: Ubuntu Desktop / LXDコンテナ (Ubuntu 25.10)
# 実行方法: sudo bash install_dtv.sh
# =============================================================
set -e

# root チェック
if [ "$(id -u)" -ne 0 ]; then
    echo "エラー: このスクリプトは root で実行してください。"
    echo "  sudo bash $0"
    exit 1
fi

# -------------------------------------------------------
# 実行環境の判定(LXD コンテナ / 通常 Ubuntu Desktop)
# -------------------------------------------------------
IS_LXD=false
if systemd-detect-virt --container 2>/dev/null | grep -qi lxc; then
    IS_LXD=true
fi
echo "実行環境: $([ "$IS_LXD" = true ] && echo 'LXDコンテナ' || echo 'Ubuntu Desktop/VM')"

# 作業ユーザーの特定
REAL_USER="${SUDO_USER:-$(logname 2>/dev/null || id -un)}"
REAL_HOME=$(getent passwd "$REAL_USER" | cut -d: -f6)
DTV_DIR="$REAL_HOME/dtv"

echo "作業ユーザー: $REAL_USER  ホーム: $REAL_HOME"

# ============================================================
# 0. キー入力
# ============================================================
echo "=== 1/8: キー設定 ==="
echo "キーの内容を貼り付けてください(入力後、Enter を 2 回押すと確定します):"
BCAS_CONTENT=$(sed '/^$/q')

# ============================================================
# 1. 依存パッケージのインストール
# ============================================================
echo "=== 2/8: 依存パッケージをインストール中 ==="
apt update
apt install -y \
    autoconf automake cmake libtool libpcsclite-dev \
    git build-essential pkg-config curl wget \
    libclang-dev libdvbv5-dev libudev-dev \
    nodejs npm ffmpeg liblua5.2-dev lua-zlib g++ make gcc

# ============================================================
# Node.js 18 のセットアップ (nvm / root 用)
# ============================================================
# LXDコンテナでは sudo 経由だと nvm PATH が引き継がれないため
# root の nvm として直接インストールする
export NVM_DIR="/root/.nvm"
if [ ! -d "$NVM_DIR" ]; then
    curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
fi
# shellcheck source=/dev/null
source "$NVM_DIR/nvm.sh"
nvm install 18
nvm use 18
nvm alias default 18
NODE18_BIN=$(dirname "$(nvm which 18)")
export PATH="$NODE18_BIN:$PATH"
echo "Node.js バージョン確認: $(node -v)  npm: $(npm -v)"

npm install -g pm2 || true

# ============================================================
# 2. TVチューナードライバ (px4_drv / isdb2056)
# ============================================================
echo "=== 3/8: ドライバをセットアップ中 ==="
mkdir -p "$DTV_DIR" && cd "$DTV_DIR"

DRIVER_VERSION="0.5.5"
DRIVER_DEB="px4-drv-dkms_${DRIVER_VERSION}_all.deb"
[ ! -f "$DRIVER_DEB" ] && curl -L -o "$DRIVER_DEB" \
    "https://github.com/tsukumijima/px4_drv/releases/download/v${DRIVER_VERSION}/${DRIVER_DEB}"
# Desktop/VM: dkms でカーネルモジュールをビルド
# LXD: ホストからパススルーされるためインストール失敗しても正常
apt install -y "./${DRIVER_DEB}" || echo "警告: px4_drv dkms インストール失敗(LXDでは正常)"
modprobe px4_drv 2>/dev/null || echo "警告: px4_drv modprobe スキップ(LXDでは正常)"

# デバイスパーミッションを設定
echo "デバイスパーミッションを設定中..."
if [ "$IS_LXD" = true ]; then
    # LXD: udev が使えないため chmod を直接適用
    chmod 666 /dev/isdb2056video* 2>/dev/null && echo "isdb2056: OK" || echo "isdb2056: デバイスなし"
    chmod 666 /dev/px4video*      2>/dev/null && echo "px4video: OK"  || echo "px4video: デバイスなし"
else
    # Ubuntu Desktop/VM: udev ルールで永続化 + 即時反映
    tee /etc/udev/rules.d/99-dtv.rules > /dev/null <<'UDEV'
SUBSYSTEM=="usb", ATTRS{idVendor}=="0511", MODE="0666"
KERNEL=="isdb2056video*", MODE="0666", GROUP="video"
KERNEL=="px4video*",      MODE="0666", GROUP="video"
UDEV
    udevadm control --reload-rules
    udevadm trigger
    sleep 2
    chmod 666 /dev/isdb2056video* 2>/dev/null && echo "isdb2056: OK" || echo "isdb2056: デバイスなし"
    chmod 666 /dev/px4video*      2>/dev/null && echo "px4video: OK"  || echo "px4video: デバイスなし"
    # video グループに追加(次回ログイン以降に有効)
    usermod -aG video "$REAL_USER" || true
fi

# デバイスが1つも見つからない場合は警告(続行はする)
if ! ls /dev/isdb2056video* /dev/px4video* 2>/dev/null | grep -q .; then
    echo "警告: TVチューナーデバイスが見つかりません。"
    if [ "$IS_LXD" = true ]; then
        echo "  LXDのプロファイルでデバイスパススルーが設定されているか確認してください。"
        echo "  例: lxc config device add <container> isdb2056video0 unix-char path=/dev/isdb2056video0"
    else
        echo "  チューナーが正しく接続・認識されているか確認してください。"
    fi
fi

# ============================================================
# 3. libyakisoba / libsobacas のビルド
# ============================================================
echo "=== 4/8: 復号ライブラリのビルド ==="
cd "$DTV_DIR"
for repo in libyakisoba libsobacas; do
    [ ! -d "$repo" ] && git clone "https://github.com/tsunoda14/${repo}.git"
    cd "$repo"
    autoreconf -i
    mkdir -p build && cd build
    [ "$repo" = "libyakisoba" ] && ../configure --sysconfdir=/usr/local/etc || ../configure
    make -j"$(nproc)"
    make install
    cd "$DTV_DIR"
done
ldconfig

# ============================================================
# 4. recisdb のビルド
# ============================================================
echo "=== 5/8: Rust と recisdb のビルド ==="
# root の cargo 環境
export CARGO_HOME="/root/.cargo"
export RUSTUP_HOME="/root/.rustup"
if ! command -v cargo &>/dev/null; then
    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --no-modify-path
fi
source "$CARGO_HOME/env" 2>/dev/null || export PATH="$CARGO_HOME/bin:$PATH"

mkdir -p /usr/local/lib/pkgconfig
tee /usr/local/lib/pkgconfig/libsobacas.pc > /dev/null <<'EOF'
prefix=/usr/local
libdir=/usr/local/lib
includedir=/usr/include

Name: libsobacas
Description: PCSC compatible ECM decoder library
Version: 0.0.0
Libs: -L${libdir} -lsobacas
Cflags: -I${includedir}/PCSC
EOF

cd "$DTV_DIR"
[ ! -d recisdb-rs ] && git clone --recursive https://github.com/kazuki0824/recisdb-rs.git
cd recisdb-rs
sed -i 's/pcsclite/sobacas/g' b25-sys/build.rs
cargo build -F dvb --release
cp target/release/recisdb /usr/local/bin/

# ============================================================
# 5. B-CAS キーの配置
# ============================================================
mkdir -p /usr/local/etc
echo "$BCAS_CONTENT" | tee /usr/local/etc/bcas_keys > /dev/null

# ============================================================
# 6. チャンネルスキャンと Mirakurun 設定
# ============================================================
echo "=== 6/8: チャンネルスキャンと Mirakurun 設定 ==="
wget -q https://github.com/tsukumijima/ISDBScanner/releases/download/v1.3.3/isdb-scanner \
    -O /usr/local/bin/isdb-scanner
chmod +x /usr/local/bin/isdb-scanner

# mirakurun インストール(root + Node 18 環境)
npm install -g \
    --unsafe-perm \
    --foreground-scripts \
    --production \
    --ignore-engines \
    mirakurun@3.9.0-rc.4

# 設定ディレクトリを確実に作成
mkdir -p /usr/local/etc/mirakurun

mirakurun start || true
sleep 5
mirakurun stop  || true

# チャンネルスキャン(root 実行のためパーミッション問題なし)
mkdir -p "$DTV_DIR/scanned"
if [ -z "$(ls -A "$DTV_DIR/scanned/" 2>/dev/null)" ]; then
    isdb-scanner "$DTV_DIR/scanned/"
fi

# スキャン結果の確認
if [ ! -f "$DTV_DIR/scanned/Mirakurun/channels.yml" ]; then
    echo "エラー: チャンネルスキャンが完了しませんでした。"
    echo "デバイスのパススルー設定を確認してから再実行してください。"
    exit 1
fi

cp -a "$DTV_DIR/scanned/Mirakurun/channels.yml" /usr/local/etc/mirakurun/channels.yml
cp -a "$DTV_DIR/scanned/Mirakurun/tuners.yml"   /usr/local/etc/mirakurun/tuners.yml
chown -R root:root /usr/local/etc/mirakurun/
mirakurun start

# ============================================================
# 7. EDCB (EpgTimerSrv) のセットアップ
# ============================================================
echo "=== 7/8: EDCB セットアップ ==="
cd "$DTV_DIR"
[ ! -d EDCB ] && git clone https://github.com/xtne6f/EDCB
cd EDCB/Document/Unix
make -j"$(nproc)"
make install
make extra
make install_extra

mkdir -p /var/local/edcb
chown -R "$REAL_USER:$REAL_USER" /var/local/edcb
make setup_ini

# EMWUI
cd "$DTV_DIR"
[ ! -d EDCB_Material_WebUI ] && git clone https://github.com/EMWUI/EDCB_Material_WebUI
cp -r EDCB_Material_WebUI/HttpPublic /var/local/edcb/
cp -r EDCB_Material_WebUI/Setting    /var/local/edcb/

# BonDriver
[ ! -d BonDriver_LinuxMirakc ] && \
    git clone https://github.com/matching/BonDriver_LinuxMirakc.git --recurse-submodules
cd BonDriver_LinuxMirakc
make -j"$(nproc)"
cp BonDriver_LinuxMirakc.so     /usr/local/lib/edcb/
cp BonDriver_LinuxMirakc.so.ini_sample /usr/local/lib/edcb/BonDriver_LinuxMirakc.so.ini

# チャンネル設定をコピー
cp "$DTV_DIR/scanned/EDCB-Wine/ChSet5.txt" /var/local/edcb/Setting/
cp "$DTV_DIR/scanned/EDCB-Wine/BonDriver_mirakc(BonDriver_mirakc).ChSet4.txt" \
   '/var/local/edcb/Setting/BonDriver_LinuxMirakc(LinuxMirakc).ChSet4.txt'

# WebUI 設定
sed -i 's/^ALLOW_SETTING=.*/ALLOW_SETTING=true/' /var/local/edcb/HttpPublic/legacy/util.lua
mkdir -p /var/local/edcb/HttpPublic/video

# チューナー数を自動検出
ISDB_DEV_COUNT=$(ls /dev/isdb2056video* 2>/dev/null | wc -l)
PX4_DEV_COUNT=$(ls /dev/px4video*       2>/dev/null | wc -l)
if [ "$ISDB_DEV_COUNT" -gt 0 ]; then
    # e-better DTV02A-1T1S-U: 1デバイス = 1チューナー
    TUNER_COUNT=$ISDB_DEV_COUNT
elif [ "$PX4_DEV_COUNT" -gt 0 ]; then
    # px4_drv: 物理1チューナーにつき4デバイス
    TUNER_COUNT=$(( PX4_DEV_COUNT / 4 ))
    [ "$TUNER_COUNT" -eq 0 ] && TUNER_COUNT=1
else
    TUNER_COUNT=$(grep -c '^ *- name:' /usr/local/etc/mirakurun/tuners.yml 2>/dev/null || echo 1)
    [ "$TUNER_COUNT" -eq 0 ] && TUNER_COUNT=1
fi
echo "検出チューナー数: ${TUNER_COUNT}"

# EpgTimerSrv.ini
tee /var/local/edcb/EpgTimerSrv.ini > /dev/null <<EOT
[SET]
EnableHttpSrv=1
EnableTCPSrv=1
RecEndMode=0
Data=1
HttpAccessControlList=+127.0.0.0/8,+10.0.0.0/8,+172.16.0.0/12,+192.168.0.0/16,+169.254.0.0/16,+100.64.0.0/10
[TunerNum]
BonDriver_LinuxMirakc(LinuxMirakc).so=${TUNER_COUNT}
[BonDriver_LinuxMirakc.so]
Count=${TUNER_COUNT}
GetEpg=1
EPGCount=0
Priority=0
EOT

# Common.ini
tee /var/local/edcb/Common.ini > /dev/null <<'EOT'
[SET]
RecFolderPath0=/var/local/edcb/HttpPublic/video
RecFolderNum=1
EOT

# systemd 登録
tee /etc/systemd/system/edcb.service > /dev/null <<EOT
[Unit]
Description=EpgTimerSrv
After=network-online.target
[Service]
Type=simple
User=$REAL_USER
ExecStart=/usr/local/bin/EpgTimerSrv
Restart=always
[Install]
WantedBy=default.target
EOT

systemctl daemon-reload
systemctl enable edcb
systemctl start edcb

# ============================================================
# 8. KonomiTV インストール
# ============================================================
echo "=== 8/8: KonomiTV インストール ==="
cd "$DTV_DIR"
curl -LO https://github.com/tsukumijima/KonomiTV/releases/latest/download/KonomiTV-Installer.elf
chmod +x KonomiTV-Installer.elf
./KonomiTV-Installer.elf

KONOMI_CONFIG=$(find /opt /usr/local /home -name "config.yaml" -path "*/KonomiTV/*" 2>/dev/null | head -1)
if [ -z "$KONOMI_CONFIG" ]; then
    echo "警告: KonomiTV の config.yaml が見つかりませんでした。パスを確認してください。"
else
    echo "KonomiTV config.yaml を更新中: $KONOMI_CONFIG"
    sed -i 's/always_receive_tv_from_mirakurun: false/always_receive_tv_from_mirakurun: true/' "$KONOMI_CONFIG"
    pm2 restart KonomiTV
fi

echo "=== 環境構築が完了しました! ==="

ハードウェアエンコードが利用出来るかどうか確実ではない場合はいったんFFmpegにしておいたほうが無難でしょう。TVTestやEDCBの動作を確認したら切り替えてみて、切り替え出来るようなら利用可能です。

/home/user/KonomiTV
tcp://127.0.0.1:4510/
FFmpeg
/var/local/edcb/HttpPublic/video

インストールが終了したら、KonomiTVを立ち上げてみます。番組表などはまだ受信されていないので、EDCBにアクセスして、EPGを受信します。

http://IPアドレス:5510

EPGを取得します。これにはかなり時間がかかります。tmpファイルが無くなれば受信完了

ls /var/local/edcb/Setting/EpgData

EDCBの再起動は下記コマンドです。

sudo systemctl restart edcb