Tennis Evolution について
Tennis Evolution は、指定したハイライト一覧からテニス動画をラベル付きリールにするローカルのコマンドライン・ウェブツールです。キーフレームに合わせた無劣化クリップを作成して出力を検証し、動画はローカルに保持します。
主な機能
- 01区間リストからハイライトリールを作成
- 02キーフレーム単位の無劣化カット
- 03打球数、場所、時刻のラベル追加
- 04カット時の HDR と回転メタデータ保持
- 05出力を検証してマニフェストを作成
活用シーン
- 01手動で指定したラリーからリールを作成
- 02別の検出ツールが出力した区間を処理
- 03クリップの整合性と音声・映像の同期を確認
MCP 対応
stdio の MCP サーバーは、動画の検査、ハイライトの順位付け、リール作成ジョブの開始と状態確認、動画検証、ライセンス状態管理のツールを公開します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
7掲載時のツール一覧 · 2 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| video | string | はい | ローカル動画のパス。 |
詳細
tennis-evolution · テニス動画 → コーナー表示付きハイライト集
SwingVision風のハイライトを作れる、オープンソースのローカル代替ツールです。 1時間のテニス録画から、ラリーの最長順にまとめた動画を作成し、打球数、会場、撮影時刻を映像に焼き付けます。クリップは無劣化で、iPhoneのHDRも保持され、アップロードもアカウント登録も不要です。無料版(1リールにつき5ラリー)または一度きりの支払いでPro(19ドル)をご利用いただけます。CLI、ローカルのWebページ、またはMCPサーバー(uvx tennis-evolution mcp)経由で、あらゆるAIエージェントから利用できます。
比較記事:テニスハイライトアプリの比較 ·
SwingVisionとの比較 ·
Tennis Cutとの比較。
1~2時間のテニス動画から、「ラリーだけ」のハイライト集をいくつか作成し、映像に打球数/場所/撮影時刻/元動画のタイムスタンプを表示します。 ハイライトの検出は任意のツールまたは手作業で行い(例:sliceappの打球リスト)、編集、結合、コーナー表示、検証はすべてローカルで完結します。
公式サイト/オンラインデモ:https://tennis-evolution.pages.dev/(英語がメインのサイトで、中国語版は /zh/ にあります。
デモ動画はCC0素材を使って本ツールで生成したもので、オンラインで再生できます。ソースコードは site/ にあります。サイトではオンラインレンダリングを提供していません。レンダリングは常にローカルで行われます。)
このリポジトリは、実際の作業をきっかけに生まれました。47分29秒のiPhone録画動画(1080p縦向き、HEVC 10-bit HDR)から、最長のラリー5つ(40/36/27/24/24打)を切り出し、3分49秒のコーナー表示付きハイライト集にまとめました。 作業中に遭遇した問題(音声と映像のずれ、結合時の破損フレーム、HDRの色ずれ、
drawtextの不足)は、すべてコード内のルールと自己検証項目として組み込まれています。
长录像 ──► 高光列表 ──► 关键帧无损切片 ──► 一次性拼接重编 ──► 角标烧录 ──► 自检
(MOV/HDR) (txt/json) (c=copy) (trim+concat) (PNG overlay) (verify)
1つのコマンドで実行
tennis-evolution all IMG_5155.MOV \
--highlights highlights.txt \
--top 5 \
--place "宁波 ECHO Tennis" \
--timezone Asia/Shanghai \
--outdir out
出力:
out/
├── clips/
│ ├── 01_40hits_27m14s-28m08s.mp4 # 1 号长回合,无损切片(原画质、HDR)
│ ├── 02_36hits_38m49s-39m38s.mp4
│ └── ...
├── labels/label_01.png # 角标图层(透明 PNG,可单独复用)
├── reel_plain.mp4 # 合集(无角标)
├── reel_labeled.mp4 # 合集(带角标)
├── highlights.normalized.json # 本次实际使用的切片清单
└── manifest.json # 全部参数 + 每个文件的校验结果
コマンドの終了時に verify PASS/FAIL が表示されます。失敗すると終了コード1で終了するため、スクリプトに直接組み込んだり、エージェントに実行させたりできます。
Web版(ローカルブラウザーで利用)
コマンドを入力したくない場合は、ローカルホストのみをリッスンするWebページを起動します(追加の依存関係は不要で、標準ライブラリのみ使用します)。
tennis-evolution web --open # 默认 http://127.0.0.1:8787
# 或:PYTHONPATH=src python -m tennis_evolution.webapp --port 8787
ページには2つの入り口があります。
- 完成品を試す —— すでにレンダリング済みのデモを直接再生します(ワークスペースに
demo_run/がある場合)。待ち時間なしで、コーナー表示付きハイライト集、5つの無劣化クリップ、各ファイルの検証内容、ダウンロードを確認できます。 - 自分のハイライト集を作成 —— ローカルの動画ファイルのパスを入力するか、動画をページにドラッグします(素材はローカルにのみ保存され、外部サービスにはアップロードされません)。打球リストを貼り付け、保持する件数/並べ替え/場所/タイムゾーン/画質プリセットを選ぶと、処理段階の進捗とffmpegの進捗バーがリアルタイムで表示されます。終了後は、プレーヤー、クリップリスト、自己検証表、ダウンロードを利用できます。
出力は webapp-runs/<job_id>/ に保存されます(gitignoreで除外済み)。パラメーターと自己検証結果はCLI版と同じ構成です(manifest.json)。
API仕様、エラーコード、進捗モデルについては docs/webapp.md を参照してください。
インストール
ffmpeg / ffprobeが必要です(数十MBの重複配布を避けるため、同梱していません)。
# macOS
brew install ffmpeg
# Ubuntu / Debian(顺带装中文字体,角标需要)
sudo apt install ffmpeg fonts-noto-cjk
次に、本ツールをインストールします(Python ≥ 3.11)。
# 需要内置音频检测时加 [detect](会装 librosa)
# pipx install "tennis-evolution[detect]@git+https://github.com/bobobo2026/tennis-evolution"
# 直接安装(推荐,pipx 会隔离环境)
pipx install tennis-evolution
# 或者从源码开发
git clone https://github.com/bobobo2026/tennis-evolution
cd tennis-evolution
pip install -e ".[dev]"
インストールしたくない場合は、
uvx tennis-evolution …で直接実行できます。mainブランチの最新コードを使う場合は、pipx install git+https://github.com/bobobo2026/tennis-evolutionを実行してください。
入力:ハイライトリスト
「開始・終了時刻+任意の打球数」を指定できるツールなら何でも使えます。形式はシンプルなほど便利です。
sliceappからエクスポートしたテキスト(そのまま貼り付けられます。ヘッダーとコメントは無視されます)。
Highlights — IMG_5155.m4a (made with sliceapp.so/tools/)
2:15 - 2:52 Long rally (24 hits)
27:14 - 28:08 Long rally (40 hits)
38:49 - 39:38 Long rally (36 hits)
JSON(独自の検出器または手作業で整理したもの)。
{
"segments": [
{"start": "27:14", "end": "28:08", "hits": 40, "kind": "Long rally"},
{"start": 135, "end": 172, "hits": 24}
]
}
並べ替えのデフォルトは --sort hits です。まず打球数、次に時間、最後に時刻の順で並べ替えるため、「最長ラリー」が常に先頭になり、結果を再現できます。
よく使うコマンド
| コマンド | 用途 |
|---|---|
probe VIDEO | 解像度、回転、HDR、録画時刻、すべての音声トラックを確認します(iPhoneでは、ffmpegでデコードできない空間オーディオのトラックが含まれることがよくあります)。 |
keyframes VIDEO | キーフレームと平均GOP長を一覧表示します(クリップをどれだけ正確に切り出せるかが決まります)。 |
highlights LIST --top 5 | 並べ替え結果だけを確認します。動画には触れません。 |
cut VIDEO --highlights LIST --outdir clips/ | 無劣化クリップのみを切り出します。結合は行いません。 |
reel VIDEO --highlights LIST --place "..." --out reel.mp4 | ハイライト集のみを作成します(コーナー表示を追加できます)。 |
all VIDEO --highlights LIST --outdir out/ | 全工程を実行し、自己検証とmanifestの生成も行います。 |
detect VIDEO --top 5 --out h.json | 音声のみでラリーを検出します(librosa)。cut/reelにそのまま渡せるファイルを生成します。 |
verify FILE | 自己検証を単独で実行します。 |
concat CLIP... --out FILE | 無劣化結合の代替手段です(タイムスタンプの問題があれば報告します。下記参照)。 |
license [activate KEY|deactivate] | Proライセンスの確認/有効化/削除を行います。 |
mcp | MCPサーバー(stdio)として実行し、AIエージェントから呼び出せるようにします。 |
この方法を採用している理由
1. クリップは「ミリ秒単位の正確さ」ではなく、キーフレームに合わせて切り出します
-c copyでは再エンコードできないため、クリップを切り出せる位置はキーフレームに限られます。GOPの途中で強制的に切ると、末尾の数フレームで参照フレームが失われ(プレーヤーではブロックノイズや緑色のフレームとして表示されます)、一方、iPhoneのGOPは約1秒です。キーフレームに合わせることで増える映像は数百ミリ秒程度ですが、ビット単位で無劣化となり、HDR/回転のメタデータも完全に保持されます。
そのため、--lead 1.0 --tail 1.5の適用後、最も近いキーフレームまで範囲を広げます。実際の cut_start/cut_end は manifest.json に記録されます。
2. ハイライト集は元動画から一度だけ再エンコードする必要があり、concat -c copyは使えません
無劣化クリップをconcat demuxerで直接結合すると、(本プロジェクトで実際に確認した)次の3つの問題が発生します。
- 各クリップの音声開始位置と映像開始位置は、音声パケット1つ分にも満たない差ですが、結合後にffmpegが
Non-monotonic DTSを繰り返し報告します。 - 完成動画は音声より映像が1.01秒遅れて始まり、素材全体で音声と映像が恒常的にずれます。
- HEVCのクリップ間で参照フレームが途切れ、
Could not find ref with POCが報告され、切り替わり後に破損フレームが表示されます。
そのため、reelでは常に「trim → concat → 1回のエンコード」を行い、音声と映像をサンプル単位で同期させ、GOPの途切れを防ぎます。
concatサブコマンドは緊急時の代替手段として残していますが、問題を隠して成功したように見せるのではなく、上記の問題をそのまま報告します。
3. コーナー表示にはdrawtextではなくPNGオーバーレイを使います
ffmpegの配布版の多く(Homebrewのデフォルトビルドを含む)にはlibfreetypeが含まれておらず、drawtext自体が使えません。
本ツールではPillowで透過PNGをレンダリングしてから overlay を適用します。これにより、フォントを制御でき(CJK文字がぼやけません)、レイアウトもデザインでき、同じPNGをほかのソフトウェアでも再利用できます。HDR素材でも、半透明の暗い背景を使って白文字を読みやすく保ちます。
4. 出力は必ず自己検証します
verifyは、デコードエラーがないこと、音声と映像の長さが一致していること、両方のストリームが0秒から始まること(音声と映像のずれを検出するため)、先頭と末尾のフレームが黒くないこと、音声が無音ではないことを確認します。allは結果を manifest.json に書き込み、終了コードにも反映します。
環境と互換性
- HDR:ソース動画は HLG(iPhone で一般的で、Dolby Vision profile 8 も同時に含まれる場合があります)です。リールの出力では HLG の色彩タグと 10-bit を維持します。 Dolby Vision の RPU 動的メタデータは再エンコード時に破棄されます(x265 は書き戻しに対応していません)。HDR10/HLG のベースレイヤーは保持されます。 SDR のみ対応するプラットフォームに投稿する場合は、必要に応じて tonemap を追加してください(内蔵していません。クリエイターの選択を隠さないためです)。
- エンコーダー:デフォルトは
libx265(--crf 19 --preset fast、M シリーズ Mac で約 2.3 倍速、3 分 49 秒の動画なら約 100 秒)です。 x265 がない環境では--codec x264でフォールバックできます(8-bit、プレビュー向け)。 - 回転:デフォルトでは縦向きの方向を映像に焼き込みます(
1080×1920)。一部のプレーヤーやプラットフォームが回転メタデータを無視するのを防ぐためです。メタデータ方式を維持する場合は--keep-rotationを指定します。 - タイムゾーン:角ラベルの時刻 = ソース動画の
creation_time+ 該当ラリーの開始時刻です。表示するタイムゾーンは--timezoneで指定します。creation_timeがない場合はファイルの更新日時を使用し、警告を表示します。
AI エージェントで使う(MCP / Claude Code プラグイン / スキル)
エージェントに「この録画の中から最も長いラリーを5つ選んで、角ラベル付きのリールにして」と伝えるだけで、あとは自動で処理します。
Claude Desktop のワンクリックインストール:tennis-evolution.mcpb をダウンロードし、ダブルクリックするか Claude Desktop の「設定 → 拡張機能」にドラッグしてください(ローカルに ffmpeg がインストールされている必要があります。Pro ライセンスと ffmpeg のディレクトリは拡張機能の設定で指定できます)。パッケージのソースファイルは mcpb/ にあります。
MCP(Claude Desktop / Claude Code / Cursor / Codex / Windsurf など、任意の MCP クライアント):
{
"mcpServers": {
"tennis-evolution": {
"command": "uvx",
"args": ["tennis-evolution", "mcp"]
}
}
}
Claude Code は次の1行でインストールできます:
claude mcp add tennis-evolution -- uvx tennis-evolution mcp
公開されるツール:probe_video → rank_highlights → start_highlight_reel(バックグラウンドタスク)→ get_job(ポーリングし、完了後に
manifest を返します)→ verify_video。さらに license_status / activate_license も使用できます。レンダリングは子プロセスで実行されるため、長時間のタスクでエージェントがブロックされることはありません。
Claude Code プラグイン(スキルと MCP をまとめてインストール):
/plugin marketplace add bobobo2026/tennis-evolution
/plugin install tennis-evolution@tennis-evolution
スキルのみ:skills/tennis-evolution/SKILL.md は、スキルに対応する任意のエージェントに直接コピーできます(例:~/.claude/skills/、~/.dsh/skills/)。
無料版と Pro
| 無料 | Pro(買い切り $19 / ¥138、永久) | |
|---|---|---|
| ローカルレンダリング、無劣化切り出し、セルフチェック、MCP | ✅ | ✅ |
| 保持できるラリー数 | 最大 5 本 | 無制限(--top 0 = すべて) |
| 角ラベル付きリールの右下に表示されるウォーターマーク | あり(tennis-evolution · free) | なし |
購入先:https://tennis-evolution.pages.dev/#pricing(海外のクレジットカード / Apple Pay / Google Pay、中国国内の WeChat Pay / Alipay)。
支払い後、ページに te1.… ライセンスが表示されます:
tennis-evolution license activate te1.xxxxx # 或环境变量 TENNIS_EVOLUTION_LICENSE
tennis-evolution license # 查看状态
ライセンスは Ed25519 署名によるオフライン検証に対応しており、有効化時もレンダリング時もネットワークに接続しません。素材がローカル端末から外部に送信されることはありません。
検出処理はどうするのですか?
このツールには、意図的に打球検出を内蔵していません。打球数(40 hits)の集計には信頼できる音声トランジェント検出器が必要であり、調整はコートの残響、マイクとの距離、複数のボールが同時に着地するかどうかに左右されます。これを編集ツールに組み込むと、パイプライン全体が壊れやすくなります。
現在の設計は「検出機能をプラグイン可能にする」ことです。時間区間を出力できるツールであれば、どれでも入力に使えます。
自分で実装する場合の難易度評価とロードマップは docs/detection.md を参照してください。onset 検出で候補となる打球点を見つけるのは難しくありません。
難しいのは「打球 / 着地 / 反響」の区別、ラリーのクラスタリング、および 90% を超えるカウント精度を達成するための調整です。
セルフチェック項目一覧
| チェック | 説明 |
|---|---|
| decode clean | 全編をエラーなしでデコード(ffmpeg -v error で出力なし) |
| start offset | 動画と音声がどちらも 0 から始まり、> 0.05 s の場合は音画ずれと判定 |
| A/V duration match | 2つのストリームの長さの差 ≤ 0.3 s |
| duration | 予想される合計時間(各クリップの長さの合計)と一致 |
| frame not black | 最初と最後のフレームの YAVG ≥ 40(黒画面や破損フレームを防止) |
| audio not silent | 平均音量 > -70 dB |
開発
pip install -e ".[dev]"
pytest -q # 单元测试 + 用 ffmpeg 合成小视频的集成测试
ruff check . && ruff format --check .
リポジトリで作業する AI エージェントは、まず AGENTS.md を読んでください。編集時に守るべき4つの不変条件、モジュールの構成図、よくある変更の対象箇所、完了の定義が記載されています。
英語の概要
tennis-evolution は、長時間のテニス録画から、角ラベル(打球数、会場、時刻、ソースのタイムスタンプ)を焼き込んだハイライトリールを作成します。スライスリストは sliceapp、任意の検出ツール、または手作業で用意してください。あとはツールがすべてローカルで処理します:
- キーフレーム精度の無劣化切り出し(
-c copy、再エンコードなし、HDR / 回転を保持); - 同期を維持したリールの結合を1回の再エンコードで実行(単純な
concat -c copyでは A/V に 1.01 秒のずれが発生し、HEVC の参照フレームも破損しました。詳しくはdocs/pipeline.mdを参照してください); - Pillow で角ラベルを描画し、PNG オーバーレイとして合成(libfreetype なしの ffmpeg ビルドでも動作);
- セルフチェック(デコードエラーなし、開始位置のずれなし、A/V の長さの一致、黒くないフレーム、音量)を
manifest.jsonに記録し、失敗時にはゼロ以外の終了コードを返します。
要件:Python ≥ 3.11、および PATH 上の ffmpeg / ffprobe。検出処理は意図的に対象外です。
ライセンス
MIT
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。