From 7c15077674fe4ef2814ed350a4278b0941080989 Mon Sep 17 00:00:00 2001 From: JULM-COMPUTER Date: Sun, 27 Apr 2025 17:48:55 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- InterphoneHandler.py | 74 +++++++++++++++++++++++++----------------- SingletonThreadPool.py | 3 +- 2 files changed, 45 insertions(+), 32 deletions(-) diff --git a/InterphoneHandler.py b/InterphoneHandler.py index 114350a..5bb4681 100644 --- a/InterphoneHandler.py +++ b/InterphoneHandler.py @@ -7,6 +7,8 @@ import urequests from machine import Pin, I2S import ubinascii import urandom +import select +import gc import shared_vars @@ -21,19 +23,22 @@ def init_i2s(): sd=Pin(shared_vars.SD_PIN), # Serial data output mode=I2S.TX, # 使用发送模式 bits=shared_vars.BITS_PER_SAMPLE, # 修改为 16 位数据 - format=I2S.MONO if shared_vars.CHANNELS == 1 else I2S.STEREO, # 修正声道判断逻辑 + format=I2S.MONO if shared_vars.CHANNELS == 1 else I2S.STEREO, # 声道判断逻辑 rate=shared_vars.SAMPLE_RATE, # 采样率 ibuf=shared_vars.BUFFER_SIZE) # 输入缓冲区大小 return i2s class InterphoneHandler: + def __init__(self): + self.audio_out = None # 全局 I2S 实例 def play_wav_file(self, data): try: # 要播放的本地 WAV 文件 WAV_FILE = data['file'] # 初始化 I2S 接口 - audio_out = init_i2s() + if not self.audio_out: + self.audio_out = init_i2s() # 打开 WAV 文件 with open(WAV_FILE, 'rb') as f: @@ -46,70 +51,78 @@ class InterphoneHandler: break # 将音频数据写入 I2S 接口 print('将音频数据写入 I2S 接口') - audio_out.write(data) + self.audio_out.write(data) except Exception as e: print(f"播放音频时出错: {e}") finally: - if 'audio_out' in locals(): - audio_out.deinit() + if self.audio_out: + self.audio_out.deinit() + self.audio_out = None def stream_and_play(self, data): - shared_vars.player_name = data['voice_url'] - url = data['voice_url'] # 替换为音频文件的URL - volume = data.get('volume', 1.0) # 从 data 中读取音量信息,默认值为 1.0(原始音量) + # 停止之前的播放 + self.stop_playing(data) + gc.collect() # 强制回收内存 + shared_vars.player_name = url = data['voice_url'] + volume = data.get('volume', 1.0) print(f"播放音频 URL: {url}, 音量: {volume}") time.sleep(1) shared_vars.player_flag = True - try: - print("添加请求头信息") - headers = { - 'User-Agent': 'MicroPython v1.0.0' - } - print("发送 HTTP 请求,获取流式响应") - response = urequests.get(url, headers=headers, stream=True) - print("检查响应状态码") + try: + headers = {'User-Agent': 'MicroPython v1.0.0'} + print("发送 HTTP 请求,获取流式响应") + response = urequests.get(url, headers=headers, stream=True, timeout=5) + if response.status_code != 200: print(f"请求失败,状态码: {response.status_code}") response.close() return - print("解析 WAV 头部") - header = response.raw.read(44) + header = response.raw.read(44) if len(header) != 44 or header[0:4] != b'RIFF' or header[8:12] != b'WAVE' or header[12:16] != b'fmt ': - print(header) raise ValueError("Not a valid WAV file") - print("提取采样率、位深、声道数") + # 提取采样率、位深、声道数 shared_vars.SAMPLE_RATE = int.from_bytes(header[24:28], 'little') shared_vars.BITS_PER_SAMPLE = int.from_bytes(header[34:36], 'little') shared_vars.CHANNELS = int.from_bytes(header[22:24], 'little') + # 初始化或重用 I2S 输出 print("初始化 I2S 输出") - audio_out = init_i2s() + self.audio_out = init_i2s() + print("开始流式播放") chunk_size = 128 + sock = response.raw while shared_vars.player_flag and shared_vars.player_name == data['voice_url']: - chunk = response.raw.read(chunk_size) - if not chunk: + r, _, _ = select.select([sock], [], [], 5) # 设置超时时间为 5 秒 + if r: + chunk = sock.read(chunk_size) + if not chunk: + break + self.audio_out.write(chunk) + else: + print("读取超时") break - audio_out.write(chunk) except Exception as e: print("Playback error:", e) finally: - if 'audio_out' in locals(): - audio_out.deinit() if 'response' in locals(): response.close() + if 'sock' in locals(): + sock.close() shared_vars.player_flag = False - print('音频播放完成') - + gc.collect() + print('音频播放结束,清理资源') + def stop_playing(self, data): shared_vars.player_flag = False print("停止播放音频") - pass + if self.audio_out: + self.audio_out.deinit() def get_playing_status(self, data): status = { @@ -117,4 +130,5 @@ class InterphoneHandler: 'player_name': shared_vars.player_name } print(f"获取播放状态: {status}") - return status \ No newline at end of file + return status + diff --git a/SingletonThreadPool.py b/SingletonThreadPool.py index 09c46ec..0c3c9ac 100644 --- a/SingletonThreadPool.py +++ b/SingletonThreadPool.py @@ -7,7 +7,7 @@ class SingletonThreadPool: def __new__(cls): if not cls._instance: - pool_size = 2 + pool_size = 3 cls._instance = super().__new__(cls) cls._instance.pool_size = pool_size cls._instance.task_queue = [] @@ -24,7 +24,6 @@ class SingletonThreadPool: task, args = self.task_queue.pop(0) self.pool_lock.release() try: - gc.collect() task(*args) except Exception as e: print(f"Task execution error: {e}")