I want to make an app that downloads youtube videos with pytube and kivy. The problem is that the app freezes and then stops responding when the download starts. I know it starts to download because it creates a mp4 file. I looked into scheduling and multithreading but I don't know how those work and I'm not even sure they are a solution to my problem in the first place. Anyone that can tell me where to look?
the python file:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from pytube import YouTube
class MyWidget(BoxLayout):
def download_video(self, link):
yt = YouTube(link)
yt.streams.first().download()
class Youtube(App):
pass
if __name__ == "__main__":
Youtube().run()
the kivy file:
MyWidget:
<MyWidget>:
BoxLayout:
orientation: 'horizontal'
Button:
text: 'press to download'
on_press: root.download_video(url.text)
TextInput:
text: 'paste the youtube URL here'
id: url
I was recently intimidated by threading myself, talk about GIL. The threading library itself isn't too complicated however and this problem is a great use-case for it.
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from pytube import YouTube
# import Thread from threading
from threading import Thread
class MyWidget(BoxLayout):
# Create a start_download method
def start_download(self):
# Creates a new thread that calls the download_video method
download = Thread(target=self.download_video)
# Starts the new thread
download.start()
def download_video(self):
# I implemented the text grabbing here because I came across a weird error if I passed it from the button (something about 44 errors?)
yt = YouTube(self.ids.url.text)
yt.streams.first().download()
class Youtube(App):
def build(self):
return MyWidget()
if __name__ == "__main__":
Youtube().run()
youtube.kv
<MyWidget>:
orientation: 'horizontal'
Button:
text: 'press to download'
# Call the start download method to create a new thread rather than override the current.
on_press: root.start_download()
TextInput:
text: 'paste the youtube URL here'
id: url
1) You enter the url
2) You click download button
3) This triggers a start_download method.
4) The start_download creates a thread that runs your download method that takes the url.text at the current time as an argument. This means you can enter additional urls, while that is downloading without overwriting the url text in the previous calls because they're in different threads of execution.