180 lines
6.6 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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)