#author("2025-12-31T06:12:18+00:00","","")
#author("2026-07-02T03:05:26+00:00","","")
#contents();
** mirakurun (Tuner Server) のインストール [#ndceae01]
*** Docker のインストール [#c6218575]
- Docker / Compose をインストール(Ubuntu公式推奨のDocker公式リポジトリ)
 sudo apt update
 sudo apt install -y ca-certificates curl gnupg
 
 sudo install -m 0755 -d /etc/apt/keyrings
 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
 sudo chmod a+r /etc/apt/keyrings/docker.gpg
 
 echo \
   "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
   $(. /etc/os-release && echo ${UBUNTU_CODENAME}) stable" \
 | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
 
 sudo apt update
 sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

- sudo なしで docker を使うための設定
 sudo usermod -aG docker $USER
 newgrp docker

- 動作確認
 [KGB2] munakata:~$  docker run --rm hello-world
 Unable to find image 'hello-world:latest' locally
 latest: Pulling from library/hello-world
 17eec7bbc9d7: Pull complete 
 ea52d2000f90: Download complete 
 Digest: sha256:d4aaab6242e0cace87e2ec17a2ed3d779d18fbfd03042ea58f2995626396a274
 Status: Downloaded newer image for hello-world:latest
 
 Hello from Docker!
 This message shows that your installation appears to be working correctly.
 
 To generate this message, Docker took the following steps:
  1. The Docker client contacted the Docker daemon.
  2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64)
  3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading.
  4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal.
 
 To try something more ambitious, you can run an Ubuntu container with:
  $ docker run -it ubuntu bash
 
 Share images, automate workflows, and more with a free Docker ID:
  https://hub.docker.com/
 
 For more examples and ideas, visit:
  https://docs.docker.com/get-started/
 
 [KGB2] munakata:~$ docker compose version
 Docker Compose version v5.0.0

*** [[Mirakurun:https://github.com/Chinachu/Mirakurun]][#z6162651]
- [[プラットフォーム / 環境構築手順 ガイド(公式):https://github.com/Chinachu/Mirakurun/blob/master/doc/Platforms.ja.md]]
- [[Setup ガイド(公式):https://github.com/Chinachu/Mirakurun/blob/master/doc/Configuration.ja.md]]
- カードリーダーの存在確認 [#s281615b]
 [KGB2] munakata:~$ lsusb
 Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
 Bus 001 Device 002: ID 04ca:004f Lite-On Technology Corp. SK-9020 keyboard
 Bus 001 Device 003: ID 05e3:0610 Genesys Logic, Inc. Hub
 Bus 001 Device 004: ID 26ce:01a2 ASRock LED Controller
 Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
 Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
 Bus 003 Device 002: ID 174c:2074 ASMedia Technology Inc. ASM1074 High-Speed hub
 Bus 003 Device 003: ID 051d:0002 American Power Conversion Uninterruptible Power Supply
 Bus 003 Device 004: ID 04e6:5116 SCM Microsystems, Inc. SCR331-LC1 / SCR3310 SmartCard Reader <---- Card Reader
 Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
 Bus 004 Device 002: ID 174c:3074 ASMedia Technology Inc. ASM1074 SuperSpeed hub
 Bus 005 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
 Bus 006 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub

- チューナの存在確認 (PT3 は /dev/dvb デバイスとして自動認識される)
 [KGB2] munakata:~$ ls -l /dev/dvb/
 total 0
 drwxr-xr-x 2 root root 100 12月 28 07:32 adapter0
 drwxr-xr-x 2 root root 100 12月 28 07:32 adapter1
 drwxr-xr-x 2 root root 100 12月 28 07:32 adapter2
 drwxr-xr-x 2 root root 100 12月 28 07:32 adapter3
 drwxr-xr-x 2 root root 100 12月 28 07:32 adapter4
 drwxr-xr-x 2 root root 100 12月 28 07:32 adapter5
 drwxr-xr-x 2 root root 100 12月 28 07:32 adapter6
 drwxr-xr-x 2 root root 100 12月 28 07:32 adapter7

- 既存の docker-compose.yml を利用(場所は munakata/mirakurun ) ---> &ref(docker-compose.yml);
 [KGB2] munakata:~/mirakurun$ cat docker-compose.yml
 services:
   mirakurun:
     # `:latest` can be changed to fix the version
     # `:latest` の部分を編集するとバージョンを固定できます
     # available tags: https://hub.docker.com/r/chinachu/mirakurun/tags
     #image: chinachu/mirakurun:latest
     image: chinachu/mirakurun:3.9.0-rc.4
     container_name: mirakurun
     cap_add:
       - SYS_ADMIN
       - SYS_NICE
     environment:
       TZ: Asia/Tokyo
       # comment out below if you commented out `network_mode: host`
       # `network_mode: host` をコメントアウトする場合はここもコメントアウト
       DOCKER_NETWORK: host
       # you must set hostname if accesing by hostname (other than IP address)
       # ブラウザから IP アドレス以外でアクセスする場合はホスト名を設定する必要があります
       # hostname: localhost
       # --
       # for debug
       # LOG_LEVEL: "3"
       # DEBUG: "true"
     network_mode: host
     # comment out `devices:` if you commented out all devices
     # `devices` を全てコメントアウトした場合は `devices:` もコメントアウト
     devices:
       # comment out below if you don't use card readers
       # カードリーダーを使わない場合は以下をコメントアウト
       - /dev/bus:/dev/bus
       # comment out below if you don't use DVB devices
       # DVB チューナーを使わない場合は以下をコメントアウト
       - /dev/dvb:/dev/dvb
     volumes:
       # you can change to any location if you want.
       - /opt/mirakurun/run:/var/run
       - /opt/mirakurun/opt:/opt
       - /opt/mirakurun/config:/app-config
       - /opt/mirakurun/data:/app-data
     tmpfs:
       - /tmp
     restart: always
     logging:
       driver: json-file
       options:
         max-file: "1"
         max-size: 10m

- mirakurunディレクトリを /opt 以下に作成する
 [KGB2] munakata:~$ sudo mkdir -p /opt/mirakurun/{run,opt,config,data}
 
 [KGB2] munakata:~$ cd /opt/mirakurun/
 [KGB2] munakata:/opt/mirakurun$ ls -l
 total 16
 drwxr-xr-x 2 root root 4096 12月 25 10:43 config
 drwxr-xr-x 3 root root 4096 12月 25 11:15 data
 drwxr-xr-x 4 root root 4096 12月 25 10:43 opt
 drwxr-xr-x 3 root root 4096 12月 28 07:32 run

- &ref(tuners.yml,center,tuners.yml); を /opt/mirakurun/config の下に配置する
 [KGB2] munakata:/opt/mirakurun$ cd config/
 [KGB2] munakata:/opt/mirakurun/config$ ls -l
 total 12
 -rw-r--r-- 1 munakata munakata 2538  8月 11  2024 channels.yml
 -rw-rw-r-- 1 root     root      278 12月 25 10:43 server.yml
 -rw-r--r-- 1 root     root     1796 12月 25 11:00 tuners.yml
 
 [KGB2] munakata:/opt/mirakurun/config$ head tuners.yml 
 - name: adapter0
   types:
     - BS
     - CS
   dvbDevicePath: /dev/dvb/adapter0/dvr0
   decoder: arib-b25-stream-test
   command: >-
     dvbv5-zap -a 0 -c ./config/dvbconf-for-isdb/conf/dvbv5_channels_isdbs.conf
     -r -P <channel>
 - name: adapter1

- latest のイメージダウンロードが失敗するので mirakurun/docker-compose.yml を編集して latest ではなく明示的に image: chinachu/mirakurun:3.9.0-rc.4 と指定する
 [KGB2] munakata:~/mirakurun$ docker compose down 2>/dev/null || true
 [KGB2] munakata:~/mirakurun$ docker image rm -f chinachu/mirakurun:latest 2>/dev/null || true
 [KGB2] munakata:~/mirakurun$ docker image rm -f chinachu/mirakurun:3.9.0-rc.4 2>/dev/null || true
 
 [KGB2] munakata:~/mirakurun$ sudo systemctl stop docker containerd
 [KGB2] munakata:~/mirakurun$ sudo rm -rf /var/lib/docker/containerd
 [KGB2] munakata:~/mirakurun$ sudo systemctl start containerd docker
 
 [KGB2] munakata:~/mirakurun$ docker compose pull

- &color(red){Docker 化された mirakurun をマニュアル起動};  
 [KGB2] munakata:~$ cd ~/mirakurun
 [KGB2] munakata:~/mirakurun$ docker compose up -d
 [KGB2] munakata:~/mirakurun$ docker compose ps
 [KGB2] munakata:~/mirakurun$ docker logs -n 200 mirakurun

- &color(red){Docker 化された mirakurun をマニュアル再起動};  
 [KGB2] munakata:~/mirakurun$ cd ~/mirakurun
 [KGB2] munakata:~/mirakurun$ docker compose restart

- 起動確認(コマンドライン)
 [KGB2] munakata:~/mirakurun$ curl -sSf http://127.0.0.1:40772/api/version
 {"current":"3.9.0-rc.4","latest":"4.0.0-beta.18"}

- 起動確認(ブラウザ)
-- http://<サーバIP>:40772/

*** mirakurun を ststemd のサービスに登録し、サーバー再起動時に自動起動できるようにする [#r621e6ab]
- compose一式を自動起動させる systemd (/etc/systemd/system/&color(red){mirakurun-compose.service};) を登録 ---> &ref(mirakurun-compose.service);
 [Unit]
 Description=Mirakurun (docker compose)
 Requires=docker.service
 After=docker.service network-online.target
 Wants=network-online.target
 
 [Service]
 Type=oneshot
 WorkingDirectory=/raid_vol/home/munakata/mirakurun
 ExecStart=/usr/bin/docker compose up -d
 ExecStop=/usr/bin/docker compose down
 RemainAfterExit=yes
 TimeoutStartSec=0
 
 [Install]
 WantedBy=multi-user.target  

- サービスの登録と自動起動設定
 [KGB2] munakata:~$ sudo systemctl daemon-reload
 [KGB2] munakata:~$ sudo systemctl enable --now mirakurun-compose.service

- サービスのマニュアル起動
 [KGB2] munakata:~$ sudo systemctl status mirakurun-compose.service --no-pager

- サーバーを再起動し自動起動したことを確認
 [KGB2] munakata:~$ systemctl status mirakurun-compose.service 
 ● mirakurun-compose.service - Mirakurun (docker compose)
      Loaded: loaded (/etc/systemd/system/mirakurun-compose.service; enabled; preset: enabled)
      Active: active (exited) since Sun 2025-12-28 07:32:31 JST; 2 days ago
     Process: 1892 ExecStart=/usr/bin/docker compose up -d (code=exited, status=0/SUCCESS)
    Main PID: 1892 (code=exited, status=0/SUCCESS)
         CPU: 76ms
 
 12月 28 07:32:31 kgb2 systemd[1]: Starting mirakurun-compose.service - Mirakurun (docker compose)...
 12月 28 07:32:31 kgb2 docker[1915]:  Container mirakurun Creating
 12月 28 07:32:31 kgb2 docker[1915]:  Container mirakurun Created
 12月 28 07:32:31 kgb2 docker[1915]:  Container mirakurun Starting
 12月 28 07:32:31 kgb2 docker[1915]:  Container mirakurun Started
 12月 28 07:32:31 kgb2 systemd[1]: Finished mirakurun-compose.service - Mirakurun (docker compose).

** [[EPGStation:https://github.com/l3tnun/EPGStation]][#d3ec5b0a]
*** [[インストール手順(公式):https://github.com/l3tnun/EPGStation/blob/master/doc/linux-setup.md]] [#fa89c617]
- EPGStation のインストール場所:&color(red){munakata/git/EPGStation};
- config/config.yml(または config.yml)で mirakurun へのパスを確認
 mirakurunPath: http://127.0.0.1:40772/

*** pm2 をユーザー環境にインストール [#k02f9796]
- 今回は &color(red){非sudo 環境で EPGStation を起動}; する(pm2はユーザー環境とsudo環境が別になっている)
 [KGB2] munakata:~$ npm install -g pm2
 
 [KGB2] munakata:~$ pm2 -v
 6.0.14

*** EPGStation のマニュアル起動/停止/再起動 [#xff33324]
- &color(red){EPGStation のマニュアル起動};
 [KGB2] munakata:~$ cd git/EPGStation/
 [KGB2] munakata:~/git/EPGStation$ sudo pm2 start dist/index.js --name epgstation

- EPGStation 起動状態の確認
 [KGB2] munakata:~$ pm2 status
-- &ref(pm2-status.png);

- EPGStation の停止、再起動
 [KGB2] munakata:~/git/EPGStation$ pm2 stop epgstations
 [KGB2] munakata:~/git/EPGStation$ pm2 restart epgstation

*** 自動起動の設定 [#n86d8aa9]
 [KGB2] munakata:~$ pm2 save

** [[削除できなくなったファイルのDBからの強制削除:https://chatgpt.com/c/6a45c554-6ecc-83e8-8faa-49979c0de437#:~:text=%E3%81%BE%E3%81%9A%E3%81%93%E3%82%8C%E3%82%92%E7%A2%BA%E8%AA%8D,%E3%81%A0%E3%81%91%E3%81%A7%E3%82%88%E3%81%84%E3%81%A7%E3%81%99%E3%80%82]] [#cfa82b9c]

まずこれを確認してください。

 sqlite3 data/database.db ".schema video_file"
 sqlite3 data/database.db ".schema thumbnail"
 sqlite3 data/database.db ".schema recorded_tags_recorded_tag"

録画一覧の検索はこの形です。

 sqlite3 -header -column data/database.db \
 "SELECT id, name, startAt, endAt, isRecording, isProtected, dropLogFileId
  FROM recorded
  WHERE name LIKE '%静岡県大井川港%'
  ORDER BY id DESC;"

recorded_history は startAt が無いので、こうです。

 sqlite3 -header -column data/database.db \
 "SELECT id, name, channelId, endAt
  FROM recorded_history
  WHERE name LIKE '%静岡県大井川港%'
  ORDER BY id DESC;"

録画ファイルとの関連は、おそらく video_file.recordedId です。確認後、たとえば recorded.id = 12345 なら:

 ID=12345
 
 sqlite3 -header -column data/database.db \
 "SELECT * FROM recorded WHERE id=$ID;"
 
 sqlite3 -header -column data/database.db \
 "SELECT * FROM video_file WHERE recordedId=$ID;"
 
 sqlite3 -header -column data/database.db \
 "SELECT * FROM thumbnail WHERE recordedId=$ID;"
 
 sqlite3 -header -column data/database.db \
 "SELECT * FROM recorded_tags_recorded_tag WHERE recordedId=$ID;"

削除する場合は、EPGStation停止・バックアップ後に関連テーブルから消します。

 pm2 stop epgstation
 cp -a data/database.db data/database.db.before-delete-$(date +%Y%m%d-%H%M)
 ID=12345
 
 sqlite3 data/database.db <<SQL
 BEGIN TRANSACTION;
 DELETE FROM thumbnail WHERE recordedId=$ID;
 DELETE FROM video_file WHERE recordedId=$ID;
 DELETE FROM recorded_tags_recorded_tag WHERE recordedId=$ID;
 DELETE FROM recorded WHERE id=$ID;
 COMMIT;
 SQL

recorded_history 側だけなら:

 HID=12345
 
 sqlite3 data/database.db <<SQL
 BEGIN TRANSACTION;
 DELETE FROM recorded_history WHERE id=$HID;
 COMMIT;
 SQL

最後に:

 sqlite3 data/database.db "PRAGMA integrity_check;"
 sqlite3 data/database.db "VACUUM;"
 pm2 resurrect

まずは .schema video_file の結果を見るのが次の一手です。

現状は録画ファイルは消せたのだが、記録だけが残っている状況です。 ID はどちらの値を使いますか?


 [KGB2] munakata:~/git/EPGStation$ sqlite3 data/database.db ".schema video_file"
 CREATE TABLE IF NOT EXISTS "video_file" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "parentDirectoryName" text NOT NULL, "filePath" text NOT NULL, "type"  text NOT NULL, "name" text NOT NULL, "size" bigint NOT NULL DEFAULT (0), "recordedId" integer NOT NULL, CONSTRAINT "FK_8407bb2c2e9d927e8c1c694c6a8" FOREIGN KEY ("recordedId") REFERENCES "recorded" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION);
 
 
 [KGB2] munakata:~/git/EPGStation$ sqlite3 data/database.db ".schema thumbnail" 
 CREATE TABLE IF NOT EXISTS "thumbnail" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "filePath" text NOT NULL, "recordedId" integer NOT NULL, CONSTRAINT "FK_f3e8be49269b5878c0f07ee0198" FOREIGN KEY ("recordedId") REFERENCES "recorded" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION);
 
 
 [KGB2] munakata:~/git/EPGStation$ sqlite3 data/database.db ".schema recorded_tags_recorded_tag"
 CREATE TABLE IF NOT EXISTS "recorded_tags_recorded_tag" ("recordedId" integer NOT NULL, "recordedTagId" integer NOT NULL, CONSTRAINT "FK_4bf93992f2a6020b74bbf80cf4c" FOREIGN KEY ("recordedId") REFERENCES "recorded" ("id") ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT "FK_c5315b388628971c92d241be9c8" FOREIGN KEY ("recordedTagId") REFERENCES "recorded_tag" ("id") ON DELETE CASCADE ON UPDATE CASCADE, PRIMARY KEY ("recordedId",  "recordedTagId"));
 CREATE INDEX "IDX_c5315b388628971c92d241be9c" ON "recorded_tags_recorded_tag" ("recordedTagId") ;
 CREATE INDEX "IDX_4bf93992f2a6020b74bbf80cf4" ON "recorded_tags_recorded_tag" ("recordedId") ;
 
 [KGB2] munakata:~/git/EPGStation$ sqlite3 -header -column data/database.db \
 "SELECT id, name, startAt, endAt, isRecording, isProtected, dropLogFileId
  FROM recorded
  WHERE name LIKE '%静岡県大井川港%'
  ORDER BY id DESC;"
 id    name                                    startAt        endAt          isRecording  isProtected  dropLogFileId
 ----  --------------------------------------  -------------  -------------  -----------  -----------  -------------
 3024  [字]魚が食べたい! 「静岡県大井川港で深海の幻のエビとアカムツ漁に密着!」  1743595200000  1743598440000  0            0
 
 [KGB2] munakata:~/git/EPGStation$
 [KGB2] munakata:~/git/EPGStation$ sqlite3 -header -column data/database.db \
 "SELECT id, name, channelId, endAt
  FROM recorded_history
  WHERE name LIKE '%静岡県大井川港%'
  ORDER BY id DESC;"
 id    name                                 channelId  endAt
 ----  -----------------------------------  ---------  -------------
 6020  魚が食べたい! 「静岡県大井川港で深海の幻のエビとアカムツ漁に密着!」  400151     1775890440000
 
 [KGB2] munakata:~/git/EPGStation$
 

使うIDは目的で分かれます。

Web画面の「録画済み一覧」に残って消せない記録なら、使うのは:

recorded.id = 3024

録画履歴・重複防止用の履歴だけを消すなら:

recorded_history.id = 6020

今回の「録画ファイルは消せたが記録だけ残っている」は、まず recorded.id=3024 側を削除するのが本命です。

停止・バックアップ後に実行してください。

 cd /raid_vol/home/munakata/git/EPGStation
 
 pm2 stop epgstation
 cp -a data/database.db data/database.db.before-delete-3024-$(date +%Y%m%d-%H%M)
 sqlite3 data/database.db <<SQL
 BEGIN TRANSACTION;
 DELETE FROM thumbnail WHERE recordedId=3024;
 DELETE FROM video_file WHERE recordedId=3024;
 DELETE FROM recorded_tags_recorded_tag WHERE recordedId=3024;
 DELETE FROM recorded WHERE id=3024;
 COMMIT;
 SQL

確認:

 sqlite3 data/database.db "PRAGMA integrity_check;"
 sqlite3 -header -column data/database.db "SELECT id,name FROM recorded WHERE id=3024;"

必要なら履歴側も削除:

 sqlite3 data/database.db <<SQL
 BEGIN TRANSACTION;
 DELETE FROM recorded_history WHERE id=6020;
 COMMIT;
 SQL

再起動:

 pm2 resurrect

補足:recorded_history は再録画防止などに使われる履歴の可能性があるので、Web画面の残骸を消したいだけなら、まずは recorded 側の 3024 だけでよいです。

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS