1
2

More than 1 year has passed since last update.

EPGStation での録画ルールを一括変更

Last updated at Posted at 2023-01-22

EPGStation での録画ルール。

image.png

最初のうちは TS ファイルも残すルールで運用していたが、エンコード処理が問題がないので TS ファイルを自動削除するようにした。
さて、ポリシー変更以前に設定したルールについても、TSファイルを自動削除するように変更したい。GUI でチマチマやるのではなく、どうしたら自動化できるかな?

環境

  • Version of EPGStation: 2.6.20
  • Version of Mirakurun: 3.9.0-rc.2
  • OS:Ubuntu Linux 20.04
  • Architecture: x64

「PLEX PX-Q3PE4 で docker-mirakurun-epgstation を使いたい」
https://qiita.com/nanbuwks/items/640ee4405e1fdd2ca497
こちらで構築したものです。

WebAPI

こういった処理は EPGStation では WebAPI を使って処理するらしい。
WebAPIのドキュメントはどこかな?

こちらによると、

EPGStation が提供する WebAPI は express-openapi によって提供される 、OpenAPI (Swagger) 準拠の RESTful API です
利用可能な全ての API は Swagger UI 上で確認可能です
http://:/api/debug

早速URLをブラウザで見てみると以下のように確認できた。

image.png

WebAPI が反応するかチェック

まずは WebAPI のアクセスができるかどうかチェック。

「archlinuxを定期的に再起動する(録画中ならやめる)」
https://qiita.com/hirmr/items/9c63bc7672032c5bf050

で使っているテクをそのまま使い、curl で録画中かどうかのチェックを行いました。

$ curl http://192.168.42.100:8888/api/recording?isHalfWidth=true

返ってきた返事

{"records":[{"id":6139,"channelId":400101,"startAt":1674367800000,"endAt":1674370800000,"name":"BS世界のドキュメンタリー「マミー・フット!おばあちゃんはサッカー選手」[二][字][再]","isRecording":true,"isEncoding":false,"isProtected":false,"ruleId":62,"programId":40010127876,"description":"シニア女性たちによるフランス対南アフリカのサッカー特別試合。珍しい取り組みの舞台裏に密着。言葉や文化が異なっても、仲間とともに人生を楽しむ気持ちは変わらない。","extended":"◇番組内容\nシニア女性たちによるフランス対南アフリカのサッカー特別試合。その舞台裏に密着する。フランスのメンバーはほとんどがサッカー経験なしだが新しいことへの挑戦に張り切る。一方の南アフリカチームは女性がショートパンツでサッカーをすることへの偏見をはねのけて練習に励んできた。試合本番。言葉や文化の違いを超えて、仲間とともに人生を楽しむ気持ちを共有する。 原題:MAMIES FOOT(フランス 2020年)\n◇制作\n~2020年 フランス Old Stories Production/PV Senioriales Production制作~","rawExtended":{"番組内容":"シニア女性たちによるフランス対南アフリカのサッカー特別試合。その舞台裏に密着する。フランスのメンバーはほとんどがサッカー経験なしだが新しいことへの挑戦に張り切る。一方の南アフリカチームは女性がショートパンツでサッカーをすることへの偏見をはねのけて練習に励んできた。試合本番。言葉や文化の違いを超えて、仲間とともに人生を楽しむ気持ちを共有する。 原題:MAMIES FOOT(フランス 2020年)","制作":"~2020年 フランス Old Stories Production/PV Senioriales Production制作~"},"genre1":8,"subGenre1":7,"genre2":0,"subGenre2":2,"genre3":0,"subGenre3":5,"videoType":"mpeg2","videoResolution":"1080i","videoStreamContent":1,"videoComponentType":179,"audioSamplingRate":48000,"audioComponentType":3,"thumbnails":[],"videoFiles":[{"id":10632,"name":"TS","filename":"2023年01月22日15時10分00秒-BS世界のドキュメンタリー「マミー・フット!おばあちゃんはサッカー選手」[二][字][再].m2ts","type":"ts","size":0}]}],"total":1}

返事が返ってきたので WebAPI へのアクセスは問題無いようです。

ルール情報を取得してみる

http://<サーバアドレス>/api/rules でルール情報を取得することができます。

パラメータ
offset オフセット Default:0
limit リミット Default:24
type 予約情報取得タイプ Available values : all, normal, conflict, skip, overlap
keyword キーワード

ということで、適当にルール3つをリクエスト

$ curl http://192.168.42.100:8888/api/rules?offset=10\&limit=3\&type="all"\&keyword=""

とすると、

{"rules":[{"id":11,"isTimeSpecification":false,"searchOption":{"keyCS":false,"keyRegExp":false,"name":true,"description":true,"extended":false,"ignoreKeyCS":false,"ignoreKeyRegExp":false,"ignoreName":false,"ignoreDescription":false,"ignoreExtended":false,"GR":false,"BS":false,"CS":false,"SKY":false,"isFree":false,"keyword":"ガリレオ","genres":[{"genre":3,"subGenre":0}],"times":[{"week":127}]},"reserveOption":{"enable":true,"allowEndLack":true,"avoidDuplicate":false},"encodeOption":{"mode1":"H.264","encodeParentDirectoryName1":"recorded","isDeleteOriginalAfterEncode":true},"reservesCnt":0},{"id":12,"isTimeSpecification":false,"searchOption":{"keyCS":false,"keyRegExp":false,"name":true,"description":true,"extended":false,"ignoreKeyCS":false,"ignoreKeyRegExp":false,"ignoreName":false,"ignoreDescription":false,"ignoreExtended":false,"GR":false,"BS":false,"CS":false,"SKY":false,"isFree":false,"keyword":"NHKスペシャル","genres":[{"genre":8,"subGenre":0}],"times":[{"week":127}]},"reserveOption":{"enable":true,"allowEndLack":true,"avoidDuplicate":false},"encodeOption":{"mode1":"H.264","encodeParentDirectoryName1":"recorded","isDeleteOriginalAfterEncode":true},"reservesCnt":6},{"id":13,"isTimeSpecification":false,"searchOption":{"keyCS":false,"keyRegExp":false,"name":true,"description":true,"extended":false,"ignoreKeyCS":false,"ignoreKeyRegExp":false,"ignoreName":false,"ignoreDescription":false,"ignoreExtended":false,"GR":false,"BS":false,"CS":false,"SKY":false,"isFree":false,"keyword":"はたらく魔王さま","genres":[{"genre":7,"subGenre":0}],"times":[{"week":127}]},"reserveOption":{"enable":true,"allowEndLack":true,"avoidDuplicate":false},"encodeOption":{"mode1":"H.264","encodeParentDirectoryName1":"recorded","isDeleteOriginalAfterEncode":true},"reservesCnt":0}],"total":185}

取得できました

python で同様に取得してみます。requests モジュールを使いました。


import requests
import json
url = "http://192.168.42.100:8888/api/rules?offset=1&limit=1&type=all&keyword="
response = requests.get(url)
jsonData = response.json()
for jsonObj in jsonData["rules"]:
    jsonObj["encodeOption"]={"mode1":"H.264","encodeParentDirectoryName1":"recorded","isDeleteOriginalAfterEncode":"False"}
    print(json.dumps(jsonObj,indent=4))
    print(jsonObj["encodeOption"]["isDeleteOriginalAfterEncode"])


この python がうまく動いたので、ルールを修正した JSON に直すようにしたのが以下です。

import requests
import json

url = "http://192.168.42.100:8888/api/rules?offset=1&limit=100&type=all&keyword="
response = requests.get(url)
jsonData = response.json()
for jsonObj in jsonData["rules"]:
    if ("encodeOption" not in jsonObj):
      print("no encodeOption:",jsonObj["id"])
      jsonObj["encodeOption"]={"mode1":"H.264","encodeParentDirectoryName1":"recorded","isDeleteOriginalAfterEncode":True}
    if (True != jsonObj["encodeOption"]["isDeleteOriginalAfterEncode"]):
      print("isDeleteOriginalAfterEncode is not True:",jsonObj["id"])
      jsonObj["encodeOption"]["isDeleteOriginalAfterEncode"]=True
    # print(json.dumps(jsonObj,indent=4))
    print(jsonObj["encodeOption"]["isDeleteOriginalAfterEncode"])

この修正した JSON を登録するようにすればいいですね。

予約修正

先程は GET メソッドで JSON を取得しましたが、それを修正した JSON は PUT メソッドを使って登録する必要があります。ルール修正のAPIが少し難しかったので、先に予約修正のAPIを curl でテストしてみました。以下の curl は、先の http://<hostname>:<port>/api/debug 画面にて Try it out を選ぶと生成することができます。

予約を取得

$ curl -X 'GET'   'http://192.168.42.100:8888/api/reserves/7444?isHalfWidth=false'   -H 'accept: application/json'
{"id":7444,"isSkip":false,"isConflict":false,"isOverlap":false,"allowEndLack":true,"isTimeSpecified":false,"isDeleteOriginalAfterEncode":false,"channelId":3273601024,"startAt":1674986400000,"endAt":1674988200000,"name":"NHKニュース7[二][字]","programId":327360102426083,"description":"「確かなニュース、いつでも どこでも」 きょうの日本、世界の今 一歩先へ、一歩深く テレビでもスマホでも このニュースを届けたい","extended":"◇番組内容\n「確かなニュース、いつでも どこでも」 きょうの日本、世界の今 一歩先へ、一歩深く テレビでもスマホでも このニュースを届けたい\n◇出演者\n【キャスター】高井正智,川﨑理加,深川仁志,【気象キャスター】向笠康二郎","rawExtended":{"番組内容":"「確かなニュース、いつでも どこでも」 きょうの日本、世界の今 一歩先へ、一歩深く テレビでもスマホでも このニュースを届けたい","出演者":"【キャスター】高井正智,川﨑理加,深川仁志,【気象キャスター】向笠康二郎"},"genre1":0,"subGenre1":0,"genre2":0,"subGenre2":1,"genre3":1,"subGenre3":0,"videoType":"mpeg2","videoResolution":"1080i","videoStreamContent":1,"videoComponentType....

これのうち、allowEndLack さえ含まれていれば、変更データは一部分だけでOKでした。以下は元々の録画予約に含まれていない encodeOption を追加したコマンドです。

$ curl -X 'PUT'   'http://192.168.42.100:8888/api/reserves/7444'   -H 'accept: application/json'   -H 'Content-Type: application/json'   -d '{  "allowEndLack": true,  "encodeOption": {"mode1": "H.264","encodeParentDirectoryName1": "recorded","isDeleteOriginalAfterEncode": true}}'

返事は以下のように返ってきました。

{"code":201,"message":"ok"}

ルール修正

ルール修正については、修正する一部だけで試したらエラーとなり、けっこうしっかりデータを作っておかないといけない感じです。基本的に取得したルールのJSONデータを書き換えて戻すようにしています。

curl でテスト

ルール取得

$ curl -X 'GET'   'http://192.168.42.100:8888/api/rules/16'   -H 'accept: application/json'
{"id":16,"isTimeSpecification":false,"searchOption":{"keyCS":false,"keyRegExp":false,"name":true,"description":true,"extended":false,"ignoreKeyCS":false,"ignoreKeyRegExp":false,"ignoreName":false,"ignoreDescription":false,"ignoreExtended":false,"GR":false,"BS":false,"CS":false,"SKY":false,"isFree":false,"keyword":"ベストヒットUSA ","channelIds":[400151],"genres":[{"genre":4,"subGenre":1}],"times":[{"week":127}]},"reserveOption":{"enable":true,"allowEndLack":true,"avoidDuplicate":false}}n

ルールに encodeOption を加えて書き換え

$ curl -X 'PUT'   'http://192.168.42.100:8888/api/rules/16'   -H 'accept: application/json'   -H 'Content-Type: application/json'   -d '{"id":16,"isTimeSpecification":false,"searchOption":{"keyCS":false,"keyRegExp":false,"name":true,"description":true,"extended":false,"ignoreKeyCS":false,"ignoreKeyRegExp":false,"ignoreName":false,"ignoreDescription":false,"ignoreExtended":false,"GR":false,"BS":false,"CS":false,"SKY":false,"isFree":false,"keyword":"ベストヒットUSA ","channelIds":[400151],"genres":[{"genre":4,"subGenre":1}],"times":[{"week":127}]},"reserveOption":{"enable":true,"allowEndLack":true,"avoidDuplicate":false},"encodeOption":{"mode1":"H.264","encodeParentDirectoryName1":"recorded","isDeleteOriginalAfterEncode":true}}'

返事

{"code":200}

Pythonプログラム

requests モジュールでは JSON の PUT がうまくいかなかったので、 urllib.request を使っています。
urllib.request が標準モジュールであることと、エラーメッセージがわかりやすかったので今後もこっちのほうがいいかな。

#import requests
import urllib.request
import json
# example json data={"id":16,"isTimeSpecification":False,"searchOption":{"keyCS":False,"keyRegExp":False,"name":True,"description":True,"extended":False,"ignoreKeyCS":False,"ignoreKeyRegExp":False,"ignoreName":False,"ignoreDescription":False,"ignoreExtended":False,"GR":False,"BS":False,"CS":False,"SKY":False,"isFree":False,"keyword":"ベストヒットUSA ","channelIds":[400151],"genres":[{"genre":4,"subGenre":1}],"times":[{"week":127}]},"reserveOption":{"enable":True,"allowEndLack":True,"avoidDuplicate":False},"encodeOption":{"mode1":"H.264","encodeParentDirectoryName1":"recorded","isDeleteOriginalAfterEncode":True}}

# limit を適宜変更のこと
urlget = "http://192.168.42.100:8888/api/rules?offset=0&limit=1000&type=all&keyword="
urlput = "http://192.168.42.100:8888/api/rules/"
# ルール一覧を得る
response = urllib.request.urlopen(urlget)
jsonData = json.load(response)
# ルールごとにループ
for jsonObj in jsonData["rules"]:
    # encodeOption が指定されていなかった場合
    if ("encodeOption" not in jsonObj):
      print("no encodeOption:",jsonObj["id"])
      # encodeOption を子要素と共に追加
      jsonObj["encodeOption"]={"mode1":"H.264","encodeParentDirectoryName1":"recorded","isDeleteOriginalAfterEncode":True}
      # 変更したルールを変更登録
      url=urlput+str(jsonObj["id"])
      headers = {"Content-Type": "application/json"}
      # print (json.dumps(s))
      res=urllib.request.Request(url,json.dumps(jsonObj).encode(),headers,method="PUT")
      with urllib.request.urlopen(res) as f:
          pass
      print(f.status,end="")
      if (200==f.status):
          print(" OK")
      else:
          print(" Error")
          print(f.reason)
          print(json.dumps(res.json()))
    # encodeOption が指定されているがisDeleteOriginarlAfterEncode が True でなかった場合
    if (True != jsonObj["encodeOption"]["isDeleteOriginalAfterEncode"]):
      print("isDeleteOriginalAfterEncode is not True:",jsonObj["id"])
      # True に変更
      jsonObj["encodeOption"]["isDeleteOriginalAfterEncode"]=True
      # 変更したルールを変更登録
      url=urlput+str(jsonObj["id"])
      headers = {"Content-Type": "application/json"}
      # print (json.dumps(s))
      res=urllib.request.Request(url,json.dumps(jsonObj).encode(),headers,method="PUT")
      with urllib.request.urlopen(res) as f:
          pass
      print(f.status,end="")
      if (200==f.status):
          print(" OK")
      else:
          print(" Error")
          print(f.reason)
          print(json.dumps(res.json()))


ちょっと手間取ったところとして、jsonObj は Python 内部では辞書型で持っているのですが、それをjson.dumps()で文字列に変えて更に encode() でバイト文字列にする必要がありました。

そのうえ、辞書型での Bool 値と json の Bool 値の表記が異なって ( True/true , False/false ) いるのをそらなかったので、最初戸惑ってしまいました。

実行

$ python3 apitest.py 
no encodeOption: 35
200 OK
no encodeOption: 40
200 OK
no encodeOption: 41
200 OK
no encodeOption: 42
200 OK
isDeleteOriginalAfterEncode is not True: 44
200 OK
isDeleteOriginalAfterEncode is not True: 45
200 OK
no encodeOption: 46
.
.
.
isDeleteOriginalAfterEncode is not True: 139
200 OK
no encodeOption: 143
200 OK
isDeleteOriginalAfterEncode is not True: 173
200 OK

うまくいきました。

録画ルール変更後の予約の扱い

録画ルールを変更しても、録画ルールから生成された予約が約一週間先まであります。録画ルールを変更する前に生成されたこの予約について、録画ルールを変更したら予約の内容はどうなるのでしょうか?

GUIで確かめたら、録画ルールを変更する以前に生成された予約の内容は、変更が反映されてました。予約も変更が必要かな? と思ってましたがそれは必要ないということになります。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2