LinuxのEPGStationでjoin_logo_scpを使ってエンコードを自動化する方法

Linuxでwineを使わずjoin_logo_scpが導入できるようになったという話は以前にこの記事で取り扱いました。記事ではRaspberry Piを用いたセットアップを行っているため少し他の環境とは違うかもしれまんが、join_logo_scpさえ導入できていれば基本的には今から掲載する方法で自動でエンコードが可能です。では、始めていきます。

ARMな環境でのjoin_logo_scpの導入はこちらで紹介しています。

実際に自動エンコードするにあたって躓いた箇所が何か所かありますが、先に正しく実行できる方法を書いておきます。後ろの方で躓いた場所や気を付けるべきところを紹介します。

目次

実行環境

私は本記事の冒頭で説明した、Raspberry Pi 4Bにjoin_logo_scpを導入したときと同じ環境で実行できることを確認しました。その環境は以下のようになっています。

  • Raspberry Pi 4B 4GB
  • Raspbian 32bit
  • PX-W3PE4
  • 録画データはNASに
  • EPGStationは2020/10/4現在で最新のもの

ARMな環境だと、join_logo_scpの導入はDockerを使えないのでローカルにインストールする必要があります。そのため、作者さんのサイトに掲載されている「jlse.js」というファイルでは動作しないので、別途エンコード用のスクリプトを用意する必要があるため、本記事を掲載するに至っています。

シェルスクリプトを作成する

私の場合は以下のようなシェルスクリプトを作成しました。

#!/bin/bash
export HOME="HOMEDIRECTORY"
jlse -i "$1" -e -t cutcm_logo -o " -c:v h264_omx -vf pullup=jb=54 -preset veryfast -acodec aac -ab 320K -b:v 4M -aspect 16:9 -r 24000/1001 -bsf:a aac_adtstoasc -tune animation" -r

1行目のbashの場所に関してはそれぞれの環境に合わせてください。また一番大切なのは2行目のexport~のところで"HOMEDIRECTORY"としている場所を以下のコマンドの結果と同じにしてください。

echo $HOME

また、3行目の-o以降の「"」で囲まれている部分はffmpegのオプションを記述する場所なので自身の好みに合わせて変更を行ってください。また、先頭のスペースは必ず必要になっています。忘れないようにしてください。

ちなみにこのシェルスクリプトを実行すると、録画ファイルと同じ階層にエンコード後のファイルが出力されてしまいます。そのため、このシェルスクリプトのあとにmvコマンドでファイルを移動するといいかもしれません。出力は私の設定だと環境変数OUTPUTで渡されているので容易に移動ができます。日時などの時間が入るのが嫌であれば、環境変数NAMEでリネームしてしまってもいいかもしれませんね。

シェルスクリプトをEPGStationに登録する

シェルスクリプトをEPGStationに登録して、自動でエンコードできるように設定していきます。

EPGStationのディレクトリに入り、config.jsonを編集します。普通はEPGStation/config以下にあるファイルです。以下のように追記を行います。私の場合は以下のようにしたというだけで好きなように設定してもらって大丈夫です。

    "encode": [
        {
            "name": "JLS_JS",
            "cmd": "/bin/bash %ROOT%/config/test.sh \"%INPUT%\"",
            "suffix": ".mp4",
            "default": false
        },
        {
    "name": "JLS_OMX_anime",
    "cmd": "/bin/bash %ROOT%/config/jlse.sh \"%INPUT%\"",
    "suffix": ".mp4",
    "default": true
        }
    ],

これで念のため再起動をおこないます。

sudo reboot

これでEPGStationにアクセスしてみると、録画時に「JLS_LS」と「JLS_OMX_anime」の二つができているので私の場合は「JLS_OMX_anime」を選択するとjoin_logo_scpを用いてエンコードができます。

私の用意したひな型をもとに改変をすれば色々応用も聞くと思うので頑張って好きな設定になるようにしてみてください。

この自動化を行ったうえで、録画をしながらハードウェアエンコードをしても問題ないかをこちらの記事で検証してみました。具体的にはI/O負荷やCPU負荷に問題がないかを検証しています。

同時録画+エンコードはできるのか!?

躓いたところ

結論から言うと、最初はHOMEを設定していなかったためにうまく動きませんでした。せっかくなので、どんな環境変数が渡されているのか調べるためにシェルスクリプトで環境変数がどうなっているのかを調べてみました。

1.INPUT
2.OUTPUT
3.NAME
4.HOME
5.PATH

1./rokuga/日時番組名.ts 
2./rokuga/日時番組名.mp4 
3.番組名
4. 
5./usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

入出力名はさておきHOMEが渡されていないためjoin_logo_scpがうまく動作していなかったようなので、シェルスクリプトの二行目にあるexport HOME~を実行しなければならなかったということです。ここがわからずしばらくここをぐるぐるしていましたが、作者様の手をお借りして解決することができました。

掲載しているシェルスクリプト自体はあえてコマンドライン引数として"%INPUT%"を渡していますので、以下のような形で実行することで直接動作させることができます。

./jlse.sh "録画ファイルのフルパス"

まず私は最初に以下のようなスクリプトを作成していました。上の項で紹介したものと違う点でいうと、二行目のexport HOME...がありません。

#!/bin/bash
jlse -i "$1" -e -t cutcm_logo -o " -c:v h264_omx -vf pullup=jb=54 -preset veryfast -acodec aac -ab 320K -b:v 4M -aspect 16:9 -r 24000/1001 -bsf:a aac_adtstoasc -tune animation" -r

うまく動かなったので手始めに簡単なログを取ってみました。すると以下のような表示になりました。

放送局はファイル名から検出できませんでした
ロゴファイルすべてを入力します

うん、わからん。ということでまずこのシェルスクリプトがそもそも正しく実行できるかをEPGStation上からではなく、SSH接続のターミナル上から確認してみることにしました。そのときのログはこのようになりました。

chapter.auf pre loading program.
usage:
chapter_exe.exe -v input_avs -o output_txt
params:
-v 入力画像ファイル
-a 入力音声ファイル(省略時は動画と同じファイル)
-m 無音判定閾値(1~2^15)
-s 最低無音フレーム数
-b 無音シーン検索間隔数
-e 無音前後検索拡張フレーム数
Setting
video: /directory
audio: (within video source)
out:/directory
mute: 50 seri: 8 bmute: 60 emute: 4
Loading plugins.
Movie data
Video Frames: 2433 [29.97fps]
Video Format:
Audio Samples: 3886002 [48000Hz]
--------
Start searching...
放送局はファイル名から検出できませんでした
ロゴファイルすべてを入力します

これで正常にエンコードも終えています。最後の一文が同じなので正しく実行できているのでは…?と思ったことが今回ドツボにはまった原因とも言えます。

考えた原因が、正しく実行できているということはEPGStationによってシェルスクリプトが途中で中断されてしまっているのではないかと思いここを重点的に探したものの情報は見つからず。もう一つはそもそもシェルスクリプトはEPGStationのエンコードコマンドとして使用できないのではないかということです。しかしそういうわけでもないらしくここでずっと躓いていました。

より詳細なログがこうしたら取れるというのを作者様に教えていただいたので、それを実行してみると以下のログを得ることができました。

terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_M_construct null not valid
放送局はファイル名から検出できませんでした
ロゴファイルすべてを入力します
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_M_construct null not valid
error: failed to open /HOME/JoinLogoScpTrialSetLinux/modules/join_logo_scp_trial/result/番組名/obs_logoframe.txt
error: failed to open /HOME/JoinLogoScpTrialSetLinux/modules/join_logo_scp_trial/result/番組名/obs_chapterexe.txt
events.js:174
throw er; // Unhandled 'error' event
^
Error: ENOENT: no such file or directory, open '/HOME/JoinLogoScpTrialSetLinux/modules/join_logo_scp_trial/result/番組名/obs_cut.avs'
Emitted 'error' event at:
at /HOME/JoinLogoScpTrialSetLinux/modules/join_logo_scp_trial/node_modules/graceful-fs/graceful-fs.js:282:14
at /HOME/JoinLogoScpTrialSetLinux/modules/join_logo_scp_trial/node_modules/graceful-fs/graceful-fs.js:333:16
at FSReqWrap.oncomplete (fs.js:141:20)

ここでやっとそもそも正常に動作していないことが突き止められたわけです。

この動かない理由がHOME変数が渡されていないからだということだったのです。JLSではHOMEを取得する作業が内部的にあるのでしょう。

この状態でも番組名のresultファイルが出来上がっているので、さもうまくいっているように見えてしまっていたのが今回解決にすごく時間がかかった理由の一つでもあります。

もしも自分なりのシェルスクリプトを書いていて困ったことがあれば、ログを取って原因を突き止めましょう。とはいえ、今回の件ばかりは作者様が教えてくれないとたどり着けなったと思いますが…

以上の躓いた点を簡単にまとめるとEPGStationからの自動エンコードでjoin_logo_scpを使う上で最も大事なのは、HOME変数を定義すること。これに尽きます。普通にターミナルからシェルスクリプトを実行するうえでは不要ですが、EPGStation上から実行する際の特別な対応になります。

以上で説明を終わりとします。お読みいただきありがとうございました。わからないことがあればコメントをいただけるとお答えできるかもしれません。

コメントする

メールアドレスが公開されることはありません。