Files
tver/PROJECT.md
T

101 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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 を出す等)を実機で確かめる [要確認]