youtube-downloader
WIP(現在進行中)
Work In Progress
このプロジェクトで現在進行中の作業と、過去のスナップショットを記録する。
現在の状況
https://yclip.org でダウンロードが瞬時に完了し、player_client 指定により取得失敗動画も解消済み。
named tunnel(worker.yclip.org)+ range リクエスト + player_client=web,android で安定稼働。
起動方法(ワーカーMac):
- ターミナル①:
cloudflared tunnel run yclip-worker - ターミナル②:
source ~/yclip-worker/venv/bin/activate WORKER_TUNNEL_URL=https://worker.yclip.org python3 ~/yclip-worker/worker.py
次にやること(優先順):
- Adsterra 広告の埋め込み(マネタイズ開始)
- 1080p 以上の高画質対応(ffmpeg マージ)
- モバイル対応・UX 改善
未決事項:
- ワーカー Mac がオフラインになるとサービス停止する問題(スケール時に Residential Proxy 移行を検討)
- cloudflared / worker を起動時に自動立ち上げする仕組み(launchd など)
過去のWIPアーカイブ
2026-04-25 14:36 時点のスナップショット
https://yclip.org でダウンロードが瞬時に完了する状態。 named tunnel(worker.yclip.org)+ range リクエスト方式で YouTube CDN のスロットリングを回避済み。
起動方法(ワーカーMac):
- ターミナル①:
cloudflared tunnel run yclip-worker - ターミナル②:
source ~/yclip-worker/venv/bin/activate WORKER_TUNNEL_URL=https://worker.yclip.org python3 ~/yclip-worker/worker.py
次にやること(優先順):
- Adsterra 広告の埋め込み(マネタイズ開始)
- 1080p 以上の高画質対応(ffmpeg マージ)
- モバイル対応・UX 改善
未決事項:
- ワーカー Mac がオフラインになるとサービス停止する問題(スケール時に Residential Proxy 移行を検討)
- cloudflared / worker を起動時に自動立ち上げする仕組み(launchd など)
2026-04-25 00:13 時点のスナップショット
https://yclip.org でダウンロードまで含めたエンドツーエンドが動作している。 自宅 Mac をワーカーとして動かし、yt-dlp 実行と CDN プロキシの両方を担わせる構成。
ワーカーの起動方法(別 Mac):
source ~/yclip-worker/venv/bin/activate
python3 ~/yclip-worker/worker.py
起動すると cloudflared Quick Tunnel が自動起動し、VPS にプロキシURLを登録する。
次にやること(優先順):
- Adsterra 広告の埋め込み(マネタイズ開始)
- named tunnel 設定(ワーカー再起動時のURL変動を恒久解決)
- 1080p 以上の高画質対応(ffmpeg マージ)
未決事項:
- ワーカー Mac がオフラインになるとサービス停止する問題(スケール時に Residential Proxy 移行を検討)
- Quick Tunnel はワーカー再起動ごとに URL が変わる(named tunnel で解決予定)
2026-04-24 20:00 時点のスナップショット
https://yclip.org でエンドツーエンドのダウンロードが動作している。 自宅 Mac をワーカーとして動かすことで YouTube の IP ブロックを回避。
ワーカーの起動方法(別 Mac):
source ~/yclip-worker/venv/bin/activate
python3 ~/yclip-worker/worker.py
次にやること(優先順):
- Adsterra 広告の埋め込み(マネタイズ開始)
- 1080p 以上の高画質対応(ffmpeg マージ)
- モバイル対応・UX 改善
未決事項:
- ワーカー Mac がオフラインになるとサービス停止する問題(スケール時に Residential Proxy 移行を検討)
/downloadプロキシの帯域コスト(スケール時に Cloudflare Workers 移行を検討)
2026-04-24 17:00 時点のスナップショット
**https://yclip.org が外部公開済み。**ただし Hetzner のデータセンター IP を YouTube がブロックするため、実際のダウンロードが機能していない。
次にやること(優先順):
- YouTube IP ブロック対策(Residential Proxy または Cookie 認証)
- Adsterra 広告の埋め込み(マネタイズ開始)
- 1080p 以上の高画質対応(ffmpeg マージ)
2026-04-24 14:30 時点のスナップショット
Phase 1 MVP 完成・push 済み。DECISIONS/ROADMAP を含む4ファイル運用に移行完了。
次にやること(優先順):
- Railway デプロイ(
railway upで外部公開) - Adsterra 広告の埋め込み(マネタイズ開始)
- 1080p 以上の高画質対応(ffmpeg マージ)
未決事項:
- yt-dlp がボット検知でブレイクした際の復旧フロー(Cookie 注入 or User-Agent ローテーション)
- 高画質対応時のサーバー側 ffmpeg コスト試算
2026-04-24 14:00 時点のスナップショット
Phase 1 MVP が完成・GitHub push 済み(commit f7480fc)。ローカルで /extract API の動作確認まで完了。
次にやること:
- Railway デプロイ(
railway upで公開) - 1080p 以上の高画質対応(ffmpeg で映像+音声をマージ)
- Adsterra 広告の埋め込み(マネタイズ開始)
未決事項:
- yt-dlp ボット検知でブレイクした際の復旧フロー(Cookie 注入 or User-Agent ローテーション)
- 高画質対応時のサーバー側 ffmpeg コスト試算
ROADMAP(計画)
ロードマップ
今週
- Hetzner VPS にデプロイして外部公開(yclip.org)
- 独自ドメイン取得(yclip.org)
- YouTube IP ブロック対策(自宅 Mac ワーカー構成で解決済み)
- ダウンロードプロキシ修正(Cloudflare Tunnel 経由でワーカーMacが担う)
- named tunnel 設定(worker.yclip.org で固定URL運用)
- ダウンロード速度問題の解決(range リクエスト方式で YouTube スロットリング回避)
- Adsterra 広告を埋め込む(バナー + ページ遷移型)
- cloudflared / worker の自動起動設定(launchd など)
今月
- 1080p 以上の高画質対応(ffmpeg で映像+音声トラックをマージ)
- サムネイル・タイトル・再生時間の UX 改善
- モバイル対応の確認・調整
今四半期
- スケール時に Cloudflare Workers へ /download プロキシを移行(帯域コスト削減)
- プレイリスト対応
- 音声のみ MP3 ダウンロード(ffmpeg で変換)
いつか
- 字幕ダウンロード対応
- 多言語 UI(英語・中国語)
- SEO 対策
DECISIONS(意思決定)
意思決定記録
このプロジェクトで下した重要な意思決定を記録する。 最新が上に来る。
2026-04-25: yt-dlp の player_client は web,android を明示指定する
背景: 一部の動画でデフォルト挙動だと This video is not available が出て取得できない(ブラウザでは普通に再生可能)。yt-dlp のデフォルト client(ANDROID_VR)の制限が原因。
決定: extractor_args={"youtube": {"player_client": ["web", "android"]}} を YDL_OPTS に追加して常に明示指定する。
理由: 動画ごとに利用可能な client が異なるため、フォールバックの効く web,android を指定するのが最も互換性が高い。yt-dlp のデフォルトは YouTube の制限変更に追従して変わるので、明示指定の方が安定運用に向く。
2026-04-25: ダウンロードプロキシは10MBの range リクエストで取得する
背景: 単一の HTTP GET で CDN URL を取得すると、YouTube が長時間接続をスロットリングし、7MB のダウンロードに5分以上かかる状態だった(ratebypass=yes パラメータがあっても効かず)。
決定: プロキシは Range ヘッダで 10MB ずつ分割取得する。yt-dlp と同じ手法。
理由: yt-dlp 直接ダウンロードでは一瞬で完了することから、スロットリングは長時間接続に対して掛かることが判明。短時間の range リクエストを連続で投げると掛からない。
2026-04-25: Cloudflare Tunnel は named tunnel(worker.yclip.org)を使う
背景: Quick Tunnel(trycloudflare.com)は無料で使えるが、Cloudflare 自身が「実験用」と明記しており速度が出ない。再起動ごとに URL も変わる。
決定: named tunnel を作成し worker.yclip.org で固定的に運用する。yclip.org 自体が Cloudflare 管理下にあるためサブドメイン追加のみで完結。
理由: 速度制限がほぼなく、URL も固定で運用が安定する。設定ファイル(~/.cloudflared/config.yml)と認証情報JSONをワーカー Mac に置くだけで済むため運用コストが小さい。
2026-04-25: ダウンロードプロキシをワーカーMac(Cloudflare Tunnel経由)に移す
背景: YouTube CDN URL には ip=<抽出時のIP> が署名として埋め込まれており、VPS 上のプロキシでは IP 不一致で 403 になることが判明した。
決定: ワーカーMac 上でダウンロードプロキシサーバー(port 8081)を起動し、Cloudflare Tunnel(Quick Tunnel)で公開する。VPS の /download はそのトンネルURLへリダイレクトするのみ。
理由: CDN URL はワーカーの IP にバインドされているため、ダウンロードもワーカーの IP から行う必要がある。Cloudflare Tunnel は無料で利用でき、インフラの追加が最小限で済む。
2026-04-24: YouTube IP ブロック対策として自宅 Mac ワーカー構成を採用する
背景: Hetzner のデータセンター IP を YouTube がボットとして弾く。Residential Proxy(月 $10〜50)や Cookie 注入が候補だった。
決定: 自宅 Mac を VPS のジョブワーカーとして使う。VPS はジョブをキューに積むだけで、yt-dlp は自宅の住宅用 IP から実行する。
理由: 無料かつ即座に実装可能。Residential Proxy のコストが不要。自宅ネットが安定していれば実用十分。スケール時は Residential Proxy への移行を検討。
2026-04-24: /download プロキシエンドポイントを追加する(帯域コスト増加を受け入れる)
背景: ブラウザの download 属性はクロスオリジン URL に効かないため、YouTube CDN の直リンクをそのまま渡してもダウンロードにならず再生されてしまう。
決定: FastAPI に /download プロキシエンドポイントを追加し、httpx でストリーミング中継する。「URL 抽出のみ」の設計原則を一部妥協する。
理由: ブラウザのセキュリティ制約上、クロスオリジン URL のダウンロードを強制する手段がない。競合サービスも全員プロキシしている。スケール時は Cloudflare Workers 移行で帯域コストを抑える方針。
2026-04-24: Cloudflare を DNS + SSL レイヤーとして採用する
背景: ドメインを取得後、HTTPS 化と DNS 管理が必要になった。
決定: Cloudflare Free プランを DNS + SSL に使う。SSL モードは「Flexible」(origin は HTTP のまま)。
理由: 無料で SSL・DDoS 対策・CDN が手に入る。Let's Encrypt を自前管理するより運用が楽。
2026-04-24: ドメインを yclip.org にする(お名前.com 初年無料)
背景: コスト優先でドメインを選定。yclip.com はプレミアムドメインで 774,312 円だった。
決定: yclip.org をお名前.com で取得(初年無料)。1年でサービスがうまくいかなければそのまま撤退する。
理由: 初年無料でリスクを最小化できる。サ終時のコストがゼロ。ただし自動更新に注意が必要。
2026-04-24: インフラを Railway → Hetzner Nuremberg に変更する
背景: Railway はデプロイが簡単だが帯域が従量課金で高い。コスト優先で再検討した。
決定: Hetzner の Nuremberg(Regular Performance)を使う。月 €4 程度で 20TB の帯域が付属。
理由: Hetzner Nuremberg は月 €4 + 20TB で、動画 100MB 換算で約 20 万 DL/月まで追加コストゼロ。Railway や Singapore リージョンと比べてコスパが圧倒的に高い。
2026-04-24: 広告ネットワークを AdSense ではなく Adsterra / PropellerAds にする
背景: マネタイズに広告収益を選定。メジャーな AdSense が第一候補だった。
決定: Adsterra または PropellerAds を使う。AdSense は使わない。
理由: YouTube ダウンローダーはグレーゾーンコンテンツとみなされ、AdSense の審査で落とされるリスクが高い。Adsterra / PropellerAds はこの種のサイト向けに実績があり審査も緩い。
2026-04-24: インフラを Railway(無料枠)でスタートする
背景: 初期の運用コストをゼロに近づけたい。
決定: Railway の無料枠でデプロイを開始し、トラフィックが増えたら $5 VPS(DigitalOcean / Vultr)に移行する。
理由: 無料枠で公開できれば PMF 前のコスト負担がない。URL 抽出のみのアーキテクチャなので帯域も食わず、小さいインスタンスで十分。
2026-04-24: バックエンドを Python (FastAPI) + yt-dlp にする
背景: バックエンド言語の選定。Node.js も候補だった。
決定: Python 3.12 + FastAPI + yt-dlp を使う。
理由: yt-dlp が Python ネイティブなので child process 経由より統合が簡潔。FastAPI は非同期対応で、run_in_executor で yt-dlp のブロッキング処理を逃がせる。
2026-04-24: サーバーは URL 抽出のみ(動画データを触らない)
背景: 運用コスト最小化が最優先。サーバーが動画を中継する構成も検討した。
決定: yt-dlp で YouTube CDN の直リンクを抽出してクライアントに返すだけ。動画バイナリはサーバーを通さない。
理由: サーバー中継だと 1000 ユーザー/日で月数万円以上の帯域コストになる。URL 抽出のみなら自サーバーの帯域はほぼゼロで、月 $5〜10 の VPS で十分に動く。
DEVLOG(作業ログ)
開発日誌
このプロジェクトでの作業を時系列で記録する。 最新のエントリが上に来る。
2026-04-25
18:43 - 特定動画で This video is not available が出る問題を解決
やったこと:
- 一部の動画(例:
KjgWWjkNbhU)で yt-dlp がThis video is not availableを返す問題を調査 - ブラウザでは普通に再生できるのに yt-dlp だけ弾かれる症状を確認
- yt-dlp の
--extractor-args "youtube:player_client=web,android"で取得成功することを確認 - worker.py の
YDL_OPTSにextractor_argsを追加して恒久対応
決めたこと:
- yt-dlp の
player_clientはweb,androidを明示指定する(デフォルトの ANDROID_VR では一部動画で失敗するため)
気づき:
- yt-dlp のデフォルト player client 選択は YouTube 側の制限変更で挙動が変わる。明示指定が安定運用には必要
14:36 - ダウンロード速度問題の解決(named tunnel + range requests)
やったこと:
- Quick Tunnel 起動時に cloudflared サブプロセスのパイプバッファ詰まりで接続が確立しないバグを修正(バックグラウンドスレッドでstdoutをドレイン)
- Quick Tunnel の速度が遅い問題を分析し、named tunnel への移行を実施
cloudflared tunnel create yclip-workerで名前付きトンネルを作成cloudflared tunnel route dns yclip-worker worker.yclip.orgで DNS 登録~/.cloudflared/config.ymlでworker.yclip.org → localhost:8081を設定cloudflared tunnel run yclip-workerで常時起動(4本接続が NRT エッジに張られる)
- ワーカーは
WORKER_TUNNEL_URL=https://worker.yclip.orgを環境変数で受け取り VPS に登録 - それでもダウンロードが遅い問題(7MB に5分)を調査
- ローカルプロキシ・トンネルとも単体では速いことを確認
- yt-dlp 直接ダウンロードは一瞬で完了 → YouTube CDN による単一接続スロットリングが原因と特定
- プロキシを range リクエスト(10MBチャンク)方式に変更
- yclip.org でダウンロードが瞬時に完了することを確認
決めたこと:
- ダウンロードプロキシは10MB の range リクエストで取得する(YouTube スロットリング回避)
- Cloudflare Tunnel は named tunnel(worker.yclip.org)を使う
詰まったこと / 気づき:
cloudflared tunnel createのスペルをcreteと誤入力していた- cloudflared を subprocess で起動して URL 取得後にパイプを読まないと、出力バッファが詰まりトンネル接続自体がブロックされる
- YouTube CDN は単一の長時間接続を意図的にスロットルする(
ratebypass=yesパラメータがあっても)。range リクエストで分割するとスロットルされない - Quick Tunnel(trycloudflare.com)は実験用で速度が出にくい。本番運用は named tunnel が必須
次回やること:
- Adsterra 広告の埋め込み
- 1080p 以上の高画質対応(ffmpeg マージ)
- モバイル対応・UX 改善
00:13 - ダウンロードプロキシをワーカーMac経由(Cloudflare Tunnel)に変更・動作確認
やったこと:
/downloadがエラーになる原因を特定:YouTube CDN URL にip=<ワーカーMacのIP>が埋め込まれており、Hetzner VPS からのアクセスが 403 で弾かれていた- ダウンロードプロキシをワーカーMac側に移す構成に変更
worker/worker.py:DownloadProxyHandler(port 8081)を追加、cloudflared Quick Tunnel を自動起動し VPS へ URL 登録する処理を追加backend/main.py:/downloadをRedirectResponseに変更(ワーカープロキシへリダイレクト)、POST /worker/registerエンドポイントを追加
- cloudflared を自宅 Mac にインストール・Cloudflare アカウントにログイン
- ワーカー起動でトンネルURL自動取得・VPS登録が動作することを確認
- yclip.org でダウンロードが正常に動作することを確認
決めたこと:
- ダウンロードプロキシはワーカーMac(Cloudflare Tunnel経由)が担う。VPS はリダイレクトするのみ。
詰まったこと / 気づき:
- YouTube CDN URL は yt-dlp を実行した IP にバインドされている。VPS や別 IP からはアクセス不可。
cloudflared tunnel createのスペルミス(crete)でハマったが、Quick Tunnel で代替。- Quick Tunnel はワーカー再起動ごとに URL が変わるが、起動時の自動登録で対処。
次回やること:
- Adsterra 広告の埋め込み
- named tunnel 設定(Quick Tunnel の URL 変動問題の恒久対策)
- 1080p 以上の高画質対応
2026-04-24
20:00 - 自宅 Mac ワーカー構成で YouTube IP ブロック問題を解決・エンドツーエンド動作確認
やったこと:
- ジョブキュー構成を設計・実装(VPS が受付、自宅 Mac が処理)
backend/main.py: SQLite ジョブキュー +/extract・/jobs/{id}・/worker/*エンドポイントを追加worker/worker.py: 自宅 Mac 用ワーカースクリプトを新規作成frontend/index.html: ジョブポーリング対応(2秒ごとに status を確認)
- Hetzner に新コードをデプロイ
- 別の Mac にワーカーをセットアップして起動
- https://yclip.org でエンドツーエンドのダウンロードが動作することを確認
- YouTube Mix URL(
&list=...&start_radio=1)を自動でクリーニングする処理を追加
気づき:
&list=...付きの URL は yt-dlp がプレイリスト全体を解析しようとしてタイムアウトする- 別 Mac の pip が壊れていたため venv 経由でインストールが必要だった
決めたこと:
- Residential Proxy(有料)や Cookie 注入ではなく、自宅 Mac の住宅用 IP をワーカーとして使う構成を採用
次回やること:
- Adsterra 広告の埋め込み
- 1080p 以上の高画質対応
17:00 - Hetzner 本番デプロイ完了・YouTube IP ブロック問題発覚
やったこと:
- yclip.org ドメインをお名前.com で取得(初年無料、.com プレミアム問題を回避し .org に変更)
- Hetzner アカウント作成・VPS 立ち上げ(Nuremberg / Regular Performance / Ubuntu 24.04)
- サーバーセットアップ: Python 仮想環境・uvicorn・nginx・systemd 設定
- Cloudflare に yclip.org を登録、DNS + SSL を設定
- https://yclip.org が外部公開できた
- YouTube がブロックしている問題を確認(Hetzner のデータセンター IP が弾かれる)
決めたこと:
- インフラを Railway → Hetzner Nuremberg に変更(20TB 帯域付きで月 €4 程度)
- ドメインは yclip.org(お名前.com 初年無料。1年でサービスがうまくいかなければサ終予定)
- Cloudflare を DNS + SSL レイヤーとして採用(無料)
/downloadプロキシエンドポイントを追加(ブラウザのクロスオリジン制約でダウンロードできない問題を解決するため。帯域コストが発生する妥協点)
詰まったこと / 気づき:
yclip.comはプレミアムドメインで 774,312円、yclip.orgは初年無料だった- Singapore VPS は月 $9.49 + 0.5TB のみ。Nuremberg は月 €4 + 20TB で全然違う
- Hetzner のクレジットカード払いが弾かれ PayPal で解決
- Cloudflare SSL モードを「Flexible」にしないと Error 521 が出る
- ブラウザの
download属性はクロスオリジン URL には効かない → サーバープロキシが必要 - Hetzner のデータセンター IP は YouTube にボットとして弾かれる(ローカルは通る)
次回やること:
- YouTube IP ブロック対策(Residential Proxy または Cookie 認証)
14:30 - session-wrap-up スキルテスト(4ファイル運用に移行)
やったこと:
- session-wrap-up スキルの動作確認(DEVLOG/WIP 2ファイル→4ファイル運用への移行確認)
- DECISIONS.md・ROADMAP.md を新規作成・初期内容を記録
次回やること:
- Railway にデプロイして公開(最優先)
14:00 - アーキテクチャ設計 & Phase 1 MVP 実装
やったこと:
- YouTube ダウンローダーサイトのアーキテクチャを壁打ちしながら設計
- Phase 1 MVP を実装・ローカル動作確認・GitHub push まで完了
決めたこと:
- サーバーは URL 抽出のみ(動画データを触らない)。yt-dlp で YouTube CDN の直リンクを返し、ユーザーのブラウザが直接 CDN からダウンロードする。自サーバーの帯域コストをほぼゼロに抑えるための核心設計。
- バックエンド: Python 3.12 + FastAPI + yt-dlp
- フロントエンド: Vanilla JS + Tailwind CSS(単一 index.html)
- インフラ: Railway(無料枠スタート)
- 広告: AdSense ではなく Adsterra / PropellerAds(グレーゾーンサイトへの審査リスクを避けるため)
実装したファイル:
backend/main.py— FastAPI エントリポイント(POST /extract・GET /)backend/extractor.py— yt-dlp ラッパー(直リンク・タイトル・サムネイル・フォーマット一覧)backend/requirements.txtfrontend/index.html— URL 入力→フォーマット選択→CDN 直 DL の UIrailway.toml— Railway デプロイ設定
気づき:
- yt-dlp は Python ネイティブなので
loop.run_in_executorで非同期化した(FastAPI のブロッキング対策) backend/ディレクトリ内から uvicorn を起動しないとfrom extractor importが解決できない(同じ階層問題)
次回やること:
- Railway にデプロイして公開
- 1080p 以上の対応(映像・音声トラックが分離しているため ffmpeg マージが必要)
- Adsterra 広告の埋め込み
最近のコミット
- 7e69936 .devnotes を更新(player_client 指定で動画取得失敗を解消した分) 2026/4/25
- 0536586 yt-dlp の player_client を web,android に指定し動画取得失敗を回避 2026/4/25
- 365324d .devnotes を更新(named tunnel 移行・range リクエスト対応分) 2026/4/25
- b4d784b ダウンロードプロキシを range リクエスト(10MBチャンク)に変更しYouTubeスロットリングを回避 2026/4/25
- ed7616b cloudflared subprocess のパイプバッファ詰まりを修正 2026/4/25
- 18d0a58 .devnotes を更新(ダウンロードプロキシ修正・Cloudflare Tunnel対応分) 2026/4/25
- 7d947d1 ワーカー自動トンネル起動・VPS動的URL登録に対応 2026/4/25
- b42cedf ダウンロードをワーカーMac経由に変更(Cloudflare Tunnel対応) 2026/4/24
- 4193a3b 自宅Macワーカー構成を実装・YouTube IPブロック問題を解決 2026/4/24
- 611930f Hetzner デプロイ対応・.devnotes を更新 2026/4/24
README
youtube-downloader
概要
(記入予定)
セットアップ
(記入予定)
使い方
(記入予定)