180 lines
6.6 KiB
Python
Executable File
180 lines
6.6 KiB
Python
Executable File
# from playsound import playsound
|
||
# import os
|
||
# from tools.log import CustomLogger
|
||
|
||
# class AudioPlayer:
|
||
# def __init__(self,audio_file=None):
|
||
# self.audio_file = audio_file
|
||
# self.logger = CustomLogger(log_name=audio_file)
|
||
# if audio_file:
|
||
# self.logger.enable_file_logging()
|
||
|
||
# def play(self,file_path,remove_file=True):
|
||
# try:
|
||
# if self.audio_file:
|
||
# self.logger.log_info(f"Playing audio file: {file_path}")
|
||
# playsound(file_path)
|
||
# if remove_file:
|
||
# os.remove(file_path)
|
||
# except Exception as e:
|
||
# self.logger.log_info(f"Error playing audio file: {e}")
|
||
|
||
# if __name__ == "__main__":
|
||
# player = AudioPlayer()
|
||
# player.play('audio.wav')
|
||
|
||
import pygame
|
||
import os
|
||
import threading
|
||
import sys
|
||
|
||
# current_dir = os.path.dirname(os.path.abspath(__file__))
|
||
# parent_parent_dir = os.path.abspath(os.path.join(current_dir, os.pardir, os.pardir))
|
||
# sys.path.append(parent_parent_dir)
|
||
from tools.log import CustomLogger
|
||
|
||
|
||
class AudioPlayer:
|
||
_current_priority = -1 # 初始优先级为 -1,表示没有音频在播放
|
||
_current_thread = None # 当前播放的线程
|
||
|
||
def __init__(self, audio_file=None):
|
||
self.audio_file = audio_file
|
||
self.logger = CustomLogger()
|
||
pygame.mixer.init() # 初始化混音器
|
||
pygame.mixer.music.set_volume(0.75)
|
||
self.queue = [] # 音频播放队列
|
||
self.queue_lock = threading.Lock() # 用于同步队列的锁
|
||
self.is_playing_queue = False # 标志位,用于指示是否正在播放队列中的音频
|
||
self.queue_thread = None # 播放队列的线程
|
||
|
||
def play(self, file_path, remove_file=True, priority=10, fade_duration=5):
|
||
"""
|
||
播放音频,并在播放结束时淡出。添加淡入淡出效果避免爆音。
|
||
:param file_path: 音频文件路径
|
||
:param remove_file: 是否在播放结束后删除文件
|
||
:param priority: 播放优先级
|
||
:param fade_duration: 淡入淡出效果的时长,单位为毫秒
|
||
"""
|
||
if priority >= AudioPlayer._current_priority: # 检查优先级
|
||
if self.audio_file:
|
||
self.logger.log_info(
|
||
f"Stopping any ongoing audio with priority {AudioPlayer._current_priority} and playing new file with priority {priority}: {file_path}"
|
||
)
|
||
|
||
# if pygame.mixer.music.get_busy(): # 检查是否有音频正在播放
|
||
# pygame.mixer.music.fadeout(fade_duration) # 使用fadeout淡出当前音频
|
||
|
||
# AudioPlayer._current_priority = priority # 更新当前播放的优先级
|
||
# AudioPlayer._current_thread = threading.current_thread() # 更新当前线程
|
||
|
||
# pygame.mixer.music.load(file_path) # 加载新的音频文件
|
||
# pygame.mixer.music.set_volume(0.75)
|
||
# pygame.mixer.music.play(fade_ms=fade_duration) # 使用fade_ms淡入新的音频
|
||
|
||
AudioPlayer._current_priority = priority # 更新当前播放的优先级
|
||
AudioPlayer._current_thread = threading.current_thread() # 更新当前线程
|
||
|
||
pygame.mixer.music.load(file_path) # 加载新的音频文件
|
||
pygame.mixer.music.set_volume(0.75)
|
||
pygame.mixer.music.play()
|
||
|
||
while (
|
||
pygame.mixer.music.get_busy()
|
||
and AudioPlayer._current_thread == threading.current_thread()
|
||
): # 等待音频播放结束
|
||
pygame.time.Clock().tick(10)
|
||
|
||
if remove_file:
|
||
os.remove(file_path)
|
||
|
||
if (
|
||
AudioPlayer._current_thread == threading.current_thread()
|
||
): # 如果当前线程仍是播放线程
|
||
AudioPlayer._current_priority = -1 # 播放完成后重置优先级
|
||
else:
|
||
if self.audio_file:
|
||
self.logger.log_info(
|
||
f"Skipped playing file {file_path} with lower priority {priority}"
|
||
)
|
||
|
||
# 队列播放函数
|
||
def queue_play(self, file_path_list, priority=10):
|
||
# 将文件路径和优先级添加到队列
|
||
with self.queue_lock:
|
||
self.queue.append((file_path_list, priority))
|
||
|
||
# 如果没有在播放队列,启动一个线程开始播放
|
||
if not self.is_playing_queue:
|
||
self.is_playing_queue = True
|
||
self.queue_thread = threading.Thread(target=self._process_queue)
|
||
self.queue_thread.start()
|
||
|
||
# 处理队列中的音频播放
|
||
def _process_queue(self):
|
||
while self.queue:
|
||
# 取出队列中的第一个音频列表和优先级
|
||
with self.queue_lock:
|
||
file_paths, priority = self.queue.pop(0)
|
||
|
||
# 依次播放队列中的音频文件
|
||
for file_path in file_paths:
|
||
self.play(file_path, remove_file=True, priority=priority)
|
||
|
||
self.is_playing_queue = False # 队列播放完成后重置标志位
|
||
|
||
# 停止播放当前音频
|
||
def stop(self):
|
||
if pygame.mixer.music.get_busy():
|
||
pygame.mixer.music.stop() # 停止当前播放
|
||
AudioPlayer._current_priority = -1 # 停止后重置优先级
|
||
AudioPlayer._current_thread = None # 清除当前线程
|
||
|
||
# 停止队列播放
|
||
def stop_queue(self):
|
||
if self.queue_thread and self.queue_thread.is_alive():
|
||
self.queue = [] # 清空队列
|
||
self.is_playing_queue = False # 重置队列播放标志
|
||
self.stop() # 停止当前音频播放
|
||
|
||
|
||
if __name__ == "__main__":
|
||
import time
|
||
|
||
player = AudioPlayer()
|
||
|
||
def thread_play(file_path, priority):
|
||
player.play(file_path, priority=priority, remove_file=False)
|
||
|
||
# 启动线程A,优先级为5
|
||
threading.Thread(
|
||
target=thread_play,
|
||
args=("/home/jsfb/jsfb_ws/MassageRobot_Dobot/Language/pre_mp3/按摩已结束.mp3", 10),
|
||
).start()
|
||
|
||
# time.sleep(2)
|
||
|
||
# 启动线程B,优先级为7(更高),强制停止A并播放新的音频
|
||
threading.Thread(
|
||
target=thread_play,
|
||
args=("/home/jsfb/jsfb_ws/MassageRobot_Dobot/Language/pre_mp3/我在/audio_1.mp3", 10),
|
||
).start()
|
||
|
||
time.sleep(2)
|
||
|
||
# 启动线程C,优先级为3(更低),不会打断线程B的播放
|
||
threading.Thread(
|
||
target=thread_play,
|
||
args=("/home/jsfb/jsfb_ws/MassageRobot_Dobot/Language/pre_mp3/完成复位.mp3", 3),
|
||
).start()
|
||
|
||
time.sleep(2)
|
||
|
||
# 启动线程D,优先级为5
|
||
threading.Thread(
|
||
target=thread_play,
|
||
args=("/home/jsfb/jsfb_ws/MassageRobot_Dobot/Language/pre_mp3/connect_successfully.mp3", 5),
|
||
).start()
|
||
|
||
time.sleep(2)
|