把 YouTube(以及其他 yt-dlp 支援網站)的影片、音樂、播放清單,直接傳到 Telegram 的自架 Bot。
你只要把網址貼給 Bot;它會下載、依 Telegram 限制切檔、上傳,最後清掉暫存檔。也能訂閱頻道,在有新影片或直播時自動處理。
Important
這是私人下載工具。請只下載你有權觀看、保存或分享的內容,並遵守來源平台與 Telegram 的規範。
-
到 @BotFather 建立 Bot,取得
BOT_TOKEN。 -
到 my.telegram.org 的 API development tools 建立 application,取得
TELEGRAM_API_ID與TELEGRAM_API_HASH。 -
在專案資料夾建立
.env:cp .env.example .env
-
編輯
.env,至少填好這三個值:BOT_TOKEN=貼上_BotFather_給你的_token TELEGRAM_API_ID=你的_api_id TELEGRAM_API_HASH=你的_api_hash
-
建置並啟動:
docker build -t ghcr.io/treehd/ytdl:latest . docker-compose up -d --build --force-recreate docker-compose logs -f ytdl-bot -
在 Telegram 對 Bot 輸入
/start,或直接貼一個影片網址。
如果日誌最後出現 Bot is running...,就完成了。按 Ctrl+C 只會停止看日誌,不會停止容器。
flowchart LR
U[你在 Telegram 貼網址或輸入指令] --> H[handlers.py<br/>檢查權限、建立一則狀態訊息]
H --> Q[下載佇列<br/>request_queue / playlist_queue]
Q --> P[queue_processor.py<br/>依序下載、切檔、清理]
P --> D[downloader.py<br/>yt-dlp + Cookie + Proxy]
D --> S[(來源網站)]
D --> F[downloads/<br/>暫存媒體檔]
F --> UP[uploader.py<br/>裁縮圖、切檔、上傳]
UP --> T[Telegram]
T --> U
M[subscription.py<br/>定期檢查訂閱頻道] --> H
D -.遇到 geo 限制就換下一個 proxy.-> W[PROXY_LIST]
W -.可選.-> WP[warp-proxy]
用白話說:
- Bot 先回覆一則進度訊息,例如「正在分析網址」。
- 任務排進佇列,避免多個大檔同時塞滿記憶體和硬碟。
- yt-dlp 下載媒體;必要時會使用 Cookie 或依序換 proxy。
- 檔案過大時,FFmpeg 會先切成 Telegram 能接受的大小。
- Bot 上傳完成後刪除暫存檔,只保留訂閱資料庫與你放的 Cookie。
| 類型 | Bot 會做什麼 |
|---|---|
| 一般影片/音樂 | 排進一般佇列,下載後上傳。 |
| 播放清單 | 排進播放清單佇列,逐部下載,避免大量檔案同時佔空間。 |
| 訂閱新影片 | 依 SUBSCRIPTION_CHECK_INTERVAL(預設 300 秒)檢查頻道,有新片就自動排入佇列。 |
| 訂閱直播 | 開始時同時錄兩路:streamlink 從現在錄作為保險;yt-dlp 嘗試從直播開頭封存。從頭錄製穩定 10 分鐘後,會停掉 streamlink 並刪除它的重複暫存,最後只傳從頭錄的完整版。沒有 DVR/VOD 時,streamlink 會繼續錄。 |
直播錄影遇到 Proxy/WARP 中斷時不會直接判定下播。Bot 會輪替所有設定的代理、以退避方式重試,並透過 YouTube metadata 連續兩次確認同一支影片已不在直播,才會上傳為 (End)。預設 30 分鐘內仍無法恢復時,會上傳已錄到的片段並標記 (Proxy interrupted),保留狀態訊息說明直播結束尚未確認。
直播流程如下:
flowchart TD
L[偵測到直播] --> A[建立同一則直播狀態訊息]
A --> N[streamlink:從現在開始錄]
A --> B[yt-dlp --live-from-start:從開頭封存]
B --> C{來源有 DVR / VOD?}
C -->|有| D[兩路暫時同錄]
D --> J{從頭錄製穩定 10 分鐘?}
J -->|是| K[停掉 streamlink/刪除重複暫存]
K --> G[只保留從頭錄的完整版]
J -->|否/中途失敗| N
C -->|沒有| E[顯示提醒,結束從頭封存]
E --> N
N --> F[目前直播分段上傳]
F --> H[直播結束或按 Stop & Upload]
G --> H
- 一台可執行 Docker Compose 的 Linux、NAS、VPS 或電腦。
- Docker Engine 與 Docker Compose。
- 一個 Telegram Bot token。
- 若要使用內建 Local Bot API(建議):Telegram API ID 與 API Hash。
- 建議預留足夠磁碟空間;影片會先下載到硬碟,再上傳到 Telegram。
先確認 Docker 可用:
docker --version
docker-compose --versiongit clone <你的-repository-url> YTDL
cd YTDL如果你已經有這個資料夾,直接進入即可:
cd /mnt/HDD/YTDL- 打開 @BotFather。
- 輸入
/newbot,照指示設定名稱與 username。 - 複製 BotFather 給你的 token。
- 不要把 token 貼到公開聊天室、README、Git commit 或截圖。
- 開啟 my.telegram.org 並用你的 Telegram 帳號登入。
- 點選 API development tools。
- 建立 application。
- 複製
api_id與api_hash。
這兩個值供本專案的 Local Bot API Server 使用,讓 Bot 能處理接近 2GB 的檔案。
cp .env.example .env
chmod 600 .env用任何文字編輯器打開 .env:
# 必填
BOT_TOKEN=123456789:AAExampleReplaceThisWithYourRealToken
TELEGRAM_API_ID=12345678
TELEGRAM_API_HASH=請貼上_api_hash
# 建議:只讓自己或指定群組使用。留空代表任何人都能用。
ALLOWED_CHAT_IDS=123456789
# 內建 WARP proxy;不需要 proxy 可把 PROXY_LIST 留空。
PROXY_LIST=socks5://warpuser:warppass@warp-proxy:1080
# 暫存下載檔預估可使用的硬碟上限(GB)。0 表示不檢查。
MAX_DISK_GB=10取得自己的 Telegram chat ID,可使用可信的查詢 Bot;群組 ID 通常是負數。ALLOWED_CHAT_IDS 可放多個值,以逗號分隔:
ALLOWED_CHAT_IDS=123456789,-1001234567890這份 docker-compose.yml 使用已命名的 image ghcr.io/treehd/ytdl:latest。因此你有修改本機 Python 程式碼時,必須先執行第一行,否則 Docker 可能仍跑舊 image。
docker build -t ghcr.io/treehd/ytdl:latest .
docker-compose up -d --build --force-recreate
docker-compose ps
docker-compose logs -f ytdl-bot確認服務應包含:
| 容器 | 用途 |
|---|---|
ytdl-bot |
接收 Telegram 指令、下載、上傳。 |
telegram-bot-api |
本機 Telegram Bot API,支援大檔上傳。 |
warp-proxy |
可選的 Cloudflare WARP proxy。 |
autoheal |
偵測到 Local Bot API 不健康時自動重啟它。 |
在 @BotFather 輸入 /setcommands,選擇你的 Bot 後,把下面整段直接貼上。每行開頭不要加 /:
start - 使用說明
help - 顯示使用說明
download - 下載影片(預設 1080p)
1080 - 下載 1080p 影片
720 - 下載 720p 影片
480 - 下載 480p 影片
360 - 下載 360p 影片
240 - 下載 240p 影片
music - 下載 M4A 音訊
mp3 - 下載 MP3 音訊
playlist - 下載播放清單
settings - 設定預設格式與解析度
subscribe - 訂閱頻道新影片
sublive - 訂閱頻道直播
unsubscribe - 取消新影片訂閱
unsublive - 取消直播訂閱
subscriptions - 查看所有訂閱
upgrade - 更新 yt-dlp
/subvideo、/unsubvideo、/subs 也仍可使用;它們是相容用別名,因此不放進指令選單。
直接傳送網址給 Bot,會依 /settings 的設定下載。預設是 1080p 影片。
https://www.youtube.com/watch?v=example
| 指令 | 怎麼用 | 結果 |
|---|---|---|
/download <網址> |
/download https://… |
用 1080p 下載影片。 |
/1080、/720、/480、/360、/240 |
/720 https://… |
指定影片最高解析度。 |
/music <網址> |
/music https://… |
下載 M4A 音訊。 |
/mp3 <網址> |
/mp3 https://… |
下載 MP3 音訊。 |
/playlist <網址> [畫質] |
/playlist https://… 720 |
逐部下載播放清單。 |
/settings |
/settings |
按按鈕設定直接貼網址時的預設格式與畫質。 |
/subscribe <頻道網址> [畫質] |
/subscribe https://youtube.com/@example 1080 |
訂閱新影片。 |
/sublive <頻道網址> [畫質] |
/sublive https://youtube.com/@example 720 |
訂閱直播並自動錄製。 |
/unsubscribe <頻道網址> |
/unsubscribe https://youtube.com/@example |
取消新影片訂閱。 |
/unsublive <頻道網址> |
/unsublive https://youtube.com/@example |
取消直播訂閱。 |
/subscriptions |
/subscriptions |
列出目前所有訂閱。 |
/upgrade |
/upgrade |
手動更新 yt-dlp nightly;有下載任務時會拒絕執行。 |
直播進度訊息會有兩個按鈕:
- Stop & Upload:停止兩條錄製線,將目前收到的片段上傳。
- Cancel:取消錄製並清掉未完成的暫存資料。
.env.example 是完整範本。下表是最常會調整的項目。
| 變數 | 要不要填 | 預設/範例 | 用途 |
|---|---|---|---|
BOT_TOKEN |
必填 | 123:ABC… |
BotFather 給的 token。 |
TELEGRAM_API_ID |
Local Bot API 必填 | 12345678 |
從 my.telegram.org 取得。 |
TELEGRAM_API_HASH |
Local Bot API 必填 | abcdef… |
從 my.telegram.org 取得。 |
API_URL |
建議保持範例值 | http://host.docker.internal:8081/bot |
指向本機 Telegram Bot API。若改為官方 API,檔案上傳限制會降到約 49MB。 |
ALLOWED_CHAT_IDS |
強烈建議 | 123456789,-100… |
白名單;留空代表所有人都能使用。 |
PROXY |
選填 | socks5://host:1080 |
單一 proxy,優先使用。 |
PROXY_LIST |
選填 | proxy1,proxy2 |
以逗號分隔的 proxy 清單;geo 限制會直接嘗試下一個。 |
WARP_USERNAME / WARP_PASSWORD |
使用內建 WARP 時 | warpuser / warppass |
必須和 PROXY_LIST 中的帳密相同。 |
MAX_DISK_GB |
建議填 | 10 |
一般下載前的暫存空間預估上限;0 為不檢查。 |
SUBSCRIPTION_CHECK_INTERVAL |
選填 | 300 |
訂閱頻道輪詢秒數。300 是 5 分鐘。 |
YTDLP_AUTO_UPDATE |
選填 | true |
容器啟動時更新 yt-dlp nightly。 |
YTDLP_DAILY_UPDATE |
選填 | true |
每天自動更新 yt-dlp。 |
YTDLP_UPDATE_TIME |
選填 | 04:00 |
每日更新時間。 |
YTDLP_UPDATE_TIMEZONE |
選填 | Asia/Taipei |
每日更新的時區。 |
LIVE_PROXY_RECOVERY_WINDOW_SECONDS |
選填 | 1800 |
直播 Proxy 故障後的最大復原時間;到期會安全上傳已有片段。 |
LIVE_PROXY_RETRY_INITIAL_SECONDS / LIVE_PROXY_RETRY_MAX_SECONDS |
選填 | 3 / 60 |
直播重連指數退避的初始與最大等待秒數。 |
LIVE_WARP_RESTART_COOLDOWN_SECONDS |
選填 | 60 |
WARP restart 的最短間隔,避免反覆重啟。 |
LIVE_END_CONFIRMATIONS / LIVE_END_CONFIRMATION_INTERVAL_SECONDS |
選填 | 2 / 15 |
判定直播真正結束所需的成功確認次數與間隔。 |
不需要 proxy:
PROXY=
PROXY_LIST=使用多個 proxy:
PROXY_LIST=socks5://proxy-a:1080,http://proxy-b:8080使用內建 WARP:
PROXY_LIST=socks5://warpuser:warppass@warp-proxy:1080
WARP_USERNAME=warpuser
WARP_PASSWORD=warppass遇到明確的地區限制(geo block)時,Bot 只會換下一個 proxy,不會重建 WARP IP。bot 偵測、403、timeout 等其他可重試錯誤,在正在使用 warp-proxy 時才可能要求 WARP rotation。
-
將瀏覽器中已登入 YouTube 的 Cookie 匯出成 Netscape cookies.txt 格式。
-
放到專案中的
data/cookies.txt:YTDL/ └── data/ └── cookies.txt -
重建/重啟 Bot:
docker-compose up -d --build --force-recreate
Cookie 等同登入憑證,絕對不要傳給別人,也不要提交到 Git。.gitignore 已排除 data/。
cd /mnt/HDD/YTDL
docker build -t ghcr.io/treehd/ytdl:latest .
docker-compose up -d --build --force-recreate
docker-compose logs -f ytdl-bot如果你沒有改本機程式碼、只想取得 registry 的新版本:
docker-compose pull
docker-compose up -d --force-recreate# 查看容器是否正常
docker-compose ps
# 持續看 Bot 日誌
docker-compose logs -f ytdl-bot
# 看 Local Bot API 日誌
docker-compose logs -f telegram-bot-api
# 重啟服務,不刪資料
docker-compose restart
# 停止服務,不刪資料庫或 Cookie
docker-compose down| 路徑 | 是否要備份 | 原因 |
|---|---|---|
.env |
是 | Bot token、Telegram API 資訊與設定。 |
data/subscriptions.db |
是 | 所有頻道訂閱。 |
data/cookies.txt |
視需要 | YouTube Cookie;請加密保存。 |
downloads/ |
通常不用 | 暫存下載檔,啟動時會清空。 |
Warning
Bot 啟動時會清空 downloads/。不要把唯一的一份重要檔案放在這個目錄,也不要在下載進行中任意重建容器。
YTDL/
├── bot.py # 啟動 Bot、註冊指令、啟動背景任務
├── handlers.py # 指令、按鈕、權限與網址解析入口
├── queue_processor.py # 下載佇列、直播錄製、切檔、清理
├── downloader.py # yt-dlp、Cookie、proxy 與 WARP rotation 判斷
├── uploader.py # 上傳 Telegram、縮圖裁切、檔案切割
├── subscription.py # 頻道新片/直播監控
├── database.py # SQLite 訂閱資料
├── config.py # .env 設定讀取與空間檢查
├── upgrader.py # yt-dlp nightly 更新排程
├── telegram_utils.py # Telegram API 重試與 flood-control 處理
├── docker-compose.yml # 四個容器的編排
├── Dockerfile # ytdl-bot 本機 image 建置方式
├── .env.example # 可複製的設定範本
├── data/ # 訂閱資料庫與選用 Cookie(不進 Git)
└── downloads/ # 暫存下載檔(不進 Git)
docker-compose ps
docker-compose logs --tail=100 ytdl-bot最常見原因:BOT_TOKEN 打錯、容器沒有啟動、或 ALLOWED_CHAT_IDS 沒有包含你的 chat ID。
通常代表 Bot 正在使用官方 Telegram API,而不是 Local Bot API。檢查 .env:
API_URL=http://host.docker.internal:8081/bot
TELEGRAM_API_ID=你的值
TELEGRAM_API_HASH=你的值再確認 Local Bot API 正常:
docker-compose ps telegram-bot-api
docker-compose logs --tail=100 telegram-bot-api先確認 yt-dlp 是最新版本:
/upgrade
仍然失敗時,再放入 data/cookies.txt,然後重啟容器。Cookie 必須是 Netscape 格式。
在 .env 放入一個或多個適合地區的 proxy:
PROXY_LIST=socks5://taiwan-proxy:1080,socks5://japan-proxy:1080Bot 會依順序嘗試。Geo block 不會重啟 WARP,只會跳下一個 proxy。
這是最常見的部署問題。docker-compose.yml 指定的是 image,不會自動把工作目錄裡的 Python 檔塞進容器。請重新 build 本機 image 後再重建容器:
docker build -t ghcr.io/treehd/ytdl:latest .
docker-compose up -d --build --force-recreate-
先停止 Bot:
docker-compose down -
查看
downloads/與 Docker 使用空間:du -sh downloads data docker system df
-
確認沒有仍要保留的檔案後,再手動清理
downloads/的舊暫存檔。
若要在主機上跑測試,先建立 Python 虛擬環境:
python3 -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt
python3 -m unittest discover -s tests