I've looking for method to play songs not from the begining in python gstreamer, consider this:
import threading
import gst
import gobject
class GobInit(threading.Thread):
...
class BasicPlayer(threading.Thread):
def __init__(self, musiclist):
threading.Thread.__init__(self)
self.musiclist = musiclist
self.song_num = 0
self.construct_pipeline()
self.set_property_file()
def construct_pipeline(self):
self.player = gst.element_factory_make("playbin")
self.is_playing = False
self.connect_signals()
def connect_signals(self):
...
def play(self):
self.is_playing = True
self.player.set_state(gst.STATE_PLAYING)
def set_property_file(self):
self.player.set_property(
"uri", "file://"+"/home/user/work/mp3/"+self.musiclist[
self.song_num])
def main():
gob = GobInit()
gob.start()
print('start')
player = BasicPlayer(['test1.mp3', 'test2.mp3', 'test3.mp3'])
print('player created')
player.play()
print('start play')
main()
So I have only this function to start:
self.player.set_state(gst.STATE_PLAYING)
But I bet there is a way to start playing from the middle of the song, something like this:
self.player.play_from_middle(gst.STATE_PLAYING, <sec_after_begin>)
Or maybe can I rewind the song somehow to make it be played from the middle?
Yes, I guess there should be a few ways, but the one (for non-live streams) that immediately comes to my mind is:
Set the pipeline to PAUSED instead of PLAYING
Wait for the GST_MESSSAGE_ASYNC_DONE message to appear in the bus handler.
Query pipeline (gst_element_query()) for the duration, and then seek the pipeline (gst_element_seek()) to the duration/2 time
Set the pipeline to PLAYING.
Related
I am trying to make a simple audio player with the ability to play, stop, pause and resume songs.
What I am trying to do
Run the audio on a separate thread with the ability to then use MCI from the main thread to pause and resume it.
What doesn't work
When trying to call a function to play a song using threading or multiprocessing MCI returns an error code with a value of 263 (unfortunately there is no documentation about number error codes anywhere online that i've been able to find) and instantly ends the whole program.
What does work
Playing, pausing and resuming without the use of threading/multiprocessing.
My code
from ctypes import windll
import threading
import time
class WinPlayAudio():
def __init__(self):
self.alias = "A{}".format(id(self))
def _MCI_command(self,command):
windll.winmm.mciSendStringW(command,0,0,0) # If printed, this returns 263 == unrecognized audio device
# This does not play anything even tho wait is turned to: True
def _play(self, start=0, wait = False):
th = threading.Thread(target=self._MCI_command, args=(f'play {self.alias} from {start} {"wait" if wait else ""}',))
th.start()
def _open_song(self, audio_path):
self._MCI_command(f'open {audio_path} alias {self.alias}')
def _set_volume(self):
self._MCI_command(f'setaudio {self.alias} volume to 500')
def _pause(self):
self._MCI_command(f'pause {self.alias}')
def _resume(self):
self._MCI_command(f'resume {self.alias}')
def _stop(self):
self._MCI_command(f'stop {self.alias}')
if __name__ == '__main__':
p = WinPlayAudio()
p._open_song(r"D:\songs\bee.mp3")
p._play(0, True)
Fixed Code
Stay away from aliasing if you wish to multithread
import threading
from ctypes import windll
class WinPlayAudio():
def __init__(self):
self.alias = "A{}".format(id(self))
self.audio_path = ""
def _MCI_command(self, command):
print(command)
err = windll.winmm.mciSendStringW(command, 0, 0, 0) # If printed, this returns 263 == unrecognized audio device
print(err)
def _play(self, start=0, wait=True):
th = threading.Thread(target=self.__play__, args=(start, wait))
th.start()
def __play__(self, start, wait):
self._MCI_command(f'play {self.audio_path} from {start} {"wait" if wait else ""}', )
def _open_song(self, audio_path):
self.audio_path = audio_path
self._MCI_command(f'open {audio_path} alias {self.alias}')
def _set_volume(self):
self._MCI_command(f'setaudio {self.alias} volume to 500')
def _pause(self):
self._MCI_command(f'pause {self.alias}')
def _resume(self):
self._MCI_command(f'resume {self.alias}')
def _stop(self):
self._MCI_command(f'stop {self.alias}')
if __name__ == '__main__':
p = WinPlayAudio()
p._open_song("start.mp3")
p._play()
i am trying to create an audio player using tkinter and a separate class for Player.
I have encountered an error. I can play the song when i call the Function "start_play_thread" , but afther i press/call the Function Pause and then i try to play again the song keeps looping same second from where i paused it.
Could someone help me, please?
import pyglet
import time
from threading import Thread
class Player():
parent=None
song_length=0
current_song_time=0
paused=False
def play_media (self):
try:
self.myplayer = pyglet.media.Player()
self.source = pyglet.media.load(self.parent.current_track)
self.myplayer.queue(self.source)
self.myplayer.play()
pyglet.app.run()
except:
pass
def start_play_thread(self):
player_thread = Thread(target=self.play_media)
player_thread.start()
time.sleep(4)
self.actual_song_time()
def pause_song(self):
try:
self.myplayer.pause()
except :
pass
def unpause_song(self):
try:
self.myplayer.play()
except:
pass
def actual_song_lenght(self):
try:
self.song_lenght = self.source.duration
except:
self.song_lenght = 0
return self.song_lenght
def set_volume(self,value):
try:
self.myplayer.volume=value
except:
pass
def actual_song_time(self):
try:
self.current_song_time = self.myplayer.time
except:
self.current_song_time = 0
return self.current_song_time
if __name__ == '__main__':
print('a pyglet player class implementation')
First picture
Second one
I want to know how to change video aspect ratio of vlc media player in python to 16:10. Note that I am using vlc module. my code is as below:
import vlc
class Player():
def __init__(self):
self._instance = vlc.Instance(['--video-on-top'])
self._player = self._instance.media_player_new()
self._player.set_fullscreen(True)
def play(self, path):
media = self._instance.media_new(path)
self._player.set_media(media)
self._player.play()
def stop(self):
self._player.stop()
p=Player()
p.play('C:\\Users\\Keshavarz\\Desktop\\a.mp4')
Use the video_set_aspect_ratio("n:n") option where "n:n" is any of the usual suspects "16:9", "4:3" etc but can be anything you want such as "2:5" for example.
You will also need to keep the script alive, I've included a simple loop in your play function, to do that.
import vlc
import time
class Player():
def __init__(self):
self._instance = vlc.Instance(['--video-on-top'])
self._player = self._instance.media_player_new()
#self._player.set_fullscreen(True)
self._player.video_set_aspect_ratio("16:9")
def play(self, path):
media = self._instance.media_new(path)
self._player.set_media(media)
self._player.play()
playing = set([1,2,3,4])
time.sleep(0.1)
while True:
state = self._player.get_state()
if state not in playing:
break
time.sleep(1)
def stop(self):
self._player.stop()
p=Player()
p.play('C:\\Users\\Keshavarz\\Desktop\\a.mp4')
Hi I need to run my gui simultaneously with my alarm sound and stop the iterating alarm sound when i click ok button in the 2nd dialog box. To achieve this task i created 2 files which is the main file(gui using easygui) and the AudioFile class witch uses pyaudio to play and stop alarm sound.
main file:
from easygui import *
import sys
from AudioFile import *
predictions[0] = 1
a = AudioFile("alarm.wav")
if (predictions[0] == 1):
while 1:
#play alarm sound
a.play()
msgbox("Critical Situation Detected!")
msg ="Please choose an action?"
title = "Critical Situation Detected!"
choices = ["Ignore the Warning", "Contact Doctor", "Call Ambulance Service", "Call Hospital"]
#choice = choicebox(msg, title, choices)
choice = multchoicebox(msg, title, choices)
#stop alarm sound
a.close()
# note that we convert choice to string, in case
# the user cancelled the choice, and we got None.
msgbox("You chose: " + str(choice), "Action is in Progress")
msg = "Do you want to continue?"
title = "Please Confirm"
if ccbox(msg, title): # show a Continue/Cancel dialog
pass # user chose Continue
else:
sys.exit(0) # user chose Cancel
AudioFile:
import pyaudio
import wave
import sys
class AudioFile:
chunk = 1024
def __init__(self, file):
""" Init audio stream """
self.wf = wave.open(file, 'rb')
self.p = pyaudio.PyAudio()
self.stream = self.p.open(
format = self.p.get_format_from_width(self.wf.getsampwidth()),
channels = self.wf.getnchannels(),
rate = self.wf.getframerate(),
output = True
)
def play(self):
""" Play entire file """
data = self.wf.readframes(self.chunk)
while data != '':
self.stream.write(data)
data = self.wf.readframes(self.chunk)
def close(self):
""" Graceful shutdown """
self.stream.close()
self.p.terminate()
# Usage example for pyaudio
#a = AudioFile("alarm.wav")
#a.play()
#a.close()
When i run this two codes using main file i wanted to run the alarm sound first and in background the gui should appear in the window and when i select the choices from the second window and i press ok it should stop the alarm sound but instead of that first my application play the alarm sound after it is over it start the gui. how should i play my alarm sound in the background of the gui and close it after i press the second ok button?
Currently, when you run the AudioFile.play() method you will play the entire file before the msgbox("Critical Situation Detected!") command is executed.
The solution to this would be to run the alarm in a thread such that control remains in the while loop in your main file.
An example of what the threaded alarm might look like (minus the details) would be:
from threading import Thread,Event
from time import sleep
class AudioFile(Thread):
def __init__(self):
Thread.__init__(self)
self._stop = Event()
def run(self):
self._stop.clear()
# in this case we loop until the stop event is set
while not self._stop.is_set():
print "BEEP BEEP BEEP!"
sleep(0.2)
def stop(self):
self._stop.set()
In your main code you would then replace a.play and a.close by a.start and a.stop. For example:
x = AudioFile()
x.start()
sleep(4)
x.stop()
I came up with the solution based on #ebarr sample code.
main file:
predictions[0] = 1
a = AudioFile("alarm.wav")
if (predictions[0] == 1):
while 1:
a.start()
sleep(0.5)
msgbox("Critical Situation Detected!")
msg ="Please choose an action?"
title = "Critical Situation Detected!"
choices = ["Ignore the Warning", "Contact Doctor", "Call Ambulance Service", "Call Hospital"]
#choice = choicebox(msg, title, choices)
choice = multchoicebox(msg, title, choices)
a.stop()
# note that we convert choice to string, in case
# the user cancelled the choice, and we got None.
msgbox("You chose: " + str(choice), "Action is in Progress")
msg = "Do you want to continue?"
title = "Please Confirm"
if ccbox(msg, title): # show a Continue/Cancel dialog
pass # user chose Continue
else:
sys.exit(0) # user chose Cancel
AudioFile:
import pyaudio
import wave
import sys
from threading import Thread,Event
from time import sleep
class AudioFile(Thread):
chunk = 1024
def __init__(self, file):
""" Init audio stream """
Thread.__init__(self)
self.wf = wave.open(file, 'rb')
self.p = pyaudio.PyAudio()
self.stream = self.p.open(
format = self.p.get_format_from_width(self.wf.getsampwidth()),
channels = self.wf.getnchannels(),
rate = self.wf.getframerate(),
output = True
)
self._stop = Event()
def run(self):
self._stop.clear()
""" Play entire file """
while not self._stop.is_set():
data = self.wf.readframes(self.chunk)
self.stream.write(data)
def stop(self):
""" Graceful shutdown """
self._stop.set()
self.stream.close()
self.p.terminate()
So I'm building a game, and I have a message handler that deals (so far) with running the game itself, and now the lobby. Every time a message is sent, a new instance of that message handler is created. For example...
from wshandler.py:
def on_message(self, message):
MH = protocol.msghandler.HandlerImplementation(self)
message = tornado.escape.json_decode(message)
MH.handle_message(message)
Now that MH object... it calls a function in the lobby class, which puts them into a queue. The queue is going to be implemented on a thread, that starts when the program is started...
from main.py:
lobby = model.lobby.Lobby()
threading.Thread(target = lobby.match_players).start()
What I'm basically asking is can I do this, in HandlerImplementation...
def join_queue(self, username):
main.lobby.join_queue(username, self)
and this in lobby.py:
def join_queue(self, username, messager):
self.lock.acquire()
self.queue.append((username, messager))
self.lock.release()
So that when I'm matching players in lobby.match_players I can basically just do this...
def match_players(self):
while(True):
while len(self.queue) < 2: pass
self.lock.acquire()
if len(self.queue) >= 2:
player1 = self.queue.pop(0)
player2 = self.queue.pop(0)
player1[1].player_connect(player1[0], player2[0])
player2[1].player_connect(player2[0], player1[0])
self.lock.release()
Assuming player_connect is a defined function in HandlerImplementation?