mcpField
Z
zahori

zahori

ローカル
github.com/josesepulvedapinoブラウザ自動化44 週間前に更新

zahori について

zahoriは実際のブラウザーでページを操作し、ネットワークリクエストを調べてメディアストリームを見つけます。HLS、DASH、MP4、音声の情報を必要とするユーザー向けで、再利用可能なJSONサイトプロファイルに対応し、DRMコンテンツは拒否します。

主な機能

  1. 01ブラウザーでページを操作しリクエストを捕捉
  2. 02ストリームURLと再生用ヘッダーを取得
  3. 03HLS、DASH、MP4、音声を識別
  4. 04言語別の音声トラック選択
  5. 05JSONサイトプロファイルの作成と修復
  6. 06DRMコンテンツの検出と拒否

活用シーン

  1. 01ウェブプレーヤーのメディアURLを特定
  2. 02ダウンロードツールに再生用ヘッダーを渡す
  3. 03難しいサイト向けに再利用可能なプロファイルを作成
  4. 04サイト変更後にプロファイルをテストして修復

MCP 対応

zahoriはMCPサーバーとして、サイトの調査、プロファイルのテストと保存を行うツールをエージェントに提供します。これらのツールでストリームを見つけ、サイト固有の手順を学習できます。

設定

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

mcp.json · 共通設定
{
"mcpServers": {
"josesepulvedapino-zahori": {
"command": "npx",
"args": [
"-y",
"zahori"
]
}
}
}
起動コマンドnpx -y zahori

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

パッケージ
npmzahori0.1.1

ツール

6

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

パラメーター型必須説明
urlstringはいプレーヤーを含むページ。
langstringいいえ多言語ストリームで優先する音声言語(例:es)。

詳細

zahori

あらゆるウェブページの背後にあるメディアストリームを見つけます。

CI npm version node license

実際のブラウザーでページを開き、オーバーレイを閉じて再生ボタンを押し、メディアリクエストが現れるまでネットワークを監視します。ストリーム URL(HLS、DASH、MP4、または音声)と、再生に必要なヘッダーを取得できます。

$ npx zahori get https://example.org/live
https://cdn.example.org/hls/live/master.m3u8

サイトごとの設定は不要です。抽出器の対応を待つ必要もありません。ブラウザーで再生できるものなら、zahori で見つけられます。

目次

機能

  • どの URL でもすぐに使えます。 組み込みの汎用フローで、ほとんどのページを設定なしで処理できます。
  • 実際のブラウザーエンジンを使用。 Playwright がバックグラウンドでヘッドレスブラウザーを操作します。複数の言語に対応し、同意バナー、再生ボタン、iframe プレーヤーを自動処理します。
  • 再生用ヘッダーも取得。 実際のリクエストから Referer/Origin/UA/Cookie を取得するため、ffmpeg などで 403 エラーになりません。
  • HLS に対応。 マスタープレイリストとメディアプレイリスト、ライブと VOD の判定、多言語ストリームの音声レンディションの言語別選択に対応します。
  • 学習可能。 難しいサイトは小さな JSON プロファイルにして一度保存すれば、その後は常に同じように処理できます。
  • エージェントネイティブ(MCP)。 コーディングエージェントがサイトを調査し、プロファイルを作成・テストして保存できます。
  • 自己修復機能。 zahori heal は、BYO キーのモデルを使ってサイトの変更に応じてプロファイルを修復します。保存前に客観的なオラクルで検証します。
  • DRM を拒否する設計。 保護されたコンテンツは常に検出して拒否します。

zahori を選ぶ理由

ウェブのロングテールでは、ダウンローダーが対応していない埋め込みプレーヤーを使って配信しているサイトが数多くあります。地方のテレビ局やラジオ局、ライブイベントのページ、小規模な動画ポータルなどです。yt-dlp は、抽出器を整備している大手プラットフォームに対しては非常に優れています。しかし、ロングテールには抽出器がなく、サイトごとに手作業で作成する方法では規模を拡大できません。

yt-dlpzahori
対応範囲厳選された約 1,800 のサイトブラウザーで開けるあらゆるページ
方法サイトごとの抽出器コード実際のブラウザーとネットワークの監視
新しいサイトメンテナーの対応を待つ汎用的に動作するか、数分で学習させる
サイトの変更パッチが適用されるまで抽出器が動作しないzahori heal がプロファイルを修復

両者は相互に補完します。YouTube には yt-dlp を使い、抽出器が作られていないページには zahori を使ってください。

インストール

npm install -g zahori   # CLI
npm install zahori      # library

要件

Node≥ 22
ブラウザーnpx playwright install chromium --only-shell を一度実行してください。実行しない場合は、インストール済みの Google Chrome が使用されます
ffmpegオプションです。--validate、--download、および検出オラクルでのみ使用します

pnpm を使用する場合: pnpm はデフォルトで依存関係のビルドスクリプトをブロックするため、Playwright はブラウザーを自動ダウンロードしません。上記の playwright install の行を一度実行するか、フォールバックとしてシステムの Chrome が使用されます。

CLI

# Resolve the stream URL behind a page (URL to stdout, everything else to stderr)
zahori get https://tv.example.org/live

# Full result as JSON: url, kind, live/VOD, replay headers, all candidates
zahori get https://tv.example.org/live --json

# Prefer an audio language on multilingual streams
zahori get https://tv.example.eu/live --lang es

# Record it (replays the captured headers; needs ffmpeg)
zahori get https://tv.example.org/live --download session.mp4
zahori get https://tv.example.org/live --audio session.m4a

# Check the stream is real media, not a bumper or geo-block slate
zahori get https://tv.example.org/live --validate

# Watch the browser work
zahori get https://tv.example.org/live --headful

--json の出力例:

$ zahori get https://example.org/watch --json
{
  "url": "https://cdn.example.org/hls/master.m3u8",
  "kind": "hls",
  "headers": {
    "referer": "https://example.org/",
    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ... Chrome/150.0.0.0 Safari/537.36"
  },
  "profileId": "generic",
  "candidates": [
    "https://cdn.example.org/hls/master.m3u8",
    "https://cdn.example.org/hls/720p/index.m3u8",
    "https://cdn.example.org/hls/1080p/index.m3u8"
  ]
}

解決された URL は署名付きで、有効期間が短いことがよくあります。zahori は実行のたびにストリームを新たに特定するため、URL はすぐに使用し、保存しないでください。

ライブラリ

import { resolve } from 'zahori';

const stream = await resolve('https://tv.example.org/live', {
  audioLanguage: 'es', // optional, for multilingual masters
});

stream.url;     // the media URL
stream.kind;    // 'hls' | 'dash' | 'mp4' | 'audio'
stream.live;    // true = live, false = VOD, undefined = unknown
stream.headers; // Referer/Origin/UA/Cookie to replay (many CDNs 403 without them)

stream.headers を、URL の取得に使用するものへ渡してください。ffmpeg の場合:

import { download } from 'zahori';
await download(stream, 'session.mp4');

エラーは型で分類されています。NoStreamError(キャプチャしたストリームがない場合)と DrmError(保護されたコンテンツを拒否した場合)です。

お使いのブラウザーを使用する

ログインが必要なサイトでは、ストレージ状態を持つコンテキストなど、ご自身で管理する Playwright コンテキスト内で zahori を操作してください。

import { runProfileOnPage, GENERIC_PROFILE } from 'zahori';

const ctx = await browser.newContext({ storageState: 'auth.json' });
const page = await ctx.newPage();
const stream = await runProfileOnPage(page, GENERIC_PROFILE, url);

プロファイル:zahori がサイトを学習する仕組み

zahori にはサイトの知識が一切ありません。ほとんどのページは組み込みの汎用フローで解決できます。解決できない場合は、プロファイルで対応します。プロファイルは、サイトの開き方(クリックする要素、メディアリクエストの認識方法、選択する候補)を記述した小さな JSON ファイルです。プロファイルはコードではなくデータです。エンジンが実行時に AI を使わず、決定論的に解釈します。

{
  "id": "tv-example-org",
  "match": ["^https?://([^/]*\\.)?tv\\.example\\.org([/:?#]|$)"],
  "steps": [
    { "action": "goto" },
    { "action": "dismissOverlays", "selectors": [] },
    { "action": "click", "selector": ".broadcast-start" }
  ],
  "sniff": { "kinds": ["hls"], "urlPattern": "/live/" }
}

プロファイルは、プロジェクト内の .zahori/profiles/(本番環境やチームメンバーの環境でも使えるよう、コミットしてください)またはグローバルな ~/.zahori/profiles/ に保存されます。プロファイルに保存されるのは、ストリームを再導出する方法であり、ストリーム URL ではありません。そのため、署名付き URL や有効期限付き URL が問題になることはありません。

zahori にサイトを学習させる

コーディングエージェントを使う場合(MCP)

zahori は MCP サーバーです。MCP に対応したエージェントなら、サイトを調査し、プロファイルを提案し、オラクルでテストして、合格した場合に保存できます。すでにお持ちのサブスクリプションを使用するため、API キーは不要です。サーバーはプロトコルのハンドシェイク時にワークフローの指示をエージェントに送信するため、どのクライアントでも同じように動作します。

ほとんどのクライアントでは標準の設定を使用できます。

{
  "mcpServers": {
    "zahori": { "command": "npx", "args": ["-y", "zahori", "mcp"] }
  }
}
クライアント設定
Cursor上記のブロックを ~/.cursor/mcp.json(またはプロジェクトごとの .cursor/mcp.json)に追加します
VS Code / Copilot.vscode/mcp.json で、"mcpServers" ではなく "servers" キーの下に追加します
Windsurf~/.codeium/windsurf/mcp_config.json
Claude Codeclaude mcp add zahori -- npx -y zahori mcp
Codex CLIcodex mcp add zahori -- npx -y zahori mcp
Gemini CLIgemini mcp add zahori npx -y zahori mcp
Claude Desktop上記のブロックを claude_desktop_config.json に追加します

次に、*「https://tricky.example.org のストリームを特定して、プロファイルを保存して」*と依頼してください。公開されるツールは、zahori_get、zahori_probe、zahori_test_profile、zahori_save_profile、zahori_validate、zahori_list_profiles です。

ヘッドレス実行で独自のキーを使用する場合

cron や CI などの無人パイプラインでは、zahori 自身がモデルを操作できます。まず無料の決定論的な方法を必ず試し、それで失敗した場合にのみトークンを消費します。

export ANTHROPIC_API_KEY=...   # or OPENAI_API_KEY, or a local Ollama
zahori discover https://tricky.example.org --model anthropic:claude-sonnet-5
zahori heal     https://tricky.example.org   # when a saved profile stops working

モデルの指定形式は、anthropic:<model>、openai:<model>、ollama:<model>、compat:<model>(OpenAI 互換の任意のエンドポイント)です。または、一度 ZAHORI_MODEL を設定してください。モデルが行うのはプロファイルの提案のみです。エンジンが各提案を実行し、オラクルが評価するため、検証されていないプロファイルが保存されることはありません。

オラクル

「何かダウンロードされたかどうか」だけでは不十分なテストです。これでは広告の前置き、保留音、地域制限の画面まで合格してしまいます。オラクルは、ストリームを信頼する前に、より確かなシグナルを組み合わせて評価します。

  • デコードプローブ。 ffmpeg で指定範囲をデコードし、音量を測定します。
  • マニフェストの妥当性チェック。 実際のセッションには多数のセグメントがありますが、画面表示には 4 つしかありません。
  • 無音の許容。 指定範囲が無音の場合は、さらに先の範囲で 2 回目のプローブを実施します(正当な休憩時間である可能性があるためです)。無音だけを理由にストリームが失敗することはありません。
  • 明確なエラー。 403/401 の応答は原因不明として扱わず、ヘッダーの問題として報告します。

判定結果は pass、fail、inconclusive のいずれかです。検出処理では、オラクルに合格したプロファイルのみ保存します。

責任ある利用

zahori は、誰でもアクセスでき、保護されていないストリームを対象に構築されています。通常のブラウザーで、すべての訪問者がすでに再生できるページです。ブラウザーがすでに再生しているものを解決するだけで、不正に侵入することはありません。

設計上、zahori は DRM を拒否します。 マニフェスト内の Widevine、PlayReady、FairPlay のマーカーを検出し、明示的な DrmError を返して拒否します。暗号化やアクセス制御を回避しようとすることは決してありません。これは設定で変更できるものではなく、厳守する方針です。

安全に利用できる範囲。 最も明確に安全なのは、サイトがすべての訪問者に提供するオープンな HLS/DASH を、アーカイブ、アクセシビリティ、文字起こし、研究などの合法的な目的で利用することです。利用先を指定する前に、知っておくべき点がいくつかあります。

  • 「公開されている」ことは「パブリックドメイン」であることを意味しません。 ストリームを無料で視聴できても、自由に再利用できるとは限りません。サイトによっては、映像・音声コンテンツに別途ライセンス条件を設けています。サイトの再利用条件を確認してください。
  • DRM がないことと、法律上保護されていないことは同じではありません。 一部の法域では、簡易なトークンや署名方式であっても、それを回避すると、迂回禁止に関する問題(米国 DMCA §1201)が生じる可能性があります。zahori は DRM を拒否し、アクセス制限を決して突破しないことで、安全な側にとどまります。この方針を守ってください。
  • EU では、テキスト・データマイニングに関する例外(DSM 指令第 3 条および第 4 条)により、権利者が機械可読形式でオプトアウトしていない限り、合法的にアクセスできる著作物の複製が認められます。オプトアウトを尊重してください。

利用するサイトの利用規約、著作権、現地の法律を遵守する責任は、利用者にあります。判断に迷う場合は、明示的にオープンなコンテンツを優先し、機関に問い合わせてください。

API

エクスポート機能
resolve(url, opts?)ページの背後にあるストリームを解決します(プロファイルまたは汎用フロー)
validate(stream, opts?)オラクル:これは実際のメディアかどうかを確認します
download(stream, path, opts?)ヘッダーを再現しながら、ffmpeg で記録します
probe(url, opts?)プロファイル作成向けに、ページの構造化された調査を行います
testProfile(profile, url, opts?)候補プロファイルを実行して評価します
saveProfile(profile, dir) / loadProfiles()プロファイルを保存/読み込みます
discoverProfile(url, opts?) / healProfile(profile, url, opts?)モデルを使って学習/修復します
runProfile(profile, url, opts?) / runProfileOnPage(page, ...)プロファイルを実行します(専用ブラウザー/利用者のブラウザー)
hostPattern(url) / profileIdFromUrl(url)プロファイル作成用のヘルパー

パッケージには、TypeScript の型定義一式が含まれています。

ドキュメント

詳しいガイドは docs/ にあります。

  • CLI:すべてのコマンドとフラグ
  • ライブラリ API:エクスポートされる関数と型
  • プロファイル:zahori にサイトを教えるための JSON 形式
  • MCP:コーディングエージェントから zahori を使用する方法
  • レシピ:最初から最後までの実例

コントリビューション

Issue や PR を歓迎します。開発環境のセットアップ、テストスイート、リリースプロセスについては、CONTRIBUTING.md をご覧ください。

ライセンス

MIT © Jose Sepulveda

コメント

MCP は初めてですか?

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

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