---
# System prepended metadata

title: pytube影片下載器-附教程及檔案
tags: [moviepy, pytube, pyinstaller]

---

**前言:
    再讓我從頭打一次我真的會生氣，還好學習歷程系統截止前做完了，但我真的很XX某系統要點兩次確認，害我高二多元不見，只能繼續跟那個pdf上傳繼續培養感情。QWQ**
    
    
打出這篇只是想分享一些截止到2024/4/18關於pytube的學習成果，我大概高一時就開始了相關研究，全部的程式碼從0到有大概花了三個多月，也碰壁了不少次------
(甚至因為一個冒號在電腦前面坐了3個小時，找到問題時真的很想砸電腦......)

總之，以下分享了我自主學習的python版 YouTube下載器及pyinstaller打包成(.exe)的一些經過及解決方法~~~~yeeeee
(附上軟體長什麼樣子)
![螢幕擷取畫面 2024-04-18 204405](https://hackmd.io/_uploads/SkZJI90xA.png)

功能:
1. 路徑更改(蠻方便的，可以直接下載到指定資料夾)
2. 影片下載
3. 清單下載(個人設定的播放清單比較好用)
4. 合併影片檔案(其實就是把影片接起來，不過太多部會有問題，要注意一下)
5. 把影片轉檔成mp3



因為是本來就打算做成(.exe)，為了方便使用所以內容很多while True。
如果你很常翻pytube製作的網站，你會發現裡面很多變數長得跟大神的很像，
不用懷疑，**我只是懶得想變數名字**，但內容我還是有經過個人風格的修改和改進。

=>成品展示(其實有些部分可以合併，但我就不~~~)

```python=
from pytube import YouTube
from pytube import Playlist
from time import sleep
from moviepy.editor import *
import os
import ssl
ssl._create_default_https_context = ssl._create_stdlib_context      
#使ssl證書設定為不用的樣子?
a = 0
#以下不是我原創，但真的好用
def onProgress(stream, chunk, remains):
    total = stream.filesize                     # 取得完整尺寸
    percent = (total-remains) / total * 100           # 減去剩餘尺寸 ( 剩餘尺寸會抓取存取的檔案大小 )
    print(f"下載中… {percent:05.2f}", end="\r")          # 顯示進度，\r 表示不換行，在同一行更新

print("本產品為萬用影、音檔處理器，有以下指令及其功能")
print("mp4 :下載mp4檔 \nmpcon :合併影片檔 \nchangeroad :改變路徑")
print("fcmp3 :將已存在檔案備份轉成mp3 \nplaylist :下載清單 \nexit :跳出功能")
for i in range(1):
  try:                          #利用try可在輸入錯誤時軟體不會跳掉
    y = str(input("請輸入目標路徑:"))        #紀錄或創建資料夾以用來儲存
    os.chdir(y)
    print("#已儲存路徑")
  except:
    os.mkdir(y)
    os.chdir(y)
    print("已創建資料夾")

while True:
  instruction = str(input("請輸入指令:"))
  if instruction == "playlist":           #判斷指令
    while True:
      if a == 1:
        print("已下載到 {}".format(y))      #如果前面有下載檔案，提示位置
      else:
        pass
      link = str(input("請輸入撥放清單網址:"))   #利用Playlist函式取得網址下載
      if link == "exit":
        break

      a = 0                     #設定還未下載(False)

      sleep(1)
      p = Playlist(link)
      try:
        print("共有 {} 部影片".format(len(p)))
        for video in p:
          try:
            a = 1
            yt = YouTube(video, on_progress_callback=onProgress)#顯示下載進度
            yt.streams.filter().get_highest_resolution().download(y)
          except:
            print("無法下載!!")
            pass
      except:
        print("發生錯誤")
        pass
  elif instruction == "mpcon":
    a = []
    try:
      b = int(input("請輸入欲合成影片數量:"))            #輸入數量方便合成
      if b == "exit":
        break

      for i in range(b):
        variable = str(input("請輸入影片名:"))
        variable = str(variable+".mp4")
        variable = VideoFileClip(variable)
        a.append(variable)
      variable = str(input("請輸入合成後檔名:"))
      variable = str(variable+".mp4")
      clip = concatenate_videoclips(a)
      clip.write_videofile(variable)
      print("已完成合成")
    except:
      print("有問題發生,下載失敗")
  elif instruction == "fcmp3":
    while True:
      variable = str(input("請輸入欲轉檔影片名:"))          #輸入檔名以偵測檔案
      if variable == "exit":
        break

      try:
        sleep(2)                           #加入延遲減緩計算
        d = str(variable + ".mp4")
        video = VideoFileClip(d)
        variable = str(variable + ".mp3")
        audio = video.audio
        audio.write_audiofile(variable)                #取出聲音並存檔
        print("--處理完成--")
      except:
        print("有問題產生,處理失敗")
        pass
  elif instruction == "changeroad":
    try:
      y = str(input("請輸入目標資料夾:"))
      if y == exit:
        break

      os.chdir(y)
      print("#已更改路徑")
    except:
      os.mkdir(y)
      os.chdir(y)
      print("已創建並指定資料夾")
  elif instruction == "exit":
    print("--感謝您的使用-再見")
    sleep(3)
    break
  elif instruction == "mp4":
    while True:
      try:
        link = str(input("請輸入網址:"))
        if link == "exit":
          break

        yt = YouTube(link, on_progress_callback = onProgress)
        yt.streams.filter().get_highest_resolution().download(y)
        print("已下載到[{}]".format(y))
      except:
        print("發生錯誤!!!")
  else:
    pass
exit()
```

總之這些東西真的把我整的不輕，首先那個SLL證書設定真的重要到爆炸，不然你做再好都一樣
軟體會不斷跳掉到你生氣都修不好QQ

再來分享一些爬文後我改進的部分
1. 很多pytube下載清單的迴圈部分會用.video或_urls之類的
    但我就是怎麼用怎麼跳掉，用了3個半個小時候後感覺腸子跟我的軟體一樣要跳到資源回收桶了，也不知道是我緣分不夠還是我做人太失敗owo
    
    總之，我直接p = Playlist(link) 後就  for i in p:了，i一樣會分別變成清單的網址，所以......為什麼要這麼麻煩?
    
2. 然後因為一些我不知道的原因，print()在try放的位置也會導致一些問題，所以我還是稍微麻煩億點，把print()移到try外面，加上了一個True和False的判斷式。


3. pyinstaller ---麻煩要使用的人，我一律建議在cmd(終端)裡面用cd /d指定到桌面一個資料夾處理，相信我，你會很省事，不含打包UI介面(tkinter)的指令--


打包而已: pyinstaller -F 檔名.格式
加上ico圖示: pyinstaller -i 檔名.ico -F 檔名.格式

結論:
1.清單下載的網址p = Playlist(link) 後就  for i in p:就好
2.pyinstaller 指令-
    pyinstaller -F 檔名.格式
    或 pyinstaller -i 檔名.ico -F 檔名.格式
    
檔案位置(附教程):
   https://drive.google.com/drive/folders/1JOfmoNczjQsdahGc_6rKL9FqU3eMDBf0?usp=sharing

以下是一些研究時參考的大神資料(記得至少翻過10個網站，但我忘記儲存了QQ):
https://ithelp.ithome.com.tw/articles/10248249
https://steam.oxxostudio.tw/category/python/example/youtube-list-download.html
https://steam.oxxostudio.tw/category/python/example/youtube-download.html
https://www.spatialgeolab.com/python-pytube-yotubedownloader/

有問題可以留言提問，看到就會回OWO
###### tags `pytube`
###### tags `pyinstaller`
###### tags `moviepy`