I’m working on a python program that extracts the sound from a given YouTube video url and plays it. I created a play_vid
method to play the sound and a pause_vid
method to pause the sound. The issue is that while the sound is still playing inside the play_vid
method and I try to call the pause_vid
method, the call gets ignored and the play_vid
method keeps running. Example:
vid = Video("youtubelink") vid.play_vid() time.sleep(5) # The sound keeps playing/this method call is being ignored vid.pause_vid()
How do I terminate the play_vid
method when the pause_vid
method is called? I’ve been researching for a while and wasn’t able to find a solution to this problem. Full program:
from selenium import webdriver from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By import time, os, vlc, requests from mutagen.mp3 import MP3 class InvalidUrl(Exception): def __init__(self, message="Invalid video url!"): super().__init__(message) class Video: def __init__(self, url): self.url = url self.paused = False self.player = "" self.is_valid() self.time_sleep = 0 def play_vid(self): driver = webdriver.Chrome("C:chromedriver.exe") driver.get("https://ytmp3.cc/en14/") element = driver.find_element_by_id("input") element.send_keys(self.url) button = driver.find_element_by_id("submit") button.click() wait = WebDriverWait(driver, 10) button2 = wait.until(EC.visibility_of_element_located((By.XPATH, '//*[@id="buttons"]/a[1]'))) button2.click() vid_name = driver.find_element_by_xpath('//*[@id="title"]').text vid_name = vid_name.replace("| ", "") file_name = os.path.expanduser(r"~Downloads{}.mp3".format(vid_name)) while not os.path.exists(file_name): time.sleep(1) driver.close() self.player = vlc.MediaPlayer() media = vlc.Media(file_name) self.player.set_media(media) self.player.play() audio = MP3(file_name) audio_info = audio.info length_in_secs = int(audio_info.length) while self.time_sleep != length_in_secs: if self.paused is True: return time.sleep(1) self.time_sleep += 1 def pause_vid(self): self.paused = True def is_valid(self): r = requests.get(self.url) if "Video unavailable" in r.text: raise InvalidUrl
A big thanks to Mark M for letting me know that I forgot to add self.player.set_pause(1)
in the pause_vid
method. He also advised me to remove the while loop, so I used time.sleep
in my main program in order to decide how long the video will play for instead of the while loop. Updated code:
from selenium import webdriver from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By import time, os, vlc, requests from mutagen.mp3 import MP3 class InvalidYouTubeUrl(Exception): def __init__(self, message="Invalid YouTube url!"): super().__init__(message) class Video: def __init__(self, url): self.url = url self.player = None self.is_valid() self.vid_len = None def play_vid(self): driver = webdriver.Chrome("C:chromedriver.exe") driver.get("https://ytmp3.cc/en14/") element = driver.find_element_by_id("input") element.send_keys(self.url) button = driver.find_element_by_id("submit") button.click() wait = WebDriverWait(driver, 10) button2 = wait.until(EC.visibility_of_element_located((By.XPATH, '//*[@id="buttons"]/a[1]'))) button2.click() vid_name = driver.find_element_by_xpath('//*[@id="title"]').text vid_name = vid_name.replace("| ", "") file_name = os.path.expanduser(r"~Downloads{}.mp3".format(vid_name)) while not os.path.exists(file_name): time.sleep(1) driver.close() self.player = vlc.MediaPlayer() media = vlc.Media(file_name) self.player.set_media(media) self.player.play() audio = MP3(file_name) audio_info = audio.info self.vid_len = int(audio_info.length) def pause_vid(self): self.player.set_pause(1) def is_valid(self): r = requests.get(self.url) if "Video unavailable" in r.text: raise InvalidYouTubeUrl
I’ve also found a way to play the whole sound in the main program:
import pyytmp3, time vid = pyytmp3.Video("youtubelink") vid.play_vid() time.sleep(vid.vid_len)
I’m basically just delaying the program by the length of the video.
Advertisement
Answer
The problem is two-fold:
- You’re not actually pausing the audio playback, so the
MediaPlayer
will just continue to play the rest of it. According to the MediaPlayer docs it has a functionpause()
or evenstop()
. Call this from your pause_vid method. You’ll need to invoke theOn second thought, I think thevid.pause_vid()
method from another thread because the play_vid() method will just run till completion. You can create a background thread to play the video from. Some good examples here https://pymotw.com/3/threading/MediaPlayer.play()
method already runs in the background due to the wording in the documentation:
Play. @return: 0 if playback started (and was already started), or -1 on error.