audioplayer is a cross platform Python 3 package for playing sounds (mp3, wav, ...). It provides the key features of an audio player, such as opening a media file, playing (loop/block), pausing, resuming, stopping, and setting the playback volume.
i`ve adapted player to use it from keyboard on windows.
keys to operate:
'space' - pause, resume
'esc' - out
up, down - volume
left, right - forward, backward seek.
but i small issue i cant handle: loop play of file.
a.play(mode=PlayMode.ONCE_ASYNC) - not working in my code.
give an advice please.
from abstractaudioplayer import AbstractAudioPlayer, AudioPlayerError, State, PlayMode
from ctypes import windll, create_unicode_buffer
import threading
import time
from pynput import keyboard
from pprint import pprint
from pydub import AudioSegment #https://pythonrepo.com/repo/jiaaro-pydub-python-audio
pprint ('клавиши управления:')
pprint ('escape: выход, space: пауза + снятие с паузы')
pprint ('громкость: вверх, вниз, перемотка: влево, вправо')
class AudioPlayerWindows(AbstractAudioPlayer):
def __init__(self, filename, callback=None):
super().__init__(filename, callback)
self._alias = "A{}".format(id(self))
self._buffer = create_unicode_buffer(255)
def _mciSendString(self, command):
result = windll.winmm.mciSendStringW(command, self._buffer, 255, 0)
return result, self._buffer.value or ""
def _do_load_player(self):
ret, _a = self._mciSendString('open "{}" type mpegvideo alias {}'.format(self._filename, self._alias))
ret = int(ret)
if ret > 0:
raise AudioPlayerError( 'Failed to play "{}"'.format(self.fullfilename))
self._mciSendString('set {} time format ms'.format(self._alias))
return ret
def _get_duration(self):
_, length = self._mciSendString('status {} length'.format(self._alias))
return float(length or 0) / 1000
def _get_position(self):
_, position = self._mciSendString('status {} position'.format(self._alias))
return float(position or 0) / 1000
def _set_position(self, pos):
pos = int(float(pos) * 1000)
if True or self.state == State.PLAYING:
self._mciSendString('play {} from {}'.format(self._alias, pos))
if self.state == State.PAUSED:
self._dopause()
else:
self._mciSendString('seek {} to {}'.format(self._alias, pos))
def _set_volume(self, value):
value = int(value * 10) # MCI volume: 0...1000
self._mciSendString(
'setaudio {} volume to {}'.format(self._alias, value))
def _doplay(self, loop=False, block=False):
sloop = 'repeat' if loop else ''
swait = 'wait' if block else ''
self._mciSendString('play {} from 0 {} {}'.format(
self._alias, sloop, swait))
def _dopause(self):
self._mciSendString('pause {}'.format(self._alias))
def _doresume(self):
self._mciSendString('resume {}'.format(self._alias))
def _dostop(self):
self._mciSendString('stop {}'.format(self._alias))
self._mciSendString('seek {} to 0'.format(self._alias))
def _doclose(self):
self._mciSendString('close {}'.format(self._alias))
def background_audio():
a.play(mode=PlayMode.ONCE_ASYNC) # not working
#if a.position == song.duration_seconds:
#print('конец')
while True:
if pausing.is_set():
pausing.clear()
resuming.clear()
a.pause()
if resuming.is_set():
pausing.clear()
resuming.clear()
a.resume()
if stopping.is_set():
a.stop()
a.close()
return False
if volume_up.is_set():
volume_down.clear()
volume_up.clear()
a.volume=a.volume+10
if volume_down.is_set():
volume_down.clear()
volume_up.clear()
a.volume=a.volume-10
if forward.is_set():
forward.clear()
backward.clear()
a.position=a.position+3.0
if backward.is_set():
forward.clear()
backward.clear()
a.position=a.position-3.0
def on_press(key):
if key == keyboard.Key.esc: # escape pressed - stop listener
print("Stopping")
stopping.set()
return False
try:
k = key.char # single-char keys
except:
k = key.name # other keys
if k == 'space' and a.state == State.PLAYING: # space - pause
print('Pause')
#print(a.state)
pausing.set()
if k == 'space' and a.state == State.PAUSED: #space again - resume
print('Resume')
resuming.set()
if k == 'up': #volume up
print('volume up')
volume_up.set()
if k == 'down': #volume down
print('volume down')
volume_down.set()
if k == 'right': #перемотка вперед
print('вперед +3 сек')
forward.set()
if k == 'left': #перемотка назад
print('назад -3 сек')
backward.set()
if __name__ == "__main__":
filename='english.wav' #аудиофайл
a = AudioPlayerWindows(filename)
song = AudioSegment.from_wav(filename) #это нужно только, чтобы узнать длину аудиофайла
print('Длина аудио: {} секунд'.format(int(song.duration_seconds)))
#print(dir(a))
a.volume=30 #громкость при старте
#print(a.duration)
#print(a.position)
#print(PlayMode(0))
pausing = threading.Event()
resuming = threading.Event()
volume_up = threading.Event()
volume_down = threading.Event()
stopping = threading.Event()
forward = threading.Event()
backward = threading.Event()
audio_thread = threading.Thread(target=background_audio) #PlayMode.ONCE_ASYNC - проиграть один раз
audio_thread.start()
listener = keyboard.Listener(on_press=on_press)
listener.start()
listener.join()
audio_thread.join()
hello!
i`ve adapted player to use it from keyboard on windows. keys to operate: 'space' - pause, resume 'esc' - out up, down - volume left, right - forward, backward seek.
but i small issue i cant handle: loop play of file. a.play(mode=PlayMode.ONCE_ASYNC) - not working in my code. give an advice please.