From d7e01878e48304f8f6a3a00eaccde12db9f8aefb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AD=A6=E8=94=B5=E4=B8=80=E5=BC=98?= Date: Sat, 3 Oct 2026 16:31:05 +0900 Subject: [PATCH] =?UTF-8?q?PROJECT.md=20=E3=82=92=E8=BF=BD=E5=8A=A0:=20?= =?UTF-8?q?=E8=A6=81=E4=BB=B6=E5=AE=9A=E7=BE=A9=E3=81=AE=E5=88=9D=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01BcuBr9DyfcqZY8xFQsY5Di --- PROJECT.md | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 PROJECT.md diff --git a/PROJECT.md b/PROJECT.md new file mode 100644 index 0000000..46b9705 --- /dev/null +++ b/PROJECT.md @@ -0,0 +1,100 @@ +--- +title: tver の現状 +tags: + - homelab + - tver +status: 要件定義中 +--- + +# tver の現状 + +> [!info] このファイルの位置づけ +> tver プロジェクトの現状(決定事項・要件・構成・課題)を積み上げていく。運用規約は [[AGENTS]] を参照。 + +## 今の状態 + +- **要件定義中。** 実装はまだ無い +- リポジトリ: `https://gitea.kazu634.com/kazu634/tver.git` + +## 目的 + +TVer(`https://tver.jp/`)で公開中の動画情報を取得し、選んだ動画を yt-dlp でダウンロードし、アプリ内で再生する Web アプリを作る。 + +## 決定事項 + +| 項目 | 決定 | +|---|---| +| TVer 利用規約との関係 | 鑑賞を前提とするダウンロードのため、問題無しと判断(ユーザー判断) | +| 利用者・公開範囲 | 自分のみ・**LAN 内だけ**。EC2 nginx では公開しない | +| 保存先 | **NAS(ds923p)** | +| 自動ダウンロード | **作る**(番組を登録し、新しい回を自動でダウンロードする) | +| 再生 | **アプリの中で再生する** | +| ダウンロード | yt-dlp を使う | +| デプロイ | Dockge で管理する複数コンテナ構成。dockage VM の `/opt/stacks/tver` | +| 開発言語 | **Go**(`web`・`worker` とも)。yt-dlp は外部コマンドとして呼び、進捗・結果は yt-dlp の出力から読み取る | +| DB | **NAS の共有 Postgres**。バックアップは規約どおり `pg_dump` → NAS | +| 定期実行 | **`worker` 内のスケジューラ** | +| NAS のマウント | **NFS**。DSM で `192.168.10.155` のみ許可する | +| 保持期間 | **削除は手動のみ**。自動削除はしない | +| 待ち行列 | **Postgres のテーブルだけで実装する**。専用のキュー基盤は持たない | +| 定期確認の間隔 | 登録番組の新しい回を **24 時間ごと**に確認する | + +## 要件 + +### 機能要件 + +| # | 要件 | 補足 | +|---|---|---| +| F1 | ドラマ・バラエティの新着一覧を表示する | 番組名・回タイトル・放送局・長さ・配信終了日時・サムネイル | +| F2 | 一覧を絞り込む | 予告(「60秒PR」等)を除外できる。ダウンロード済み・待ち行列中を区別して表示する | +| F3 | 選んだ動画をダウンロードの待ち行列に入れる | 複数選択できる | +| F4 | ダウンロードの進捗・結果を表示する | 失敗理由(DRM・地域制限・TVer 側の変更による抽出失敗)を区別して表示する | +| F5 | 同じ回を二重にダウンロードしない | 手動・自動の両方で共通 | +| F6 | 番組(シリーズ)を登録し、新しい回を自動でダウンロードする | 登録・解除・一覧。定期的に新しい回を確認する | +| F7 | ダウンロード済みの動画をアプリ内で再生する | シーク(HTTP Range)に対応する | +| F8 | ダウンロード済みの動画を一覧・削除する | NAS の容量管理のため | +| F9 | 保存ファイルの名前と置き場所を規則で決める | 例: `<番組名>/<番組名> <回タイトル> [<エピソードID>].mp4` | + +### 非機能要件 + +- **yt-dlp を素早く更新できること。** TVer 側の変更で抽出が壊れやすいので、worker のイメージを再ビルドするだけで更新できるようにする +- **TVer への負荷を抑える。** 一覧取得はキャッシュし、同時ダウンロード数は 1〜2 に制限する +- **ブラウザで再生できる形式で保存する。** 映像 H.264 + 音声を MP4 に結合する(ffmpeg が必要) +- 認証は持たない(LAN 内限定のため) +- homelab の規約に従う([[homelab/docs/conventions|運用規約]]): Compose v2、秘匿情報は `.env`、`TZ=Asia/Tokyo` + +## 構成(案) + +| コンテナ | 役割 | +|---|---| +| `web` | UI・API。新着一覧の取得、待ち行列への登録、番組登録、動画の配信(再生) | +| `worker` | Go + yt-dlp + ffmpeg。待ち行列からダウンロードし、登録番組の新しい回を定期的に確認する | + +- DB はコンテナを持たず、NAS の共有 Postgres に接続する(番組登録・ダウンロード履歴・待ち行列) +- 保存先の NAS 共有フォルダは dockage VM に NFS でマウントし、`worker`(書き込み)と `web`(読み取り・削除)にバインドマウントする + +## 外部とのつながり + +| 相手 | 用途 | 備考 | +|---|---|---| +| TVer `platform-api.tver.jp` | 新着一覧(`/service/api/v1/callNewerDetail/{drama\|variety}`)・番組のエピソード一覧 | **非公開 API**。セッションは `/v2/api/platform_users/browser/create` で発行する(yt-dlp と同じ方式) | +| yt-dlp | ダウンロード | TVer extractor を使う | +| NAS ds923p(NFS) | 動画の保存先 | DSM で NFS を有効化し、共有フォルダを `192.168.10.155` のみに許可する | +| NAS ds923p(Postgres) | DB | DSM 内蔵の Postgres が `5432` を使うため、共有 Postgres コンテナの公開ポートを使う。DSM ファイアウォールで `192.168.10.155` のみ許可する | + +## 確認済みの事実 + +- 新着 API は `drama` / `variety` それぞれ 100 件を返す。予告動画も含まれる。各件に `id`・`seriesID`・`seriesTitle`・`title`・`broadcasterName`・`duration`・`endAt`・`thumbnailPath` がある [実機] 2026-10-03 確認 +- dockage VM から TVer API に到達でき(HTTP 200)、送信元は日本と判定される [実機] 2026-10-03 確認 +- yt-dlp 2026.08.19 で TVer のエピソードを抽出できる(`--simulate`)。映像(H.264 / `avc1`)と音声が別ストリームで、結合に ffmpeg が要る。1080p・約 50 分で約 1.2GiB [実機] 2026-10-03 確認 +- yt-dlp の TVer extractor は日本のみ(`_GEO_COUNTRIES = ['JP']`)。DRM 付きの作品は取得できない [公式] https://github.com/yt-dlp/yt-dlp/blob/master/yt_dlp/extractor/tver.py (取得日: 2026-10-03) +- dockage VM に NAS のマウントは無い。ルートの空きは約 20GB [実機] 2026-10-03 確認 + +## 課題 + +- 新着 API が 100 件で打ち切りか、続きを取得できるか [要確認] +- 新着のうち DRM 付きの作品の割合 [要確認] +- 実ダウンロードの所要時間とファイルサイズ(`--simulate` の推定値のみ) [要確認] +- 非公開 API と yt-dlp の TVer 対応は、TVer 側の変更で予告なく壊れうる。壊れたことを検知する手段が要る +- NAS の準備(NFS 共有フォルダ、共有 Postgres へのデータベース・ユーザー作成、DSM ファイアウォール)は DSM での手作業になる。共有 Postgres の現行の公開ポートは [[homelab/docs/inventory|インフラ詳細]] に記載が無い [要確認] +- Go から yt-dlp の進捗を読み取る方式(`--progress-template` と `--print` で 1 行 1 JSON を出す等)を実機で確かめる [要確認]