4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

EPGStationの状態をshでLINE Messege APIに送る

Last updated at Posted at 2025-10-04

EPGStationの状態をサ終したLINE Notifyに代わってLINE Messege APIでLINEに送るシェルスクリプトです。

このシェルスクリプトはPiedHarrierさんのEPGS-to-LINEを参考に作り変えています。

(Qiitaの記事を書くのは初めてなので少し不自然な部分があるかもしれません。)

必要なもの

EPGStationが導入済のLinux PC

PHPが動く、かつドメインがありSSL付きで外部に公開されているサーバー
→ない場合の対処法あり

LINE Business ID作成時の
・メールアドレス
・SMS認証用の電話番号

環境

Ubuntu 24.04.2 LTS
EPGStation v2.10.0
Docker 28.4.0

docker-mirakurun-epgstationでepgstationを構築済み

LINE NotifyとLINE Nessege APIの違い

送信上限

LINE Notify → 1,000 回/時間
LINE Messege API → 200回/月

利用価格

LINE Notify → 無料
LINE Messege API → 無料 (送信上限を上げられる有料プランあり)
(上限に達するとエラーで送信できなくなります。)

プログラムを保存

以下のシェルスクリプトをrun.shという名前でローカルに保存してください。

必ず「UnixLF」で保存してください。CRLFなどだと正しく動きません。

run.sh
 #!/bin/bash
set -eu

########################################################################
#License:
#https://github.com/PiedHarrier/EPGS-to-LINE
########################################################################

########################################################################
# トークン
########################################################################
LINE_TOKEN="ここにチャネルアクセストークン貼付け"
LINE_TO="ここにユーザーIDまたはグループID貼付け"

########################################################################
# JSON エスケープ(簡易)
########################################################################
escape_json() {
  local s="$1"
  s="${s//\\/\\\\}"
  s="${s//\"/\\\"}"
  s="${s//$'\n'/\\n}"
  s="${s//$'\r'/\\r}"
  s="${s//$'\t'/\\t}"
  printf '%s' "$s"
}

########################################################################
# epoch -> JST 表示
########################################################################
epoch_to_jst() {
  local epoch_s="$1"
  if [ -z "$epoch_s" ] || [ "$epoch_s" = "0" ]; then
    printf '%s' "未設定"
    return
  fi
  local utc
  utc=$(date -u -d "@${epoch_s}" '+%Y-%m-%d %H:%M:%S')
  date -d "${utc} +9 hours" '+%m/%d(%a) %H:%M'
}

########################################################################
# main
########################################################################
if [ "$#" -ne 1 ]; then
  echo "Usage: $0 <reserve|update|delete|prestart|prepfailed|start|end|recfailed|encod_end>" >&2
  exit 1
fi

ret="$1"

CHANNELNAME="${CHANNELNAME:-放送局名なし}"
NAME="${NAME:-タイトル未設定}"
DESCRIPTION="${DESCRIPTION:-番組概要が指定されていません。}"
EXTENDED="${EXTENDED:-}"
STARTAT_MS="${STARTAT:-}"
ENDAT_MS="${ENDAT:-}"
DURATION_MS="${DURATION:-}"
ERROR_CNT="${ERROR_CNT:-N/A}"
DROP_CNT="${DROP_CNT:-N/A}"
SCRAMBLING_CNT="${SCRAMBLING_CNT:-N/A}"

start_epg_time=""
end_epg_time=""
if [ -n "$STARTAT_MS" ] && printf '%s' "$STARTAT_MS" | grep -qE '^[0-9]+$'; then
  start_epg_time=$(( STARTAT_MS / 1000 ))
fi
if [ -n "$ENDAT_MS" ] && printf '%s' "$ENDAT_MS" | grep -qE '^[0-9]+$'; then
  end_epg_time=$(( ENDAT_MS / 1000 ))
fi

startat="$(epoch_to_jst "${start_epg_time:-}")"
endat="$(epoch_to_jst "${end_epg_time:-}")"

if [ -n "$DURATION_MS" ] && printf '%s' "$DURATION_MS" | grep -qE '^[0-9]+$'; then
  duration_minutes=$(( DURATION_MS / 60000 ))
else
  duration_minutes="未設定"
fi

# ----- ここから printf -v を使わない組み立て -----
case "$ret" in
  reserve)
    content=$(printf '%s\n%s\n%s\n%s ~ %s    %s分\n%s\n%s' \
      "✅ 予約追加" "$NAME" "$CHANNELNAME" "$startat" "$endat" "$duration_minutes" "$DESCRIPTION" "$EXTENDED")
    ;;
  delete)
    content=$(printf '%s\n%s\n%s' "💨 予約削除" "$NAME" "$CHANNELNAME")
    ;;
  update)
    content=$(printf '%s\n%s\n%s\n%s ~ %s    %s分' \
      "🔁 予約更新" "$NAME" "$CHANNELNAME" "$startat" "$endat" "$duration_minutes")
    ;;
  prestart)
    content=$(printf '%s\n%s\n%s' "🔷 録画準備開始" "$NAME" "$CHANNELNAME")
    ;;
  prepfailed)
    content=$(printf '%s\n%s\n%s' "💥 録画準備失敗" "$NAME" "$CHANNELNAME")
    ;;
  start)
    content=$(printf '%s\n%s\n%s\n%s' "⏺ 録画開始" "$NAME" "$CHANNELNAME" "$startat")
    ;;
  encod_end)
    content=$(printf '%s\n%s\n%s' "⏹ エンコード終了" "$NAME" "$CHANNELNAME")
    ;;
  end)
    content=$(printf '%s\n%s\n%s\n%s ~ %s    %s分\n%s' \
      "⏹ 録画終了" "$NAME" "$CHANNELNAME" "$startat" "$endat" "$duration_minutes" "エラー: ${ERROR_CNT}, ドロップ: ${DROP_CNT}, スクランブル: ${SCRAMBLING_CNT}")
    ;;
  recfailed)
    content=$(printf '%s\n%s\n%s' "❌ 録画失敗" "$NAME" "$CHANNELNAME")
    ;;
  *)
    echo "未知のコマンド: $ret" >&2
    exit 1
    ;;
esac
# ----- 終わり -----

escaped_text=$(escape_json "$content")
json="{\"to\":\"${LINE_TO}\",\"messages\":[{\"type\":\"text\",\"text\":\"${escaped_text}\"}]}"

curl -sS -X POST "https://api.line.me/v2/bot/message/push" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${LINE_TOKEN}" \
  -d "${json}" || {
    echo "LINE message push failed" >&2
    exit 1
  }

exit 0

LINE Messaging APIの登録とチャネルの作成

LINE Messaging APIを使うためには、まずLINE Official Accountを作成し、Messaging APIを有効化します。これでAPIチャネルが作成されます。

LINE Official Accountを作成

ブラウザで https://manager.line.biz/ にアクセスし、下にある[アカウントを登録]を押してLINEアカウントまたはメールアドレスでアカウントを登録します。

フォームに必要な情報を入力(名前、メールなど)して、LINE Official Accountを作成します。

Messaging APIを有効化

LINE Official Account Manager https://manager.line.biz/ にログインし、対象のアカウントを選択。
[設定(右上にあります)] > [Messaging API] に移動し、[Messaging API を有効化] をクリック。

プロバイダを選択(初めての場合は新規作成)。これでMessaging APIチャネルが自動的に作成されます。

初めての場合、開発者アカウントの作成を求められることがあります。必要な情報を入力して進めます。
また、SMS認証を求められることもあります。認証して進めます。

LINE Developers Consoleにログイン:

https://developers.line.biz/console/ にアクセスし、同じLINEアカウントでログイン。
作成したプロバイダとチャネルが表示されていることを確認します。

これでLINE Messege APIを使う準備完了です。次にアクセストークンを取得します。

チャネルアクセストークンの取得

スクリプトがAPI呼び出し時の認証に使う長期アクセストークンを取得します。

LINE Developers Console で、作成したMessaging APIチャネルを選択。
[Messaging API] タブに移動。
チャネルアクセストークン(長期)の欄で[発行]をクリックし、トークンを発行します。
スクリーンショット 2025-10-04 185556.png

発行されたトークンをコピーし、run.shの

run.sh
LINE_TOKEN="ここにチャネルアクセストークン貼付け" 

に貼り付けます (例: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...")。

このトークンは機密情報なので、安全に保管しましょう。
セキュリティ向上のため、[セキュリテイ設定]タブからIP制限を設定することもできます。

ユーザーIDまたはグループIDの取得

スクリプトのLINE_TOに使うIDです。プッシュメッセージを送る相手(自分自身やグループ)のIDが必要です。IDはWebhookイベントから取得します。

ボットを友達追加

LINEアプリで、作成したLINE Official Accountを友達追加します(Consoleの[Messaging API] タブにQRコードがあります)。

Webhookを設定してIDを取得

Webhookは、ユーザーがボットにメッセージを送ったときにイベントを受け取るためのURLです。これでuserIdを取得できます。

Webhook URLの設定

LINE Developers Console > チャネル > [Messaging API] タブ > [Webhook設定] > [編集] をクリック。
自分のサーバーのURLを入力(例: https://example.com/webhook/api.php )。SSL証明書が必要です(無料のLet's Encryptなどで大丈夫です)。
サーバーがない場合は、後述の「自分のサーバーがない場合の対処法」を参照してください。
スクリーンショット 2025-10-04 185927.png
スクリーンショット 2025-10-04 190041.png

最初は同一ディレクトリ内にIDを記述するphpにしたのですが、何故か動かなかったのでサーバーに送られてきたIDをDiscordのWebhookに送信するphpを置き、そこに送信しました。

IDをDiscord WebHookに送信するPHP

api.php
<?php
// DiscordのWebhook URLを設定(WebHook URLを貼り付けてください。)
$discordWebhookUrl = 'https://discord.com/api/webhooks/XXXXXXXXXX/XXXXXXXX';

// LINE Webhookからのリクエストを処理
$input = file_get_contents('php://input');
$data = json_decode($input, true);

// イベントが存在する場合
if (isset($data['events']) && count($data['events']) > 0) {
    // 最初のイベントからユーザーIDを取得(通常、メッセージイベントの場合)
    $event = $data['events'][0];
    if (isset($event['source']['userId'])) {
        $userId = $event['source']['userId'];
        
        // DiscordにユーザーIDを送信するメッセージを作成
        $message = [
            'content' => "届いたユーザーID: $userId"
        ];
        
        // cURLを使ってDiscord WebhookにPOST
        $ch = curl_init($discordWebhookUrl);
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($message));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        
        $response = curl_exec($ch);
        curl_close($ch);
        
        // レスポンスをログ出力(オプション)
        error_log("Discord response: $response");
    }
}

// LINE APIからのリクエストに200 OKを返す
http_response_code(200);
echo 'OK';
?>
元のテキストに保存するphpも載せておきます。
api_txt.php
<?php
// POSTデータを読み込む
$json = file_get_contents('php://input');
$data = json_decode($json, true);

// データが正しくデコードされたか確認
if ($data && isset($data['events'][0]['source']['userId'])) {
    $userId = $data['events'][0]['source']['userId'];
    
    // 同一ディレクトリのid.txtにユーザーIDを記述(上書きモード)
    file_put_contents('id.txt', $userId);
    
    // デバッグ用にデータをログ出力(本番では削除またはログファイルに)
    error_log(print_r($data, true));
}

// LINEにOKを返す(200 OK)
http_response_code(200);
echo 'OK';
?>

自分のサーバーがない場合の対処法
自分のサーバーがない場合はPythonなどで簡易的なサーバーを立て、Ngrokなどで外部公開しましょう。

簡易的なサーバー.py
from flask import Flask, request
app = Flask(__name__)

@app.route('/webhook', methods=['POST'])
def webhook():
    data = request.json
    print(data)  # ここにuserIdなどが表示される
    return 'OK', 200

if __name__ == '__main__':
    app.run()

Secure Shere NetとCloudflare Tunnelの無料プランではエラーになり送信できませんでした。

[更新] をクリックし、[検証] でテスト。
スクリーンショット 2025-10-04 162831.png
このように表示されたら成功です。

スクリーンショット 2025-10-04 162612.png
このように表示された場合は正しく通信できていません。URLを確認してやり直してください。

正しく検証できたら[Webhookの利用] をクリックしてWebHookを有効化します。

LINEアプリからボットにメッセージを送る

LINEアプリからボットにメッセージを送ります。(例: "hello")

サーバーにIDが届き、ユーザーID(例: "U1234567890abcdef...")が表示されます。

発行されたトークンをコピーし、run.shの

run.sh
LINE_TO="ここにユーザーIDまたはグループID貼付け" 

に貼り付けます (例: "U1234567890abcdef...")。

スクリプトの設置と設定

run.shをEPGStationのルートディレクトリ(%ROOT%)の下のconfigディレクトリに保存
(例: /path/to/epgstation/config/run.sh)

必ず「UnixLF」で保存してください。CRLFなどだと正しく動きません。

実行権限を付与

chmod +x /path/to/epgstation/config/run.sh

docker-mirakurun-epgstationで構築している場合はこの先の手順を行っても正しく動作しない場合があります。
docker-mirakurun-epgstationで構築している場合は
https://qiita.com/saturi/items/6f8d9d2524a8d1e92095#docker-mirakurun-epgstationで構築している場合
も参考にしてください。

EPGStationでのConfig設定

EPGStationのconfigファイルに以下を追記します。

config.yml
reserveNewAddtionCommand: '/bin/sh %ROOT%/config/run.sh reserve'
reserveUpdateCommand: '/bin/sh %ROOT%/config/run.sh update'
reservedeletedCommand: '/bin/sh %ROOT%/config/run.sh delete'
recordingPreStartCommand: '/bin/sh %ROOT%/config/run.sh prestart'
recordingPrepRecFailedCommand: '/bin/sh %ROOT%/config/run.sh prepfailed'
recordingStartCommand: '/bin/sh %ROOT%/config/run.sh start'
recordingFinishCommand: '/bin/sh %ROOT%/config/run.sh end'
recordingFailedCommand: '/bin/sh %ROOT%/config/run.sh recfailed'
encodingFinishCommand: '/bin/sh %ROOT%/config/run.sh encod_end'
設定項目名 イベント発生タイミング
reserveNewAddtionCommand 新しい予約が追加されたとき
reserveUpdateCommand 既存の予約が更新されたとき
reservedeletedCommand 予約が削除されたとき
recordingPreStartCommand 録画開始直前(チューナー準備中)
recordingPrepRecFailedCommand 録画準備に失敗したとき
recordingStartCommand 録画が開始されたとき
recordingFinishCommand 録画が完了したとき
recordingFailedCommand 録画中に失敗したとき
encodingFinishCommand エンコードが完了したとき

EPGStationを再起動して適用

停止

cd ~/git/docker-mirakurun-epgstation  (Pathは自分の環境に合わせて変えてください。)
docker compose down

起動

cd ~/git/docker-mirakurun-epgstation  (Pathは自分の環境に合わせて変えてください。)
docker compose up -d

簡易テスト

プログラムが正しく動くかテストします。
以下コマンドを実行し、LINEアプリに正しくメッセージが来るか確認してください。

cd /path/to/epgstation/config  (Pathは自分の環境に合わせて変えてください。)
bash run.sh reserve

Screenshot_20251004-170840.png
このようにメッセージが来れば成功です。

あとはEPGStationのWebUIから録画予約などをしてみて正しくメッセージが届けば成功です。

docker-mirakurun-epgstationで構築している場合

dockerコンテナ内にEPGStationがある場合、上記の方法ではEPGStation側からrun.shを呼び出せません。
(つまり手動でrun.shを打つと動くのにEPGStationでrun.shを呼び出そうとしてもrun.shが呼び出されないという問題が起こります。)

docker内からrun.shを呼び出す方法

docker psを実行してコンテナ名を確認

docker psを実行してコンテナ名を確認します。

euser@SV-REC01:~$ docker  ps
CONTAINER ID   IMAGE                                    COMMAND                   CREATED       STATUS       PORTS                                                                                          NAMES
697917e7b531   docker-mirakurun-epgstation-epgstation   "npm start"               4 hours ago   Up 4 hours   0.0.0.0:8888-8889->8888-8889/tcp, [::]:8888-8889->8888-8889/tcp                                epgstation-v2
a99c725ceacb   mariadb:10.5                             "docker-entrypoint.s…"   4 hours ago   Up 4 hours   3306/tcp                                                                                       mysql-epgstation-v2
61b0245f5ec9   chinachu/mirakurun                       "docker-entrypoint.s…"   4 hours ago   Up 4 hours   0.0.0.0:9229->9229/tcp, [::]:9229->9229/tcp, 0.0.0.0:40772->40772/tcp, [::]:40772->40772/tcp   mirakurun

一番右側のNAMESの部分にある名前がコンテナ名です。(この場合は[epgstation-v2]です。)

docker cpでrun.shをコピー(お手軽)

この方法は簡単ですが、dockerの再起動 (もしくはPC自体の再起動)でrun.shが消えてしまいます。
永続化したい場合はこの次の方法をおすすめします。

ホストPCからコンテナ内にコピー

docker cp ./run.sh epgstation-v2:/app/config/run.sh

コンテナ内で実行権限を付与

docker exec -it epgstation-v2 chmod +x /app/config/run.sh

これで EPGStation から呼び出せるようになります。

メモ:
/app は epgstation の %ROOT% にあたるディレクトリです

docker-compose.yml にマウント設定を入れる(永続化・おすすめ)

この方法であれば再起動しても消えないのでこの方法がおすすめです。

docker-compose.ymlにマウント設定をする

書き方はホストPCのPath:Docker内のPathです。

docker-compose.yml
   epgstation:
        container_name: epgstation-v2
        build:
            context: "./epgstation"
            dockerfile: "debian.Dockerfile"
        volumes:
            #この下の行を追加 (Pathは環境に合わせて変えてください。) (相対パスでも動くはずですが、トラブルを避けるために絶対パスにしています。)
            - /home/euser/git/docker-mirakurun-epgstation/epgstation/config/run.sh:/app/config/run.sh  # ← ☆追加
            - /etc/localtime:/etc/localtime:ro
            - ./epgstation/config:/app/config
            - ./epgstation/data:/app/data
            - ./epgstation/thumbnail:/app/thumbnail
            - ./epgstation/logs:/app/logs
            - /mnt/data1:/app/recorded

こうすると、ホスト側の ./config フォルダに置いた run.sh が 自動でコンテナの /app/config と同期されます。
→ 以降はホストで run.sh を編集するだけでコンテナ内に反映されます。

実行権限を付与

chmod +x /path/to/epgstation/config/run.sh

ホスト側で実行権限をつけるとDockerにも反映されます。

Docker再起動して適用

停止

cd ~/git/docker-mirakurun-epgstation  (Pathは自分の環境に合わせて変えてください。)
docker compose down

起動

cd ~/git/docker-mirakurun-epgstation  (Pathは自分の環境に合わせて変えてください。)
docker compose up -d

送信テスト

以下を実行し正しくメッセージが届くか確認してください。

docker exec -it epgstation-v2 /bin/bash /app/config/run.sh reserve

届く場合は成功です。EPGStationのWebUI側から操作して正しく動くか確認してください。
Screenshot_20251004-170840 (1).png

届かない場合はrun.shで使われているcURLがDockerコンテナにインストールされていない可能性があります。以下コマンドでcURLをインストールしてください。

#Dockerコンテナへ入る
docker exec -it epgstation-v2 /bin/bash
#パッケージリストの更新
apt update
#cURLのインストール
apt install curl

再度以下を実行し正しくメッセージが届くか確認してください。

docker exec -it epgstation-v2 /bin/bash /app/config/run.sh reserve

メッセージが届けば成功です。EPGStationのWebUI側から操作して正しく動くか確認してください。
Screenshot_20251004-184705.png

この方法ではDockerコンテナ・PCの再起動でcURLが消えてしまい、run.shを動かすには再度インストールが必要です。永続化したい場合はDockerファイルにapt-get install curlを追加し、ビルドしてください。やり方→ https://qiita.com/saturi/items/6f8d9d2524a8d1e92095#dockerコンテナのcurlのインストールと再ビルド

詳細テスト

cd /path/to/epgstation/config  (Pathは自分の環境に合わせて変えてください。)

# 予約追加イベントをテスト
bash run.sh reserve

# 予約更新イベントをテスト
bash run.sh update

# 録画開始をテスト
bash run.sh start

# 録画終了をテスト
bash run.sh end

# エンコード終了をテスト
bash run.sh encod_end

#EPGStationから渡される変数をテストしたい場合
NAME="テスト番組" CHANNELNAME="TEST" DESCRIPTION="テスト説明文" STARTAT=1728000000 ENDAT=1728003600 DURATION=3600000 bash run.sh start

DockerコンテナのcURLのインストールと再ビルド

Dockerコンテナ・PCの再起動後もcURLが使えるようにDockerfileを書き換えてからDockerコンテナを再ビルドします。

再ビルドではデータは消えないはずですが、バックアップを取っておくことをおすすめします。

EPGStationを停止

cd ~/git/docker-mirakurun-epgstation  (Pathは自分の環境に合わせて変えてください。)
docker compose down

Dockerfileは以下のようになっていると仮定して進めます。この部分は環境によって変えてください。
DockerfileのPath/home/euser/git/docker-mirakurun-epgstation/epgstation/debian.Dockerfile

Dockerfile
FROM l3tnun/epgstation:master-debian

ENV DEV="make gcc git g++ automake curl wget autoconf build-essential libass-dev libfreetype6-dev libsdl1.2-dev libtheora-dev libtool libva-dev libvdpau-dev libvorbis-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev pkg-config texinfo zlib1g-dev"
ENV FFMPEG_VERSION=7.0

RUN apt-get update && \
    apt-get -y install $DEV && \
    apt-get -y install yasm libx264-dev libmp3lame-dev libopus-dev libvpx-dev && \
    apt-get -y install libx265-dev libnuma-dev && \
    apt-get -y install libasound2 libass9 libvdpau1 libva-x11-2 libva-drm2 libxcb-shm0 libxcb-xfixes0 libxcb-shape0 libvorbisenc2 libtheora0 libaribb24-dev && \
\
#ffmpeg build
    mkdir /tmp/ffmpeg_sources && \
    cd /tmp/ffmpeg_sources && \
    curl -fsSL http://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.bz2 | tar -xj --strip-components=1 && \
    ./configure \
      --prefix=/usr/local \
      --disable-shared \
      --pkg-config-flags=--static \
      --enable-gpl \
      --enable-libass \
      --enable-libfreetype \
      --enable-libmp3lame \
      --enable-libopus \
      --enable-libtheora \
      --enable-libvorbis \
      --enable-libvpx \
      --enable-libx264 \
      --enable-libx265 \
      --enable-version3 \
      --enable-libaribb24 \
      --enable-nonfree \
      --disable-debug \
      --disable-doc \
    && \
    make -j$(nproc) && \
    make install && \
\
# 不要なパッケージを削除
    apt-get -y remove $DEV && \
    apt-get autoremove -y && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/* && \
    rm -rf /tmp/*

これを以下のように変更します。

Dockerfile
FROM l3tnun/epgstation:master-debian

ENV DEV="make gcc git g++ automake curl wget autoconf build-essential libass-dev libfreetype6-dev libsdl1.2-dev libtheora-dev libtool libva-dev libvdpau-dev libvorbis-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev pkg-config texinfo zlib1g-dev"
ENV FFMPEG_VERSION=7.0

RUN apt-get update && \
    apt-get -y install $DEV && \
    apt-get -y install yasm libx264-dev libmp3lame-dev libopus-dev libvpx-dev && \
    apt-get -y install libx265-dev libnuma-dev && \
    apt-get -y install libasound2 libass9 libvdpau1 libva-x11-2 libva-drm2 libxcb-shm0 libxcb-xfixes0 libxcb-shape0 libvorbisenc2 libtheora0 libaribb24-dev && \
\
#ffmpeg build
    mkdir /tmp/ffmpeg_sources && \
    cd /tmp/ffmpeg_sources && \
    curl -fsSL http://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.bz2 | tar -xj --strip-components=1 && \
    ./configure \
      --prefix=/usr/local \
      --disable-shared \
      --pkg-config-flags=--static \
      --enable-gpl \
      --enable-libass \
      --enable-libfreetype \
      --enable-libmp3lame \
      --enable-libopus \
      --enable-libtheora \
      --enable-libvorbis \
      --enable-libvpx \
      --enable-libx264 \
      --enable-libx265 \
      --enable-version3 \
      --enable-libaribb24 \
      --enable-nonfree \
      --disable-debug \
      --disable-doc \
    && \
    make -j$(nproc) && \
    make install && \
\
# 不要なパッケージを削除
    apt-get -y remove $DEV && \
    apt-get autoremove -y && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/* && \
    rm -rf /tmp/* && \ #☆この行から変更あり
\
# --- 最終イメージに curl と httpsを使うための ca-certificates を残す  ---
    apt-get update && \
    apt-get -y install --no-install-recommends curl ca-certificates && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

プロジェクトルートフォルダに移動し、ビルド実行

cd ~/git/docker-mirakurun-epgstation  (Pathは自分の環境に合わせて変えてください。)

docker compose build --no-cache epgstation

コマンドは「epgstation」です。「epgstation-v2」ではありません。
実行できない場合はdocker-compose.ymlにかかれている名前を使用してください。

services:
    epgstation: # ←この部分
        container_name: epgstation-v2
        ...
全文
docker-compose.yml
services:
    mirakurun:
        container_name: mirakurun
        build:
          context: Mirakurun
          dockerfile: docker/Dockerfile
        image: chinachu/mirakurun
        cap_add:
            - SYS_ADMIN
            - SYS_NICE
        ports:
            - "40772:40772"
            - "9229:9229"
        volumes:
            - /etc/localtime:/etc/localtime:ro
            - ./Mirakurun/config/:/app-config/
            - ./Mirakurun/data/:/app-data/
        environment:
            TZ: "Asia/Tokyo"
        devices:
            - /dev/px4video0:/dev/px4video0
            - /dev/px4video1:/dev/px4video1
            - /dev/px4video2:/dev/px4video2
            - /dev/px4video3:/dev/px4video3
            - /dev/bus:/dev/bus
        restart: always
        logging:
            driver: json-file
            options:
                max-file: "1"
                max-size: 10m

    mysql:
        container_name: mysql-epgstation-v2
        image: mariadb:10.5
        volumes:
            - mysql-db:/var/lib/mysql
        environment:
            MYSQL_USER: epgstation
            MYSQL_PASSWORD: epgstation
            MYSQL_ROOT_PASSWORD: epgstation
            MYSQL_DATABASE: epgstation
            TZ: "Asia/Tokyo"
        command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --performance-schema=false --expire_logs_days=1 # for mariadb
        restart: always
        logging:
            options:
                max-size: "10m"
                max-file: "3"

    epgstation: # ← !!!この部分!!!
        container_name: epgstation-v2
        build:
            context: "./epgstation"
            dockerfile: "debian.Dockerfile"
        volumes:
            - /home/euser/git/docker-mirakurun-epgstation/epgstation/config/run.sh:/app/config/run.sh
            - /etc/localtime:/etc/localtime:ro
            - ./epgstation/config:/app/config
            - ./epgstation/data:/app/data
            - ./epgstation/thumbnail:/app/thumbnail
            - ./epgstation/logs:/app/logs
            - /mnt/data1:/app/recorded
        environment:
            TZ: "Asia/Tokyo"
        depends_on:
            - mirakurun
            - mysql
        ports:
            - "8888:8888"
            - "8889:8889"
        #user: "1000:1000"
        restart: always

volumes:
    mysql-db:
        driver: local

必ず「--no-cache」をつけてください。つけないと古いレイヤーが使われ変更が反映されない場合があります。

ビルド実行
スクリーンショット 2025-10-05 024446.png

ビルドが終わったらEPGStationを立ち上げます。

cd ~/git/docker-mirakurun-epgstation  (Pathは自分の環境に合わせて変えry)
docker compose up -d 

Dockerコンテナ内でcURLが使えるか確認

docker exec -it epgstation-v2 bash
curl --version

トラブルシューティング

ありがちなトラブルです。

無効なオプションです。と表示される

bash run.sh
: 無効なオプションです set: 使用法: set [-abefhkmnptuvxBCEHPT] [-o option-name] [--] [-] [arg ...] run.sh: 行 5: $'\r': コマンドが見つかりません run.sh: 行 12: $'\r': コマンドが見つかりません run.sh: 行 18: 予期しないトークン $'{\r'' 周辺に構文エラーがあります 'un.sh: 行 18: escape_json() {

このエラーの原因は基本的にCRLFで保存したことによる「改行コードが Windows(CRLF) のまま(\r が残っている)」または「ファイル先頭に UTF-8 BOM が混入している」です。

対処法 → UnixLFで保存し直してください。

EPGStationから呼び出せない。かつEPGStationのSystemログに以下のようなものが残っている。

[2025-10-04T14:12:50.630] [INFO] system - execute cmd: /bin/bash /app/config/run.sh delete 
[2025-10-04T14:12:50.664] [ERROR] system - failed: /bin/bash /app/config/run.sh delete. exit: 1

exit: 1は「EPGStation がスクリプトを呼べているがスクリプトが途中で失敗した」ことを意味します。
このエラーはcURLがインストールされていない環境で起きやすいです。cURLがインストールされているか確認し、されていなければインストールしてください。
インストール方法

#Dockerコンテナへ入る(dockerを使っていない場合はスキップ)
docker exec -it epgstation-v2 /bin/bash
#パッケージリストの更新
apt update
#cURLのインストール
apt install curl

exit: 2と表示されてプログラムが動かない(以下のようなエラーログが出る。)

euser@SV-REC01:~/git/docker-mirakurun-epgstation$ docker exec -it epgstation-v2 /bin/sh -x /app/config/run.sh reserve || echo "exit:$?" 
+ set -eu + 
+ LINE_TOKEN=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ LINE_TO=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ [ 1 -ne 1 ] 
+ ret=reserve 
+ CHANNELNAME=放送局名なし 
+ NAME=タイトル未設定 
+ DESCRIPTION=番組概要が指定されていません。 
+ EXTENDED= 
+ STARTAT_MS= 
+ ENDAT_MS= 
+ DURATION_MS= 
+ ERROR_CNT=N/A 
+ DROP_CNT=N/A 
+ SCRAMBLING_CNT=N/A 
+ start_epg_time= 
+ end_epg_time= 
+ [ -n ] 
+ [ -n ] 
+ epoch_to_jst 
+ local epoch_s= 
+ [ -z ] 
+ printf %s 未設定 
+ return 
+ startat=未設定 
+ epoch_to_jst 
+ local epoch_s= 
+ [ -z ] 
+ printf %s 未設定 
+ return 
+ endat=未設定 
+ [ -n ] 
+ duration_minutes=未設定 
+ printf -v content %s\n%s\n%s\n%s ~ %s %s分\n%s\n%s ✅ 予約追加 タイトル未設定 放送局名なし 未設定 未設定 未設定 番組概要が指定されていません。 /app/config/run.sh: 98: printf: Illegal option -v exit:2

exit: 2とは シェルスクリプト自体が呼び出せているが、中でエラーになって異常終了している。ことを意味します。
これはrun.shの記述ミスが主な原因です。上記のエラーの場合はprintf -vというオプションが使えなかったということを意味します。
dockerなどの軽量環境では使えないオプションがあるようです。(printf -vなど)なのでこのページのrun.shはprintf -vを使わないように修正済ですが、同様に環境によって他の部分でエラーがでる可能性があります。その場合はrun.shを修正してください。

追記

APIの利用上限に一瞬で到達してしまったので、録画開始とエンコード開始・終了あと各種異常以外は送信しないようにしたほうがいいかもしれません。

設定項目名 イベント発生タイミング
reserveNewAddtionCommand 新しい予約が追加されたとき
reserveUpdateCommand 既存の予約が更新されたとき
reservedeletedCommand 予約が削除されたとき
recordingPreStartCommand 録画開始直前(チューナー準備中)
recordingPrepRecFailedCommand 録画準備に失敗したとき
recordingStartCommand 録画が開始されたとき
recordingFinishCommand 録画が完了したとき
recordingFailedCommand 録画中に失敗したとき
encodingFinishCommand エンコードが完了したとき

デフォルトだと結構たくさん来ます。
Screenshot_20251004-235422.png

参考サイト

4
0
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
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?