How to play video with python-vlc? - python

I would like to play video with python-vlc module. I wrote the following code. My computer is MacOS Catalina.
#!/usr/bin/env python3
import vlc
p = vlc.MediaPlayer("mediafile.mp4")
p.play()
while True:
pass
But the python3 interpreter threw the following errors.
[00007f89b9661950] caopengllayer vout display error: No drawable-nsobject found!
[00007f89b9661950] macosx vout display error: No drawable-nsobject nor vout_window_t found, passing over.
[00007f89b30530f0] main video output error: video output creation failed
[00007f89b9650c00] main decoder error: failed to create video output
[h264 # 0x7f89b407c000] get_buffer() failed
[h264 # 0x7f89b407c000] thread_get_buffer() failed
[h264 # 0x7f89b407c000] decode_slice_header error
[h264 # 0x7f89b407c000] no frame!
I guessed that this code didn't make a frame displaying the video. It'll be a main cause of this error, I think.
However, I can not come up with a solution of this problem.
Please tell me how to play video with python-vlc module!!

I think the possible reason is, it requires an active hwnd where it can show the video.
So you need an GUI and set hwnd to that player.
Here is my code for Tkinter Window.You can also check out different GUI based example From Github
import vlc
from tkinter import *
root=Tk()
instance=vlc.Instance()
p=instance.media_player_new()
p.set_hwnd(root.winfo_id())
p.set_media(instance.media_new(path_to_media))
p.play()
root.mainloop()
And if you r using Mac ,then as per the example
you should use instaed of this line
p.set_hwnd(root.winfo_id())
try:
libtk = 'libtk%s.dylib' % (Tk.TkVersion,)
prefix = getattr(sys, 'base_prefix', sys.prefix)
libtk = joined(prefix, 'lib', libtk)
dylib = cdll.LoadLibrary(libtk)
# getNSView = dylib.TkMacOSXDrawableView is the
# proper function to call, but that is non-public
# (in Tk source file macosx/TkMacOSXSubwindows.c)
# and dylib.TkMacOSXGetRootControl happens to call
# dylib.TkMacOSXDrawableView and return the NSView
_GetNSView = dylib.TkMacOSXGetRootControl
# C signature: void *_GetNSView(void *drawable) to get
# the Cocoa/Obj-C NSWindow.contentView attribute, the
# drawable NSView object of the (drawable) NSWindow
_GetNSView.restype = c_void_p
_GetNSView.argtypes = c_void_p,
del dylib
except (NameError, OSError): # image or symbol not found
def _GetNSView(unused):
return None
libtk = "N/A"
h = root.winfo_id() # .winfo_visualid()?
# XXX 1) using the videopanel.winfo_id() handle
# causes the video to play in the entire panel on
# macOS, covering the buttons, sliders, etc.
# XXX 2) .winfo_id() to return NSView on macOS?
v= _GetNSView(h)
if v:
p.set_nsobject(v)
else:
p.set_xwindow(h)# plays audio, no video

I think this will work:
import vlc
media = vlc.MediaPlayer("1.mp4")
media.play()
It just takes a media filename for you.
Make sure the video is in the same folder as the script.

Related

Python: How to overcome invalid argument of incorrect file path

I am attempting to write a Python script that captures a screenshot everytime the left mouse button is pressed. I am using this guide as a reference: https://pytutorial.com/python-capture-screenshot-mouse-clicked
My problem is coming from the file path. I am wanting the screenshots to be saved in the "Screenshoots" folder, but am instead getting the error, "OSError: [Errno 22] Invalid argument: 'C:/Users/tjdob/codebase/Screenshoots//26-10-2022_22:12:52.jpg'"
My base directory is C:\Users\tjdob\codebase
Here is the code I am attempting to run:
from pymouse import PyMouseEvent
import pyautogui
import os
class ScreenshotsTaker(PyMouseEvent):
def __init__(self, path):
self.path = path # path to save Screenshot
PyMouseEvent.__init__(self)
def click(self, x, y, button, press):
# if button number 1
if button == 1:
# if button number 1 is pressed (clicked)
if press:
# Take ScreenShot
myScreenshot = pyautogui.screenshot()
# Save ScreenShot file
now = datetime.now()
# Date Time Now
dt_string = now.strftime("%d-%m-%Y_%H:%M:%S")
# Save ScreenShot
myScreenshot.save(os.path.join(self.path,dt_string + ".jpg"))
# Output:
print("ScreenShot is taken")
C = ScreenshotsTaker(path="C:/Users/tjdob/codebase/Screenshoots//")
C.run()
I am sure it is a simple fix. Any direction would be appreciated
I have tried changing the filepath, and switching backslashes with forward slashe.
The problem is with the filename you're creating using strftime():
26-10-2022_22:12:52.jpg
Windows filenames can't have a : in them, because : in a file path is the separator between a drive letter (e.g. C:) and a path. There is an exception to this to use a : as part of a feature called Alternative Data Streams, but that's not what you're trying to do here.
Because it's not a valid filepath, you get the Invalid argument error.
You'll have to format the timestamp portion of the filename differently - possible alternative format options are:
%H-%M-%S -> 22-12-52
%H.%M-%S -> 22.12.52
%H%M%S -> 221252

Cannot click on tkinter button more than twice

I am a newbie to tkinter and have know idea what I am doing sometimes:D . I created a python script to get Corona Virus Stats from a GitHub post link The script has over 20 files in it so I thought I should just create one file to run all the other files. So what other better way to do it than creating a UI. And that's what I did I used tkinter to run all the files. If they clicked on x button then I would run abc. And I ended up running these files by importing them in a certain order(Don't know If that was the best way). So here is where I ran into an error. I don't exactly know if this error is because of how I imported my files or my tkinter code is just wrong. I just couldn't seem to click on a button twice. I would run my program and click on a button, it would run properly and then the next time I clicked on that same button It would just not work. There was no error and no output. Nothing would happen. Here is my code:
#Import tkinter
import tkinter as tk
from tkinter import *
from tkinter import simpledialog
tk = tk.Tk()
Max = 190
def RunDeaths():
#If they click on RunDeaths I will run this function
#Check if they have already entered a path
try:
open('/Users/test/Documents/python/Py_Programs/Hackathon/DeathStats/Info.txt','r')
from DeathStats import RunAll
except:
YourPath = simpledialog.askstring('Countries','''Please Enter Your Path To HACKATHON Folder:
Example:
\"/Users/Name/Documents/python/\"
Note: Leave out the HACKATHON folder and you must put a slash at the end''',parent=tk)
#Write this path to a file call Info.txt
file = open('/Users/test/Documents/python/Py_Programs/Hackathon/DeathStats/Info.txt','w')
file.write(str(YourPath)+'\n')
file.write(str(Max))
file.close()
#Run all the files that gather the data for Corona Virus Deaths
from DeathStats import RunAll
def RunRecoveredCases():
#If they click on RecoveredCases Run this
#Check If they had already entered a path
try:
open('/Users/test/Documents/python/Py_Programs/Hackathon/RecoveredCases/Info.txt','r')
from RecoveredCases import RunAll
except:
YourPath = simpledialog.askstring('Countries','''Please Enter Your Path To HACKATHON Folder:
Example:
\"/Users/Name/Documents/python/\"
Note: Leave out the HACKATHON folder and you must put a slash at the end''',parent=tk)
file = open('/Users/test/Documents/python/Py_Programs/Hackathon/RecoveredCases/Info.txt','w')
#Write there path to a file
file.write(str(YourPath)+'\n')
file.write(str(Max))
file.close()
#Run all the files that gather all the Recovered Cases
from RecoveredCases import RunAll
#* * Here is where I think I went wrong But Im not sure
Deaths = Button(tk,height = 20, width = 30, text='Run Deaths',command = RunDeaths,highlightbackground='#000000')
Recovered = Button(tk,height = 20, width = 30, text='Run Recovered Cases',command = RunRecoveredCases,highlightbackground='#000000')
Deaths.pack()
Recovered.pack()
tk.mainloop()
So my question and problem is: Why can I not click on a button more than twice?
This has happened to me before and I could not fix it. Any help would be appreciated.(If you would like to run my program because my explanation was just not good enough here is a git hub repo GitHub)
Thank You
It appears that you are assuming that from RecoveredCases import RunAll will run the code in RecoveredCases.py each time it is imported. That is a false assumption. Python caches code that is imported.
The proper way to use code in a separate file is to put the code in a function or class, import the function or class exactly once, and then call the function or instantiate the class whenever you want to run the code.

Getting RealSense depth frame in ROS

I have a drone in a Gazebo environment with a RealSense d435 camera on it. My plan is to use YOLO to find the center of an object of interest, and then find the depth of that point from the depth image. I heard that the depth camera outputs an image where the depth values are encoded in the RGB values. When further looking this up online, I found that there is a pyrealsense2 library that has functions for everything I need.
The implementations I've seen online need you to create a pyrealsense.pipeline() and get your frames from that. The issue is this seems to only work if you have a RealSense camera connected to your computer. Since mine exists in the Gazebo environment, I need a way to get and use the depth frame in a ROS callback. How would I do this? Any pointers would be greatly appreciated
yeah, you can do this with help of a ROS subscriber as follows (most of the code was taken from here):
import rospy
from sensor_msgs.msg import Image as msg_Image
from cv_bridge import CvBridge, CvBridgeError
import sys
import os
class ImageListener:
def __init__(self, topic):
self.topic = topic
self.bridge = CvBridge()
self.sub = rospy.Subscriber(topic, msg_Image, self.imageDepthCallback)
def imageDepthCallback(self, data):
try:
cv_image = self.bridge.imgmsg_to_cv2(data, data.encoding)
pix = (data.width/2, data.height/2)
sys.stdout.write('%s: Depth at center(%d, %d): %f(mm)\r' % (self.topic, pix[0], pix[1], cv_image[pix[1], pix[0]]))
sys.stdout.flush()
except CvBridgeError as e:
print(e)
return
if __name__ == '__main__':
rospy.init_node("depth_image_processor")
topic = '/camera/depth/image_rect_raw' # check the depth image topic in your Gazebo environmemt and replace this with your
listener = ImageListener(topic)
rospy.spin()
Note: To install CvBridge, you may follow the instructions below:
sudo apt-get install ros-(ROS version name)-cv-bridge
sudo apt-get install ros-(ROS version name)-vision-opencv
More information: http://wiki.ros.org/cv_bridge
To complement the above answer, be careful to the depth/image_rect_raw topic. Very likely you actually want the raw image, which you can obtain from /camera/aligned_depth_to_color/image_raw.
This topic may not be active by default, for instance on d435i you should toggle the align_depth:=true option:
roslaunch realsense2_camera rs_camera.launch align_depth:=true
See https://github.com/IntelRealSense/realsense-ros#usage-instructions for more info.

Catching a Tkinter exception for a missing file

I'm writing a Tkinter program that loads some .png images.
Since files can be faulty or non-existent, it is good to use a try-except block. I'm first checking the file with generic Python. Then I load the image file into Tkinter if it passes the generic Python try-except block:
ok = True
try:
image_file = open("cat.png")
image_file.close()
except IOError:
ok = False
if ok:
self.image = PhotoImage(file="cat.png")
This has to load the image file twice: once for the Python check, and once for Tkinter. Also, there is no guarantee the Tkinter image load attempt will work. If the file were arriving over a network, it is possible the file was available for the Python try-except call, but was then suddenly not available for the Tkinter call.
When I intentionally crash the program by making a call to an unavailable file, I get:
tkinter.TclError: couldn't open "fakefile.png": no such file or directory
This is exactly the error type (file not found) that I am trying to catch inside of Tkinter. I've hunted around, but I have been unable to find out a way for Tkinter to try-except its own call to: PhotoImage(...).
How can I safely load the PNG?
You don't need to make tkinter try-except its own call; just try-except your call to tkinter:
try:
self.image = PhotoImage(file="cat.png")
except tkinter.TclError:
# do whatever you wanted to do instead
For example:
try:
self.image = PhotoImage(file="cat.png")
except tkinter.TclError:
self.cat = Label(text="Sorry I have no cat pictures")
else:
self.cat = Label(image=self.image)

play MIDI files in python?

I'm looking for a method to play midi files in python.
It seems python does not support MIDI in its standard library.
After I searched, I found some python midi librarys such as pythonmidi.
However, most of them can only create and read MIDI file without playing function.
I would like to find a python midi library including playing method.
Any recommendations? Thanks!
The pygame module can be used to play midi files.
http://www.pygame.org/docs/ref/music.html
See the example here:
http://www.daniweb.com/software-development/python/code/216979
a whole bunch of options available at:
http://wiki.python.org/moin/PythonInMusic
and also here which you can modify to suit your purpose:
http://xenon.stanford.edu/~geksiong/code/playmus/playmus.py
Just to add a minimal example (via DaniWeb):
# conda install -c cogsci pygame
import pygame
def play_music(midi_filename):
'''Stream music_file in a blocking manner'''
clock = pygame.time.Clock()
pygame.mixer.music.load(midi_filename)
pygame.mixer.music.play()
while pygame.mixer.music.get_busy():
clock.tick(30) # check if playback has finished
midi_filename = 'FishPolka.mid'
# mixer config
freq = 44100 # audio CD quality
bitsize = -16 # unsigned 16 bit
channels = 2 # 1 is mono, 2 is stereo
buffer = 1024 # number of samples
pygame.mixer.init(freq, bitsize, channels, buffer)
# optional volume 0 to 1.0
pygame.mixer.music.set_volume(0.8)
# listen for interruptions
try:
# use the midi file you just saved
play_music(midi_filename)
except KeyboardInterrupt:
# if user hits Ctrl/C then exit
# (works only in console mode)
pygame.mixer.music.fadeout(1000)
pygame.mixer.music.stop()
raise SystemExit
pretty_midi can generate the waveform for you, you can then play it with e.g. IPython.display.Audio
from IPython.display import Audio
from pretty_midi import PrettyMIDI
sf2_path = 'path/to/sf2' # path to sound font file
midi_file = 'music.mid'
music = PrettyMIDI(midi_file=midi_file)
waveform = music.fluidsynth(sf2_path=sf2_path)
Audio(waveform, rate=44100)
Use pygame to play your midi file. Examples are here or here
I find that midi2audio works well.
Example:
from midi2audio import FluidSynth
#Play MIDI
FluidSynth().play_midi('input.mid')
#Synthesize MIDI to audio
# Note: the default sound font is in 44100 Hz sample rate
fs = FluidSynth()
fs.midi_to_audio('input.mid', 'output.wav')
# FLAC, a lossless codec, is recommended
fs.midi_to_audio('input.mid', 'output.flac')
On macOS, you can use the pyObjC library to access the OS's own MIDI handling routines. This script will play midi files given as arguments.
#!/usr/bin/env python3
from AVFoundation import AVMIDIPlayer
from Foundation import NSURL
import time
import sys
def myCompletionHandler():
return
def playMIDIFile(filepath):
midiFile = NSURL.fileURLWithPath_(filepath)
midiPlayer, error = AVMIDIPlayer.alloc().initWithContentsOfURL_soundBankURL_error_(midiFile, None, None)
if error:
print (error)
sys.exit(1)
MIDItime = midiPlayer.duration()
midiPlayer.prepareToPlay()
midiPlayer.play_(myCompletionHandler)
if not midiPlayer.isPlaying:
midiPlayer.stop()
else:
time.sleep(MIDItime)
return
if __name__ == "__main__":
for filename in sys.argv[1:]:
playMIDIFile(filename)

Categories

Resources