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.