此篇文章所述皆是我個人習慣的方法,僅供參考!
若想了解更多資訊,歡迎參考 Reference 部分的相關連結~
# 方法一: yt-dlp
我個人習慣使用 Colab
來跑,因為每次都可以重開一個乾淨的環境 XD
所以這裡的 demo 皆是以在 colab 上面跑的指令為主~
每次開始執行的時候,都需要先下載 yt-dlp
!pip install yt-dlp |
設定參數
url = "https://www.youtube.com/watch?v=_xL58zG9k5k" # @param {type:"string"} | |
# @markdown - title would be `"%(title)s.%(ext)s"` | |
title = '"%(title)s.%(ext)s"' | |
########## 取得 format code ########## | |
import subprocess | |
result = subprocess.run(f'yt-dlp -F {url} | grep audio | grep -v webm | tail -n1', shell=True, capture_output=True, text=True) | |
output = result.stdout.strip() | |
audio_format_code = output.split(' ')[0] | |
result = subprocess.run(f'yt-dlp -F {url} | grep video | grep -v webm | grep "720p"', shell=True, capture_output=True, text=True) | |
output = result.stdout.strip() | |
video_format_code = output.split(' ')[0] | |
########## 設定間隔時間 (下載影片片段才需要設定) ########## | |
start_time_seconds = "2120" # @param {type:"string"} | |
end_time_seconds = "2137" # @param {type:"string"} |
下面這段則是 debug 才需要跑的指令
!yt-dlp -F {url} | |
!yt-dlp -F {url} | grep audio | |
!yt-dlp -F {url} | grep audio | grep -v webm | tail -n1 | |
!yt-dlp -F {url} | grep video | |
!yt-dlp -F {url} | grep video | grep -v webm | grep '720p' |
之後會按照下載的目的來區分要執行的指令!
# 下載音樂
需求和規格:影片為 mp4
檔案, 720p
畫質;聲音則是 m4a
檔案,約 129k
的就行~
下載純聲音檔案的指令
!yt-dlp -f {audio_format_code} --extract-audio --audio-format mp3 -o {title} {url} |
以下指令是單獨下載影片 (無聲音) 才需要跑的
!yt-dlp -f {video_format_code} -o {title} {url} |
下載完整的影片 (含聲音)
!yt-dlp -f {audio_format_code}+{video_format_code} --embed-thumbnail -o {title} {url} |
可以加上 --embed-thumbnail
來為影片添加縮圖。
# 下載影片片段 (含聲音)
主要是拿來做精華剪輯的~
dur = f"*{start_time_seconds}-{end_time_seconds}" | |
command = f'yt-dlp -o "%(title)s({start_time_seconds}-{end_time_seconds}).%(ext)s" -f {audio_format_code}+{video_format_code} {url} --download-sections {dur}' | |
!{command} |
--download-sections *{start_time_seconds}-{end_time_seconds}
: 要下載的片段中,起始和結束的秒數。- 最後的連結就是要下載的影片連結。
接下來的指令則是按照需求來決定要不要執行~
取得標題 (若字幕非原文才需要)
import json | |
result = subprocess.run(f'yt-dlp -j {url}', shell=True, capture_output=True, text=True) | |
output = result.stdout.strip() | |
try: | |
# 解析 JSON | |
data = json.loads(output) | |
# 提取並打印 title 欄位 | |
title = data.get('title', 'Title not found') | |
print(title) | |
title = f'{title}' | |
except json.JSONDecodeError: | |
print("Error: Failed to decode JSON") |
確認字幕語言
comm = 'awk "/Available subtitles for/ {flag=1; next} flag"' | |
result = subprocess.run(f'yt-dlp --list-subs {url} | {comm} | grep -E "zh-TW|zh-Hant|zh"', shell=True, capture_output=True, text=True) | |
output = result.stdout.strip() | |
print(output) |
zh-TW
和zh-Hant
為繁體中文,請複製下來供下一步使用。zh
和zh-Hans
為簡體中文中,請在下載之後另行簡轉繁。
下載字幕 (srt 檔案)
lang_code = "zh-Hant" # @param {type:"string"} | |
!yt-dlp --write-subs --sub-lang {lang_code} --convert-subs srt --skip-download -o {title} {url} |
查看影片大小 (若不會太大,則可以接續下一步的預覽)
!yt-dlp --print "%(filesize_approx&~|)s%(filesize_approx,filesize)#D%(filesize_approx,filesize&B|)s" {url} |
在 colab 上預覽影片 (如果不想下載的話)
result = subprocess.run('ls | grep "mp4"', shell=True, capture_output=True, text=True) | |
output = result.stdout.strip() | |
from IPython.display import HTML | |
from base64 import b64encode | |
mp4 = open(output,'rb').read() | |
data_url = "data:video/mp4;base64," + b64encode(mp4).decode() | |
HTML(""" | |
<video width=400 controls> | |
<source src="%s" type="video/mp4"> | |
</video> | |
""" % data_url) |
注意,此預覽僅限小檔案 (如影片片段),只要檔案大一點,colab 就會終止連線。
(經測試,5MiB 的完整歌曲 mp4 可以;60MB 的另一部歌曲 mp4 不行)
# 方法二: pytube
有鑑於 Youtube 會常常更新網站,但 pytube 已經 1 年多沒更新了 (雖然目前還可以正常執行),為了避免未來某天 pytube 會無法使用,所以我之後可能都會改成使用 yt-dlp 來下載。
更:目前出現新的 bug,基於以上原因,只好果斷跳去 yt-dlp。為了省一點空間,程式碼就不附上了 (放在 colab)。
再更 (2024.8.23): 雖然暫時找到解法了,不過以後應該還是會直接使用 yt-dlp。(不再更新真的是硬傷 QQ)
下載音樂 | 下載影片片段 |
---|---|
原本:使用 pytube + ffmpeg 現在:使用 yt-dlp ,請參考此處 | 我本來就是使用 yt-dlp 來達成,請參考此處 |
# 方法三:線上工具
我有用過的網站:
- YouTube Video Downloader
- YouTube MP3 Playlist Downloader
- 雖然這些網站會有彈出式廣告,十分惱人,但因為下載功能還不錯用,所以還是先寫下來,等有遇到更好用的再說!
- 第一次按
Download
的彈出式視窗暫時無法避免,不過等它跑完影片後再按的那個Download
則可利用在新頁籤中開啟連結來自動關閉!
(或是使用 ADGUARD🤣 (沒辦法,Opera 的 ADB sucks🙃))
# 同場加映
筆者我在大一的暑假利用所學 (Tkinter 視窗 + pytube 套件),寫了一個可以下載單一影片或整個撥放清單的小應用程式,直到大二暑假都還可正常運行。
可惜現在 pytube 不再維護了,之後可能會改成用 yt-dlp 重新寫一個 (GUI 順便換掉),或是直接使用以上的方法就好 XD
之後會再把之前寫的程式上傳 github 做個紀錄~
(畢竟這是筆者第一個用上所學來解決現實中問題的程式,有其意義在!)
# Reference
- 非官方 yt-dlp 指令使用教學
- 官方 yt-dlp github
- 官方 pytube github
- 非官方 pytube bug RegexMatchError 解法
- 非官方 pytube 下載 srt 字幕