[Python] Youtubeから音声のみのファイルを作ってみる
こんにちは、@yasuです。
車で音楽を聴くのために、Youtubeから音声のみをダウンロードしています。これまでは、あるサイトを利用して音声ファイルをダウンロードしていましたが、簡単にできないかと考えてみました^^
こんな機能を作ってみました^^
- Youtube動画URLを指定して音声のみをダウンロードする
- ダウンロード中には、プログレスバーを経過を把握できるようにする
- Youtubeチャンネルの再生リストを指定して、動画URLを取得する
- ダウンロード中には、サムネイルを表示する
あまり動かしすぎると、Youtubeのサーバから拒否られます。(拒否られました^^)私の場合は、数日間アクセスを休んだらまたできるようになりました。
環境
- 今回はhttps://repl.it/ ではなくVisual Studio Codeで行います
- pytube3ライブラリのインストール
pip install pytube3 - ワークスペースにdownloadフォルダを作る
コード
from pytube import YouTube,Playlist
import os
#
# YouTubeから音声だけをダウンロードする。
#
# 参考サイト
#
def downlod_audio(yt):
try:
ys = yt.streams.get_audio_only()
#ダウンロード
print("Downloading...")
filepath = ys.download(output_path="./download")
print("Download completed!!")
if os.path.exists(filepath):
root_ext_pair = os.path.splitext(filepath)
dst = root_ext_pair[0] + ".mp3"
print(root_ext_pair)
if os.path.exists(dst):
os.remove(dst)
os.rename(filepath, dst)
except :
print(sys.exc_info())
finally:
pass
#
# プレイリストの動画URLを抽出する。
#
def get_playlist(playlisturl):
from pytube import Playlist
import re
playlist = Playlist(playlisturl)
playlist._video_regex = re.compile(r"\"url\":\"(/watch\?v=[\w-]*)")
print(len(playlist.video_urls))
for url in playlist.video_urls:
print(url)
return playlist.video_urls
def getImageByUrl(thumbnail_url):
from PIL import Image, ImageTk
from urllib.request import urlopen
from io import BytesIO
with urlopen(thumbnail_url) as f:
raw_data = f.read()
im = Image.open(BytesIO(raw_data))
resize_image = im.resize((200,200))
photo2 = ImageTk.PhotoImage(resize_image)
return photo2
from tkinter import simpledialog
#
# 入力ダイアログ
#
class MyDialog(simpledialog.Dialog):
def body(self, master):
#self.geometry("800x600")
self.label = Label(master, text="プレイリストのURLを入力してください。")
self.label.pack(anchor="nw")
self.entry = Entry(master,width=80 )
self.entry.pack()
#self.entry.insert(0,"https://www.youtube.com/playlist?list=PLfxuH4AnuITJ5Y3TLnVrlYmSED2GHKvwL")
self.entry.insert(0,"https://www.youtube.com/playlist?list=PLfxuH4AnuITKgM38P9NLBPxLv-4NSxOcJ")
return self.entry # initial focus
def apply(self):
first = self.entry.get()
print (first)
#return first
self.result = first
#
# メイン
#
import os
import tkinter.ttk as ttk
from tkinter import *
root = Tk()
root.title("Youtubeから動画の音声をダウンロードする")
root.geometry("640x480")
def command_run_download():
s = txt.get("1.0","end")
lines = [x for x in s.splitlines(False) if x != ""]
print("■lines",lines)
p_var.set(1)
progress_bar.update()
for line in enumerate(lines):
yt = None
try:
print("■line",line)
yt = YouTube(line[1])
#-----------------
#global photo
print(yt.thumbnail_url)
photo = getImageByUrl(yt.thumbnail_url)
label_photo.config(image=photo)
label_photo.update()
#-----------------
downlod_audio(yt)
#downlod_video(yt)
p_var.set(100 / len(lines) * (line[0]+1))
progress_bar.update()
except:
print(sys.exc_info())
finally:
pass
p_var.set(100)
def command_get_playlist():
from tkinter import simpledialog
d = MyDialog(root) #added this
print(d.result)
playlisturl = d.result
video_urls = get_playlist(playlisturl)
for url in video_urls:
txt.insert(END,url+"\n")
#
# メイン
#
menu = Menu(root)
menu_file = Menu(menu, tearoff=0)
menu_file.add_command(label = "終了", command=root.quit)
menu.add_cascade(label="ファイル", menu=menu_file)
menu_tool = Menu(menu, tearoff=0)
menu_tool.add_command(label = "プレイリストから動画を抽出する", command=command_get_playlist)
menu.add_cascade(label="ツール", menu=menu_tool)
#
#
#
top_frame = Frame(root)
top_frame.pack(side="top",fill="both" ,expand=True, padx=5,pady=5)
lbl = Label(top_frame,text="YoutubeのURLを記述してください。")
lbl.pack(side="top",anchor = 'nw')
label_photo = Label(top_frame)
label_photo.pack(side="right",anchor = 'n')
#スクロールバー
scrollbar = Scrollbar(top_frame)
scrollbar.pack(side="right",fill="y")
txt = Text(top_frame, yscrollcommand=scrollbar.set)
txt.pack(side="left",fill="both",expand = True)
scrollbar.config(command=txt.yview)
#
#プログレスフレーム
#
progress_frame = LabelFrame(root,text="進行状況")
progress_frame.pack(fill="x", padx=5,pady=5,ipady=5)
p_var = DoubleVar()
progress_bar = ttk.Progressbar(progress_frame,maximum=100,variable=p_var)
progress_bar.pack(fill="x",padx=5,pady=5)
#
#ボタン
#
run_frame = Frame(root)
run_frame.pack(fill="x",padx=5,pady=5)
btn_close = Button(run_frame, padx=5,pady=5,text="閉じる",width=12,command=root.quit)
btn_close.pack(side="right",padx=5,pady=5)
btn_start = Button(run_frame, padx=5,pady=5,text="ダウンロード開始",width=15,command=command_run_download)
btn_start.pack(side="right",padx=5,pady=5)
root.config(menu=menu)
root.mainloop()
@yasu transfered 0.5 KRWP to @krwp.burn. voting percent : 6.77%, voting power : 60.03%, steem power : 1937084.07, STU KRW : 1200.
@yasu staking status : 250 KRWP
@yasu limit for KRWP voting service : 0.5 KRWP (rate : 0.002)
What you sent : 0.5 KRWP [47652071 - 01901a5fa16433e5aa76dd706e7fc3a4c38b2fd0]