rokkonet

PC・Androidソフトウェア・アプリの開発・使い方に関するメモ

TV録画システムchinachuをDocker版mirakurunシステムにインストール

2021 Mar. 31.
2021 Feb. 20.
2021 Jan. 30.
2020 Dec. 31.

「PT2 + DVBブロックデバイス + DVB-Tools + Docker版mirakurun + chinachu」システム


chinachuインストール

Mirakurun稼働ユーザーでシステムにログインして作業を進める。ここではユーザー名をtvとする。

インストール作業
$ su - tv
$ sudo apt update && sudo apt install build-essential curl git-core vainfo
$ curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
$ sudo apt install -y nodejs
$ sudo npm install pm2 -g
$ sudo pm2 startup
$ git clone git://github.com/kanreisa/Chinachu.git ~/chinachu
$ cd ~/chinachu/

$ ./chinachu installer
1) Auto (full)   3)Node.js Environment   5)ffmpeg
2)submodule   4)Node.js Modules
what do you install? > 1 ## 1) Autoを指定する

空の設定ファイルを作成。config.jsonの元を作成
$ cd ~/chinachu/
$ echo [] > rules.json
$ cp config.sample.json config.json

~/chinachu/config.jsonを編集(二重引用符と行末のカンマに注意)

参考元 Gamma Configuration · Chinachu/Chinachu Wiki · GitHub

"uid": "<実行ユーザー名>",

"gid": "video",

"mirakurunPath": "http+unix://%2Fusr%2Flocal%2Fmirakurun%2Frun%2Fmirakurun.sock/",  # Docker版mirakurunのUNIX Socketのパスは/usr/local/mirakurun/run/mirakurun.sock (https://twitter.com/chinachu_rec/status/1278652540402298880)。ディレクトリ区切りの'/'は’%2F'で表現。'

"recordedDir" : "/var/tv/recorded/",  # 録画用ディレクトリ

"temporaryDir" : "/var/tv/recordtmp/",  # 作業用の ディレクトリ

"wuiOpenHost": "0.0.0.0",  ## wuiHostからwuiOpenHostに名前変更 

"recordedFormat": "<date:yyyymmddHHMM><type><channel>-<channel-sid>-<channel-name>-<title>.m2ts",  # キャプチャした番組のファイル名

"recordedCommand": "/FULL/PATH/chinachu/usr/bin/SHELL-SCRIPT_RUNNED_AFTER_RECORDING",  # 録画後に実行するシェルスクリプト

(録画ファイル名のフォーマット)
参考元
 chinachu-gamma_html
 PX-S1UDとChinachuを組み合わせる – 底辺迷走

<date:日付フォーマット>
    日時。dateformatが使われる。
<id>
    番組ID
<type>
    放送波の種類
<channel>
    チャンネル番号
<channel-id>
    チャンネルID(利用する必要なし)
<channel-sid>
    SID(serviceID)
<channel-name>
    チャンネル名
<tuner>
    チューナー名
<title>
    タイトル
<fulltitle>
    EPGで受信したタイトル
<subtitle>
    サブタイトル
<episode>
    話数
<category>
    ジャンル 
<type><channel><channel-sid>でチャンネルを特定できる

recordedCommandに指定するシェルスクリプトについて

参考元 Configuration recordedCommand · Chinachu/Chinachu Wiki · GitHub

シェルスクリプトは~/chinachu/usr/bin/ に置く(のが無難)。「PATHが通った~/bin/ 」「PATHの通っていない~/ 」に置いても機能した。
シェルスクリプトパーミッションはユーザー実行可能にしておく。
  chmod 700 SCRIPT.sh
・recordedCommandにはスクリプトをフルパスで指定する。config.json内では${HOME}変数は展開されない。
スクリプト内で$#の値は2。
・$0にはrecordedCommandに指定したスクリプトファイルのフルパスが入っている。
・$1には直前に録画したファイル名が入っている。
・$2には直前に録画した番組のデータ(~/chinachu/data/recorded.jsonの内容の直前番組分)が入っている。
スクリプト内で${HOME}は展開されなかったので、環境変数は無効となっている模様。

隠しディレクトリ)~/chinachu/.nave/installed/ 以下が空の場合はNode.jsのバイナリに向けてシンボリックリンクを作成しておく必要がある。
# node のシンボリックリンク先を確認
$ cd ~/chinachu/.nave
$ ls -la
> node -> /mnt/hdd1/chinachu/.nave/installed/10.16.3/bin/node
> npm -> /mnt/hdd1/chinachu/.nave/installed/10.16.3/bin/npm

# n でインストールした上記と一致するバージョンのnodeへのシンボリックリンクを作成
$ cd installed/
$ ln -s /usr/local/n/versions/node/10.16.3 10.16.3


LAN内に20772ポートを開放
$ sudo ufw enable
$ sudo ufw allow proto tcp from 192.168.1.0/24 to any port 20772
$ sudo ufw reload

OpenVPNクライアントからのアクセス許可
$ sudo ufw enable
$ sudo ufw allow proto tcp from 10.8.0.0/24 to any port 20772
$ sudo ufw reload


chinachuプロセス起動

参照元 
【RaspberryPi】PX-S1UDを使用する - uepon日々の備忘録
chinachuは2つのプロセスから構成されている
1つ目はEPGGUIを表示するWebサーバのプロセスchinachu-wui
2つ目は動画をキャプチャする録画制御用のプロセスchinachu-operator

EPGGUIを表示するWebサーバのプロセスchinachu-wuiの起動
$ cd ~/chinachu/
$ ./chinachu service wui execute
  
(画面出力)
~/chinachu$ ./chinachu service wui execute
Client {
  basePath: '/api',
  docsPath: '/docs',
  priority: 0,
  host: '',
  port: 40772,
  socketPath: '/var/run/mirakurun.sock',
  userAgent: 'Chinachu/0.10.3-gamma.0 (wui)',
  _userAgent: 'MirakurunClient/3.4.1 Node/v10.23.0 (linux)' }
31 Dec 20:08:59 - HTTP Open Server Listening on { address: '0.0.0.0', family: 'IPv4', port: 20772 }
31 Dec 20:08:59 - HTTP Open Server mDNS advertising started.
31 Dec 20:08:59 - READ: `/home/ryuichi-xubuntu2004/chinachu/rules.json` is updated.
31 Dec 20:08:59 - READ: `/home/ryuichi-xubuntu2004/chinachu/data/schedule.json` is updated.
31 Dec 20:08:59 - READ: `/home/ryuichi-xubuntu2004/chinachu/data/reserves.json` is updated.
31 Dec 20:08:59 - READ: `/home/ryuichi-xubuntu2004/chinachu/data/recording.json` is updated.
31 Dec 20:08:59 - READ: `/home/ryuichi-xubuntu2004/chinachu/data/recorded.json` is updated.

起動したら http://localhost:20772/ にアクセスして確認

 問題なく起動できたらCtl+cでプロセスを終了する

EPGデータの取得
$ cd ~/chinachu/
$ ./chinachu update
## mirakurunに接続しているとEPGデータを取得できる
## しばらくしてからプロセスを再起動
$ ./chinachu service wui execute
## http://localhost:20772/ にアクセスして番組表を確認し、Ctl+cでプロセスを終了する

動画をキャプチャする録画制御用のプロセスchinachu-operatorの起動

(chinachuはchinachu-wuiとchinachu-operatorの2つのプロセスで構成される)

$ cd ~/chinachu/
$ ./chinachu service operator execute
## 出力画面で起動確認して、Ctl+cでプロセスを終了する

ログファイル保管場所

/usr/local/var/log/chinachu-*

ログローテーション設定

 (参考元 Chinachu γ(ガンマ) インストール手順(CentOS 7編) | 自分に負けないラボラトリー
 pm2-logrotateをインストール

# pm2 install pm2-logrotate

 /etc/logrotate.d/chinachuを次の内容で作成

/usr/local/var/log/chinachu-operator.stderr.log
/usr/local/var/log/chinachu-operator.stdout.log
/usr/local/var/log/chinachu-wui.stderr.log
/usr/local/var/log/chinachu-wui.stdout.log
{
  weekly
  compress
  rotate 4
  missingok
  notifempty
}


インストールされたコマンドが保管されたディレクトリにパスを通す

~/.profileに次を追記する

if [ -d "${HOME}/chinachu/usr/bin" ] ; then
    PATH="${HOME}/chinachu/usr/bin:${PATH}"
fi


PC再起動時にchinachu自動起動する設定
pm2の稼働を確認
$ ps ax | grep pm2
    -> PM2 v4.5.1: God Daemon (/root/.pm2)
pm2が稼働していなければ
$ sudo pm2 startup
  
chinachuサービス開始
$ cd ~/chinachu/
$ sudo pm2 start processes.json
  
プロセス稼働状況確認
$ sudo pm2 status
 ->chinachu-wui、 chinachu-operatorの稼動を確認する
  
稼動していなければ
$ cd ~/chinachu/
$ ./chinachu service wui execute &
$ ./chinachu service operator execute &
  
稼動状態のプロセスリストを保存・スタートアップ登録
$ sudo pm2 save

chinachuの起動、終了、動作確認はすべてpm2で行う

[起動]

$ sudo pm2 start chinachu-wui
$ sudo pm2 start chinachu-operator


[再起動]

$ sudo pm2 restart chinachu-wui
$ sudo pm2 restart chinachu-operator


[停止]

$ sudo pm2 stop chinachu-wui
$ sudo pm2 stop chinachu-operator


稼働状況確認

$ sudo pm2 status

録画中のプロセス稼働状況
$ ps ax -f
root  13987  3179  0 17:44 ?  S<  0:00 dvbv5-zap -a 1 -c ./config/dvbconf-for-isdb/conf/dvbv5_channels_isdbt.conf -r -P 26
root  13988        2  0 17:44 ?  S    0:00 [kdvb-ad-1-fe-0]
root  13989  3179  1 17:44 ?  S<  0:03 cat /dev/dvb/adapter1/dvr0
root  13990        2  2 17:44 ?  S    0:06 [earth-pt1]
root  13991  3179  6 17:44 ?  S<  0:17 arib-b25-stream-test

録画済番組情報(タイトル、時刻等)が保管されているファイル

~/chinachu/data/recorded.json に保管されている

recorded.jsonの内容(jsonツールで整形したもの)

## jsonを解析するjqをインストール
$ sudo apt install jq

## 整形出力
$ cat ~/chinachu/data/recorded.json | jq .

## output
[
  {
    "id": "35qj0z387g",
    "category": "information",
    "title": "淡路島へ行こう!~ほっこり洲本温泉の旅~",
    "fullTitle": "淡路島へ行こう!~ほっこり洲本温泉の旅~",
    "detail": "",
    "start": 1610862900000,
    "end": 1610863200000,
    "seconds": 300,
    "channel": {
      "type": "GR",
      "channel": "26",
      "name": "サンテレビ1",
      "id": "1h2ccts",
      "sid": 43056,
      "nid": 32086,
      "hasLogoData": true,
      "n": 7
    },
    "subTitle": "",
    "episode": null,
    "flags": [],
    "isManualReserved": true,
    "isConflict": false,
    "priority": 2,
    "tuner": {
      "name": "Mirakurun (UnixSocket)",
      "command": "*",
      "isScrambling": false
    },
    "command": "mirakurun type=GR url=/api/programs/320864305610572/stream?decode=1 priority=2",
    "recorded": "/var/tv/recorded/2101171455GR26_43056_サンテレビ1淡路島へ行こう!~ほっこり洲本温泉の旅~.m2ts"
  },
  {
    "id": "37zmvybppr",
    "category": "documentary",
    "title": "Catch!!",
    "fullTitle": "Catch!![字]",
    "detail": "“手”には職業や人柄、生きざま全てが現れている。アスリート、職人、アーティスト、クリエイターなど頑張ってる人達の情熱や魅力を『Catch!!』\n◇おことわり\n番組の内容と放送時間は、変更になる場合があります。",
    "start": 1610889540000,
    "end": 1610889900000,
    "seconds": 360,
    "description": "“手”には職業や人柄、生きざま全てが現れている。アスリート、職人、アーティスト、クリエイターなど頑張ってる人達の情熱や魅力を『Catch!!』",
    "extra": {
      "おことわり": "番組の内容と放送時間は、変更になる場合があります。"
    },
    "channel": {
      "type": "GR",
      "channel": "16",
      "name": "MBS毎日放送",
      "id": "1i46n9s",
      "sid": 2064,
      "nid": 32722,
      "hasLogoData": false,
      "n": 10
    },
    "subTitle": "",
    "episode": null,
    "flags": [
      "字"
    ],
    "isManualReserved": true,
    "isConflict": false,
    "priority": 2,
    "tuner": {
      "name": "Mirakurun (UnixSocket)",
      "command": "*",
      "isScrambling": false
    },
    "command": "mirakurun type=GR url=/api/programs/327220206417135/stream?decode=1 priority=2",
    "recorded": "/var/tv/recorded/2101172219GR16_2064_MBS毎日放送Catch!!.m2ts"
  }
]
## 全情報出力
$ cat ~/chinachu/data/recorded.json | jq
$ cat ~/chinachu/data/recorded.json | jq '.[]'

## 全録画ファイル名出力(-rオプションでダブルクォート囲み無しで出力)
$ cat ~/chinachu/data/recorded.json | jq -r '.[].recorded'

## 先頭録画番組ファイル名出力
$ cat ~/chinachu/data/recorded.json | jq -r '.[0].recorded'

## 2番目の録画番組ファイル名出力
$ cat ~/chinachu/data/recorded.json | jq -r '.[1].recorded'

## 全録画番組タイトル出力
$ cat ~/chinachu/data/recorded.json | jq -r '.[].title'

## 全録画番組のファイルパス、タイトル、フルタイトル、内容detail、内容description出力
$ cat ~/chinachu/data/recorded.json | jq '.[] | .recorded, .title, .fullTitle, .detail, .description'

録画したFILE.m2tsをmp4に変換する

定期実行するスクリプトによって録画ファイルをmp4に変換し、chinachuの録画情報を更新する
  • 録画時に、録画ファイルパスと録画番組情報を特定の文字( __TAB__ とした)で区切られた1行のデータとしてmp4変換記録ファイルに保存する。
  • 定期的にmp4変換記録ファイルから録画ファイルパスと録画番組情報を読み込む。読み取った録画ファイルパスからmp4ファイルを作成し、録画番組情報からchinachuの録画情報を更新する。


~/chinachu/config.jsonのrecordedCommandに指定する、録画ファイルパスと録画番組情報をmp4変換記録ファイルに保存するスクリプト
chinachu-save_record_information-asRecordedCommand.sh

  • このスクリプトにユーザー実行属性を付けて、${HOME}/chinachu/usr/bin/ にあたりに保存する。
  • このスクリプトのフルパスを、${HOME}/chinachu/config.jsonのrecordedCommandに指定する。
  • ${HOME}/varディレクトリを作る
$ mkdir ~/var
$ chmod 700 ~/var

https://bitbucket.org/arsmus/shell-script-public/src/d238e7f8dcf5ba63c319b60c7571785c535478dd/audio-video/chinachu-save_record_information-asRecordedCommand.sh?at=master#chinachu-save_record_information-asRecordedCommand.sh-7:8,10,14:15,17,20,22:23,34:35,37:39,39,48,66,68,78:79


mp4変換記録ファイルからデータを読み込み、mp4ファイル作成、data/recorded.json更新を行うスクリプト
chinachu-m2ts2h264.sh

 Mp4fileDir=/FILEPATH/OF/CONVERTED/MP4/FILE

  • スクリプト冒頭のchinachu録画情報ファイルrecorded.jsonのパス設定を利用環境に合わせる。

 ChinachuJsonPath=/CHINACHU/data/recorded.json

  • 後掲の ts2h264ffmpeg-quit_on_another_ffmpeg.sh をインストールする。
  • コマンドライン引数無しでchinachuユーザーのcronで定期実行する。


(crontab例)
45 */6 * * * /home/tv/bin/chinachu-m2ts2h264.sh

https://bitbucket.org/arsmus/shell-script-public/src/d238e7f8dcf5ba63c319b60c7571785c535478dd/audio-video/chinachu-m2ts2h264.sh?at=master#chinachu-m2ts2h264.sh-11,13,18:19,21,23:25,36:37,48,50,52,56,58,60,100,103,106


MPEG2ビデオ(.m2tsファイル)をH.264ビデオ(.mp4ファイル)に変換するスクリプト
ts2h264ffmpeg-quit_on_another_ffmpeg.sh
実行属性を付けchinachuユーザーのPATHの通ったディレクトリに置く。

https://bitbucket.org/arsmus/shell-script-public/src/d238e7f8dcf5ba63c319b60c7571785c535478dd/audio-video/ts2h264ffmpeg-quit_on_another_ffmpeg.sh?at=master

録画直後に録画ファイルをmp4に変換し、それを新たな録画情報としてrecorded.jsonに追記するスクリプト例1

(短時間に複数録画した時の挙動が不安なので採用せず)

出典 recordedCommand/recorded.sh at master · kenh0u/recordedCommand · GitHub

RECORDEDJSON="/home/USER/chinachu/data/recorded.json"
MP4DIR="/YOUR/MP4/DIR/"

TSFILENAME=${1##*/}
MP4FILENAME="${TSFILENAME%.*}.mp4"
MP4FILEPATH="${MP4DIR}${MP4FILENAME}"

## for escaping conflict of writing to recorded.json
sleep 5

## append to recorded.json
RECORDEDJSONTEMP=`cat $RECORDEDJSON`
echo $RECORDEDJSONTEMP | jq -c ".+[ \
  $(
    echo $2 |
    jq  ".id += \"_mp4\"" | \
    jq  ".recorded = \"${MP4FILEPATH//\//\\\/}\"" | \
    jq -c ".title = \"[mp4]$(echo $2 | jq '.title' | tr --delete \")\"" \
  )
  ]" > $RECORDEDJSON

## jq -c : 改行・整形せずにjsonデータを出力する
## echo JSON-TEXT | jq ... | jq ... : echo出力はパイプを通じてjqによってフィルター処理された上で標準出力されて次に渡される。
## echo $RECORDEDJSONTEMP | jq -c ".+[ \ : .(ドット)は入力内容を表すので、パイプから入力された$RECORDEDJSONTEMP全体に +[以降の内容を連結する。
## 連結される[ ]の中に $(コマンド1 | コマンド2) を記述できる。
## jq  ".id += \"_mp4\"" : 入力テキスト(.)対し、idキーの値の末尾に _mp4 を連結した上で出力する。
## jq  ".recorded = \"${MP4FILEPATH//\//\\\/}\"": 前行のフィルター結果が.(ドット)に渡され、そのrecordedキーの値を、パス区切り文字(/)の前にエスケープ文字(\)を付けながら、$MP4FILEPATHの値に置き換える。
## jq -c ".title = \"[mp4]$(echo $2 | jq '.title' | tr --delete \")\"" : titleキーの値の先頭を[mp4]とし、それに続けて $(echo $2 | jq '.title' | tr --delete \") を連結する。
## $(echo $2 | jq '.title' | tr --delete \") : 直前録画情報($2)について、titleキーの値から二重引用符を削除して出力する。

## ${MP4FILEPATH//\//\\\/} について
##    ${MP4FILEPATH//ABC/xyz} は変数MP4FILEPATHの文字列内のすべてのABCをxyzに置き換えた文字列を返す。
##    上例では \/ が ABC に、\\\/ が xyz に相当する。
##    \/ は / をメタ文字ではなく単なる文字として扱う。
##    \\\/ は \\ と \/ に分けられる。
##    \\ は \ をメタ文字ではなく単なる文字として扱う。
##    \/ は / をメタ文字ではなく単なる文字として扱う。
##    したがって、 \\\/ は単なる文字としての \/ を表す。
##    ${MP4FILEPATH//\//\\\/} はMP4FILEPATHの文字列内のすべての / を \/ に置き換えた文字列を返す。

## | , && , || , & は、1行を複数行に分ける時、行末にバックスラッシュを書かなくてもよい。
##    $(コマンド)の ( , ) も?


## disallow writing to ts file
chmod 444 "$1"

## encode ts to mp4
nice -n 10 HandBrakeCLI \
    -i "$1" -o "${MP4FILEPATH}" \
    -f MP4 -O -e x264 \
    --x264-preset medium --x264-tune animation \
    --h264-profile high -q 25 --vfr \
    -a 1 -E fdk_aac -B 160 -6 stereo

## allow writing to ts file
chmod 666 "$1"

# allow writing to mp4 file
chmod 666 "${MP4FILEPATH}"

録画直後に録画ファイルをmp4に変換し、それを新たな録画情報としてrecorded.jsonに追記するスクリプト例2

(上記1の改変)
(短時間に複数録画した時の挙動が不安なので採用せず)

スクリプト保管場所
https://bitbucket.org/arsmus/shell-script-public/src/d238e7f8dcf5ba63c319b60c7571785c535478dd/audio-video/chinachu-m2ts2h264-asRecordedCommand.sh?at=master

全番組情報保管場所

~/chinachu/data/schedule.json

録画番組の無変換ストリーミング視聴

ストリーミング再生メニューでXSPFを選択する

コマンドラインでの録画ファイル削除・録画ファイル情報削除

  参考元: https://www.imoimo.xyz/?p=55

## ファイルを削除する
$ rm RECORDED/FILES/*.m2ts
## chinachuから録画情報を削除する
## chinachu cleanupは「ファイルが存在しない録画済情報をchinachuから削除する」「録画予定情報等は削除されない」
$ expect -c "
    set timeout 5
    spawn ~/chinachu/chinachu cleanup
    expect &#092;"[Y/n]? &#092;"
    send &#092;"Y&#092;n&#092;"
    expect &#092;"$&#092;"
    exit 0
  "