此篇文章所述皆是我個人習慣的方法,僅供參考!

若想了解更多資訊,歡迎參考 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 才需要跑的指令

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-TWzh-Hant 為繁體中文,請複製下來供下一步使用。
  • zhzh-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 字幕