python-vlc: Exit the player programatically - python

I'm trying to play a video using VLC, and close the window after the video is finished. However, I can't close the player window. I tried releasing instances of the player and media, but it doesn't work. And I couldn't find anything else in the API documentation.
Note that I don't want to terminate the whole application after the player finished, so sys.exit is not an option.
The following code is what I'm doing.
import vlc
VIDEO_PATH="/path/to/video.mp4"
def get_end_callback(mediaplayer):
def end_callback(event):
print("End of playing reached")
mediaplayer.stop()
mediaplayer.get_media().release()
mediaplayer.release()
mediaplayer.get_instance().release()
return end_callback
def play():
vlc_instance = vlc.Instance(["--no-xlib"])
media_player = vlc.MediaPlayer(vlc_instance, VIDEO_PATH)
media_player.play()
event_manager = media_player.event_manager()
event_manager.event_attach(vlc.EventType.MediaPlayerEndReached, get_end_callback(media_player))
play()
input("press Enter to exit")
I'm testing it with python=3.9, python-vlc=3.0.12118, vlc=3.0.9.2, on Ubuntu=20.04. I also tried another machine with older OS and older VLC.

So LibVLC will spawn a window to draw on, if you don't provide one. You don't want that, as you won't be able to manage it easily.
Before calling media_player.play(), you want to call media_player.set_hwnd(window.handle) (for Windows) / media_player.set_xwindow(window.xid) (for Linux) with a window handle.
Creating and managing and deleting this window is up to you and it does not have to be your main window of your app.
Here you can find more complete yet minimal samples with Qt and GTK frameworks https://github.com/oaubert/python-vlc/tree/master/examples

Related

Raspberry Pi freezes when python starts to play

I've written a program in python, on my Mac, which I intend to run on a Raspberry Pi.
It includes a background picture that changes, and a button that starts/stops music playing.
The program uses pygame.
On the Mac it runs exactly as I expect it to do.
But when I run it on the Pi, and the play button is pressed, the whole program freezes for 25 - 30 seconds (the images stop changing, can't ctrl+alt+f to a different login) with no sound. After the freeze the program resumes, sound start playing ....
There's nothing logged in /var/log/syslog ....
In the main object for the program I initialise the mixer.
def __init__(self):
pygame.mixer.pre_init(44100, -16, 2, 2048)
pygame.mixer.init()
pygame.init()
Then the play button in the program calls this method to toggle the button image between a play and stop icon, and start the current tune (the media files are ogg files called 001.ogg, 002.ogg etc):
def clickButtonPlay(self):
self.buttonPlay+=1
if self.buttonPlay > 2:
self.buttonPlay=1
self.drawButtonPlay()
if self.buttonPlay == 1:
self.song.stop()
else:
newTune = "tunes/%03d.ogg" %self.tuneNo
self.song = pygame.mixer.Sound(newTune)
self.song.play()
Any ideas what's causing the freeze?
Doh!Should have used pygame.mixer.music, not pygame.mixer.Sound.

Wait for song played outside of python to finish

I am trying to wait for a song to finish to play the next song.
I am running python 3.4 on windows but am trying to be able to use it on Linux (raspberry pi).
I have used the command subprocess.call([PLAYER, SONG]) to open the mp3 file. It plays in vlc and then stops. I know that I have not incorporated anything for the program to tell python when its finished.
That's where you guys come in. I want to find a command that will wait until the song has finished and when the song is finished, the rest of the code will process.
I would like the command to be able to used on a Linux operating system and I am trying not to have to install any modules.
If modules are definitely needed, I will install them.
You may use VLC python bindings to get the different information about the VLC player.
There are different methods that can provide your different information. You may achieve your solution by using the get_state(self) method, it provides the state information of the player. So, when the song is completed the VLC state would be stopped.
Sample code:
import vlc
def setup_player(filename):
vlc_instance = vlc.Instance()
media = vlc_instance.media_new(filename)
player = vlc_instance.media_player_new()
player.set_media(media)
player.play()# Start the player
print player.get_state()# Print player's state
player.stop()# Stop the player
print player.get_state()# Print player's state
setup_player('filename')#Put media file name/location here
I hope it was helpful.

Automating windows media player

Any ideas about controling windows media player in Python? I found the following code on the net which runs fine but no audio is played. am using win7 64 bit machine
# this program will play MP3, WMA, MID, WAV files via the WindowsMediaPlayer
from win32com.client import Dispatch
mp = Dispatch("WMPlayer.OCX")
#tune = mp.newMedia("./SleepAway.mp3")
tune = mp.newMedia("./plays.wav")
mp.currentPlaylist.appendItem(tune)
mp.controls.play()
raw_input("Press Enter to stop playing")
mp.controls.stop()
As I have mentioned in comments, I have had an identical problem. I tried a ridiculous number of different approaches. None of them really worked, so I was stuck using os.startfile to open windows media player to play my sound files. However, just today I had an idea which has led to an alternative solution. It is a bit hack-ish, but it works. Technically I still open windows media player with this approach, but I do so using subprocess, and thus I can use the greater control over the process allowed by that to supress the window. This makes it seem like it plays without a secondary application. Why I had to do something so bizarre to get a simple result I have no idea, but it is the only thing that worked. Here is my code for it if you want.
import subprocess
import threading
def windowsmedia(filename):
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
a = subprocess.call('C:\\Program Files (x86)\\Windows Media Player\\wmplayer.exe /play /close "C:/Users/Student/Documents/notes/file.mp3"',startupinfo=startupinfo)
def startmp3(filename):
mythread = threading.Thread(target=windowsmedia,args=[filename])
mythread.start()
time.sleep(15) #You might want to extend this... I just give it 15 seconds to complete before killing the process. It shouldn't be too hard to read the exact length from the file and wait that, or add an interrupt, but that was somewhat unnecessary for my purposes.
pkill("wmplayer") #This is a function of my own but it basically just kills the process. It shouldn't be too hard to reproduce.
Again it is truly regrettable that I had to do something so weird for just playing a sound but as far as you have described it this is the same issue and I hope this helps.
Thought, it might help others who are still facing this issue.
All you had to do is to call PlayItem() API after Play().
from win32com.client import Dispatch
from time import sleep
mp = Dispatch("WMPlayer.OCX")
tune = mp.newMedia("./plays.wav")
mp.currentPlaylist.appendItem(tune)
mp.controls.play()
sleep(1)
mp.controls.playItem(tune)
raw_input("Press Enter to stop playing")
mp.controls.stop()
It helps me to use Windows Media COM. When I tried it, I need to make 2 small modification to make it working in Python Flask.
CoInitialize to make it single thread i.e. pythoncom.CoInitialize() and pythoncom.CoUninitialize()
PumpWaitMessage to keep MediaPlayer working i.e while mp.PlayState != 1: pythoncom.PumpWaitingMessages()

urllib.urlretrieve stops download when no activity on Tkinter window on Mac only

I'm trying to make a file downloader with a Tkinter GUI window, which will download a file using the following line:
urllib.urlretrieve(url = fileurl, filename = file, reporthook = progBar)
Progbar is a progress bar on my Tkinter GUI window. When I run my code on Windows, the download works fine and runs normally, as does the progress bar.
However, when I run the same code on a Mac, the download and progress bar will only progress if there is activity in the Tkinter GUI window. For example, if the window is in the background, the download will pause until the window is clicked on. Even then, when the Tkinter GUI window is not in the background, the download will only progress if I am doing something like moving the mouse around the screen or repeatedly pressing buttons on the keyboard, otherwise the download pauses again. It seems like it is timing out for some reason, and I'm not sure how to fix this or why it only happens on Mac and not windows.
If I put a print statement in the progBar method, the download also slows down.
I have also tried removing the reporthook argument from the call to urllib.urlretrieve, when I do this the download progresses fine.
My progBar method is as follows:
def progBar(blocks, blocksize, totalsize) :
global pb
bytesdownloaded = blocksize*blocks
mbdownloaded = bytesdownloaded/1024/1024
mbsize = float(blocksize)/float(totalsize)
totalsize = totalsize/1024/1024
percent = mbsize*100
global v
va.set("(" + str(mbdownloaded) + 'MB out of ' + str(totalsize) + 'MB)')
pb.step(percent)
I am using Python 2.7 if this helps.
Edit: for further information, the download (call to urllib.urlretrieve) is performed in a background thread, while the GUI window is meant to be the main thread. This may have something to do with the problem.
This is just a guess, but it's possible that the UI output command in the reporthook is hanging due to the fact that the event loop is (I'm guessing) paused for a program when it's in the background. I have vague recollection of the Tkinter UI model but one solution might be to set some global variable with your current progress in the hook, and have UI paint it separately - do not issue UI commands in the hook.

Quit VLC if already running

I am having a weird problem with VLC in Python. Using the following things.
import vlc
self.Instance = vlc.Instance()
self.List = self.Instance.media_list_new()
self.Player_d = self.Instance.media_list_player_new()
I am using self.List.add_media(address of video) to populate the media list.
Then self.Player_d.set_media_list(self.List)
and self.Player_d.play()
The problem is that VLC starts in a weird (YUV something) window, without any controls. Then freezes after playing the list. I have to use Task Manager to shut it down.
Can anybody point out the problem? I want to play the VLC with all controls.
Secondly, is there anyway of checking if VLC is already running, if running, then to quit and start a new instance of VLC.
Any help would be appreciated.
I don't see anything about wxPython in your question, but if you're using it with the vlc module, then that could be your problem. I'm guessing they don't play nicely together. You probably need to run all the vlc stuff in a separate thread rather than in wx's main loop.

Categories

Resources