mcpField
T
Tennis Evolution

Tennis Evolution

ローカル
tennis-evolution.pages.devメディア・デザイン01 週間前に更新

Tennis Evolution について

Tennis Evolution は、指定したハイライト一覧からテニス動画をラベル付きリールにするローカルのコマンドライン・ウェブツールです。キーフレームに合わせた無劣化クリップを作成して出力を検証し、動画はローカルに保持します。

主な機能

  1. 01区間リストからハイライトリールを作成
  2. 02キーフレーム単位の無劣化カット
  3. 03打球数、場所、時刻のラベル追加
  4. 04カット時の HDR と回転メタデータ保持
  5. 05出力を検証してマニフェストを作成

活用シーン

  1. 01手動で指定したラリーからリールを作成
  2. 02別の検出ツールが出力した区間を処理
  3. 03クリップの整合性と音声・映像の同期を確認

MCP 対応

stdio の MCP サーバーは、動画の検査、ハイライトの順位付け、リール作成ジョブの開始と状態確認、動画検証、ライセンス状態管理のツールを公開します。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

mcp.json · 共通設定
{
"mcpServers": {
"bobobo2026-tennis-evolution": {
"command": "uvx",
"args": [
"tennis-evolution"
]
}
}
}
起動コマンドuvx tennis-evolution

ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
pypitennis-evolution0.2.0

ツール

7

掲載時のツール一覧 · 2 週間前に更新

パラメーター型必須説明
videostringはいローカル動画のパス。

詳細

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ライセンスの確認/有効化/削除を行います。
mcpMCPサーバー(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 match2つのストリームの長さの差 ≤ 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

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。