From c87d5deedfa920aa49a6a9929e4fd3a696a06ddc Mon Sep 17 00:00:00 2001 From: jeremygan2021 Date: Tue, 3 Mar 2026 21:27:07 +0800 Subject: [PATCH] 1 --- display.py | 10 + main.py | 141 +++++++- .../__pycache__/server.cpython-312.pyc | Bin 14717 -> 21697 bytes websocket_server/received_audio.mp3 | Bin 6812 -> 3788 bytes websocket_server/received_audio.raw | Bin 67584 -> 34816 bytes websocket_server/requirements.txt | 1 + websocket_server/server.py | 339 +++++++++++++++++- 7 files changed, 460 insertions(+), 31 deletions(-) diff --git a/display.py b/display.py index acabb97..ec525ff 100644 --- a/display.py +++ b/display.py @@ -83,3 +83,13 @@ class Display: self.tft.fill_rect(100, 240 - bar_height, 40, bar_height - last_bar_height, color) return bar_height + + def show_image(self, x, y, width, height, rgb565_data): + """在指定位置显示RGB565格式的图片数据""" + if not self.tft: return + + try: + # 将字节数据转换为适合blit_buffer的格式 + self.tft.blit_buffer(rgb565_data, x, y, width, height) + except Exception as e: + print(f"Show image error: {e}") diff --git a/main.py b/main.py index b2d0ff8..9ab1d1e 100644 --- a/main.py +++ b/main.py @@ -9,6 +9,7 @@ from audio import AudioPlayer, Microphone from display import Display from websocket_client import WebSocketClient import uselect +import ujson WIFI_SSID = "Tangledup-AI" WIFI_PASS = "djt12345678" @@ -16,15 +17,22 @@ SERVER_IP = "6.6.6.88" SERVER_PORT = 8000 SERVER_URL = f"ws://{SERVER_IP}:{SERVER_PORT}/ws/audio" +# 图片接收状态 +IMAGE_STATE_IDLE = 0 +IMAGE_STATE_RECEIVING = 1 -def connect_wifi(max_retries=3): +IMG_WIDTH = 120 +IMG_HEIGHT = 120 + + +def connect_wifi(max_retries=5): wlan = network.WLAN(network.STA_IF) try: wlan.active(False) - time.sleep(1) + time.sleep(2) wlan.active(True) - time.sleep(1) + time.sleep(3) except Exception as e: print(f"WiFi init error: {e}") return False @@ -40,23 +48,25 @@ def connect_wifi(max_retries=3): start_time = time.ticks_ms() while not wlan.isconnected(): - if time.ticks_diff(time.ticks_ms(), start_time) > 20000: + if time.ticks_diff(time.ticks_ms(), start_time) > 30000: print("WiFi timeout!") break time.sleep(0.5) + print(".", end="") if wlan.isconnected(): - print('WiFi connected!') + print('\nWiFi connected!') return True if attempt < max_retries - 1: + print(f"\nRetry {attempt + 1}/{max_retries}...") wlan.disconnect() - time.sleep(2) + time.sleep(3) except Exception as e: print(f"WiFi error: {e}") if attempt < max_retries - 1: - time.sleep(3) + time.sleep(5) print("WiFi connection failed!") return False @@ -69,6 +79,98 @@ def print_asr(text, display=None): display.text(text, 0, 40, st7789.WHITE) +def process_message(msg, display, image_state, image_data_list): + """处理WebSocket消息,返回新的image_state""" + if not isinstance(msg, str): + return image_state + + # 处理ASR消息 + if msg.startswith("ASR:"): + print_asr(msg[4:], display) + + # 处理图片生成状态消息 + elif msg.startswith("GENERATING_IMAGE:"): + print(msg) + if display and display.tft: + display.fill_rect(0, 40, 240, 100, st7789.BLACK) + display.text("正在生成图片...", 0, 40, st7789.YELLOW) + + # 处理提示词优化消息 + elif msg.startswith("PROMPT:"): + prompt = msg[7:] + print(f"Optimized prompt: {prompt}") + if display and display.tft: + display.fill_rect(0, 60, 240, 40, st7789.BLACK) + display.text("提示词: " + prompt[:20], 0, 60, st7789.CYAN) + + # 处理图片开始消息 + elif msg.startswith("IMAGE_START:"): + try: + parts = msg.split(":") + size = int(parts[1]) + img_size = int(parts[2]) if len(parts) > 2 else 64 + print(f"Image start, size: {size}, img_size: {img_size}") + image_data_list.clear() + image_data_list.append(img_size) # 保存图片尺寸 + return IMAGE_STATE_RECEIVING + except Exception as e: + print(f"IMAGE_START parse error: {e}") + return image_state + + # 处理图片数据消息 + elif msg.startswith("IMAGE_DATA:") and image_state == IMAGE_STATE_RECEIVING: + try: + data = msg.split(":", 1)[1] + image_data_list.append(data) + except: + pass + + # 处理图片结束消息 + elif msg == "IMAGE_END" and image_state == IMAGE_STATE_RECEIVING: + try: + print("Image received, processing...") + + # 获取图片尺寸 + img_size = image_data_list[0] if image_data_list else 64 + hex_data = "".join(image_data_list[1:]) + image_data_list.clear() + + # 将hex字符串转换为字节数据 + img_data = bytes.fromhex(hex_data) + + print(f"Image data len: {len(img_data)}") + + # 在屏幕中心显示图片 + if display and display.tft: + # 计算居中位置 + x = (240 - img_size) // 2 + y = (240 - img_size) // 2 + + # 显示图片 + display.show_image(x, y, img_size, img_size, img_data) + + display.fill_rect(0, 0, 240, 30, st7789.WHITE) + display.text("图片已生成!", 0, 5, st7789.BLACK) + + gc.collect() + print("Image displayed") + + except Exception as e: + print(f"Image process error: {e}") + + return IMAGE_STATE_IDLE + + # 处理图片错误消息 + elif msg.startswith("IMAGE_ERROR:"): + print(msg) + if display and display.tft: + display.fill_rect(0, 40, 240, 100, st7789.BLACK) + display.text("图片生成失败", 0, 40, st7789.RED) + return IMAGE_STATE_IDLE + + return image_state + + def main(): print("\n=== ESP32 Audio ASR ===\n") @@ -91,6 +193,8 @@ def main(): is_recording = False ws = None + image_state = IMAGE_STATE_IDLE + image_data_list = [] def connect_ws(): nonlocal ws @@ -151,8 +255,7 @@ def main(): events = poller.poll(0) if events: msg = ws.recv() - if isinstance(msg, str) and msg.startswith("ASR:"): - print_asr(msg[4:], display) + image_state = process_message(msg, display, image_state, image_data_list) except: ws = None @@ -170,16 +273,26 @@ def main(): try: ws.send("STOP_RECORDING") - t_wait = time.ticks_add(time.ticks_ms(), 500) + # 等待更长时间以接收图片生成结果 + t_wait = time.ticks_add(time.ticks_ms(), 30000) # 等待30秒 + prev_image_state = image_state while time.ticks_diff(t_wait, time.ticks_ms()) > 0: poller = uselect.poll() poller.register(ws.sock, uselect.POLLIN) - events = poller.poll(100) + events = poller.poll(500) if events: msg = ws.recv() - if isinstance(msg, str) and msg.startswith("ASR:"): - print_asr(msg[4:], display) - except: + prev_image_state = image_state + image_state = process_message(msg, display, image_state, image_data_list) + # 如果之前在接收图片,现在停止了,说明图片接收完成 + if prev_image_state == IMAGE_STATE_RECEIVING and image_state == IMAGE_STATE_IDLE: + break + else: + # 检查是否还在接收图片 + if image_state == IMAGE_STATE_IDLE: + break + except Exception as e: + print(f"Stop recording error: {e}") ws = None gc.collect() diff --git a/websocket_server/__pycache__/server.cpython-312.pyc b/websocket_server/__pycache__/server.cpython-312.pyc index 3be65f6d2c122c8cf7863be9b38faa5d8e5a4888..caec868772f7071675ac8ef9f3250e4f3316f83d 100644 GIT binary patch literal 21697 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

=KJx3c@ zCO$?Gm$F(E@bI@qdVu;nIc^gYf2Yu(xDL08iN7n>Lj2blZj%we#tTur2)8MTU+Z#F zd>d|45x?G!;NQ-|ZK=fD8U*upBW}we-fl8N{O`+CY#QO;Z)wSbhkr=JZ6(A%q;G>b zlZxB)VkRvI#Vc`JIl)vFL);JPRfIpS8se9QEmC_07Ere2+i^i~0}cziap ziiI~Y&5;7(4GjU1H?%1CMxFqr6o^o6u@I$~$*fA@jg6^RiSVXC1SvNqB1pNZM7cLr zGOJN|QUr=?_EB>W%S zQL*2NvLNYqT2$1MLnRwmv0*A3X0V|~ zWGj+3@vzLl~FHf--ihiFf2FCxsP=r$0 zPWXL=%%KC!@`IRgr3vBu7!yIt$0CIDW2x-H z4Z@F8k{>J)eq6xjmWWWw1~#`c(^(??gizC&f=|)~(1o953g}$XCmI~3XR|4}LKM$u zFqWEm8!Kw@QQ%N1r3I!KMX#JuNG0 zb&gv5U{i@a?rf^Ab|*J&h8>C6VI;R?V-@>n-BAE`Awh&V;sE;zfzAdR@Tl>AWxE02 zW2lNqM&L_;<_Rl}TnM=D8X;>^L^62{Y%H{${mK#j-%uvn7mwPshG2uCp$-gf>{kJ4 zF)AUWU?&JZ95`W#q{X6DtSzYuK9@ivLnDpM)7%%4z~vO96{sLF=7diPiovh~Ul;`Q z*o4(|)N(Q+G*3)$=OWJ{&~qqQK*5hu@CFKwpum9w)-s2DEZDE!#O-<9fk$Lap(`MO zofz%|dkUxxafP+WNn^33X!6iWE@RvQ8(k*r1Z#DT2!Zo7IwBJPj#EUsh5JO*Hu?{c zfezw2%OHfc4affxYxZN!?_0n5OaTTC zT={5HI6ZH+_356cdYF7;AiZW<7Q|BiNu2bEby^4z>g+##Xj&Q0FfdqZG)zvNR)m$g z)3R_@1%st?AuP?wDbw=Xga(JNMQN*VV<>W~E(Op1M4yjqZnfe&a6EmbT>yvb9?$zm z-l>NIce-Q2Z`@&_abpzy0&S E05m`KP5=M^ delta 5904 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 b`y=t+5&gZxBBpW`T6x4w#*RM9QFs0a6&?;~ diff --git a/websocket_server/received_audio.mp3 b/websocket_server/received_audio.mp3 index 10b03fd71b8671b41f605931c88eeeb87e5a9338..bd5948ace286629a812ce4f049924deb6d40b33d 100644 GIT binary patch literal 3788 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 literal 6812 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 literal 67584 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 diff --git a/websocket_server/requirements.txt b/websocket_server/requirements.txt index c69469c..f2b1c2f 100644 --- a/websocket_server/requirements.txt +++ b/websocket_server/requirements.txt @@ -4,3 +4,4 @@ websockets pydub dashscope python-dotenv +Pillow diff --git a/websocket_server/server.py b/websocket_server/server.py index 915edee..fb5d663 100644 --- a/websocket_server/server.py +++ b/websocket_server/server.py @@ -5,11 +5,14 @@ import os import subprocess import struct import base64 +import time +import hashlib +import json from dotenv import load_dotenv import dashscope from dashscope.audio.asr import Recognition, RecognitionCallback, RecognitionResult from dashscope import ImageSynthesis -import json +from dashscope import Generation # 加载环境变量 load_dotenv() @@ -17,14 +20,272 @@ dashscope.api_key = os.getenv("DASHSCOPE_API_KEY") app = FastAPI() +# 字体文件配置 +FONT_FILE = "GB2312-16.bin" +FONT_CHUNK_SIZE = 512 +HIGH_FREQ_CHARS = "的一是在不了有和人这中大为上个国我以要他时来用们生到作地于出就分对成会可主发年动同工也能下过子说产种面而方后多定行学法所民得经十三之进着等部度家电力里如水化高自二理起小物现实加量都两体制机当使点从业本去把性好应开它合还因由其些然前外天政四日那社义事平形相全表间样与关各重新线内数正心反你明看原又么利比或但质气第向道命此变条只没结解问意建月公无系军很情者最立代想已通并提直题党程展五果料象员革位入常文总次品式活设及管特件长求老头基资边流路级少图山统接知较将组见计别她手角期根论运农指几九区强放决西被干做必战先回则任取据处队南给色光门即保治北造百规热领七海口东导器压志世金增争济阶油思术极交受联什认六共权收证改清己美再采转更单风切打白教速花带安场身车例真务具万每目至达走积示议声报斗完类八离华名确才科张信马节话米整空元况今集温传土许步群广石记需段研界拉林律叫且究观越织装影算低持音众书布复容儿须际商非验连断深难近矿千周委素技备半办青省列习响约支般史感劳便团往酸历市克何除消构府称太准精值号率族维划选标写存候毛亲快效斯院查江型眼王按格养易置派层片始却专状育厂京识适属圆包火住调满县局照参红细引听该铁价严龙飞" + +# 高频字对应的Unicode码点列表 +HIGH_FREQ_UNICODE = [ord(c) for c in HIGH_FREQ_CHARS] + +# 字体缓存 +font_cache = {} +font_md5 = {} + +def calculate_md5(filepath): + """计算文件的MD5哈希值""" + if not os.path.exists(filepath): + return None + hash_md5 = hashlib.md5() + with open(filepath, "rb") as f: + for chunk in iter(lambda: f.read(4096), b""): + hash_md5.update(chunk) + return hash_md5.hexdigest() + +def init_font_cache(): + """初始化字体缓存和MD5""" + global font_cache, font_md5 + script_dir = os.path.dirname(os.path.abspath(__file__)) + font_path = os.path.join(script_dir, FONT_FILE) + + if not os.path.exists(font_path): + font_path = os.path.join(script_dir, "..", FONT_FILE) + + if os.path.exists(font_path): + font_md5 = calculate_md5(font_path) + print(f"Font MD5: {font_md5}") + + # 预加载高频字到缓存 + for unicode_val in HIGH_FREQ_UNICODE: + try: + char = chr(unicode_val) + gb_bytes = char.encode('gb2312') + if len(gb_bytes) == 2: + code = struct.unpack('>H', gb_bytes)[0] + area = (code >> 8) - 0xA0 + index = (code & 0xFF) - 0xA0 + if area >= 1 and index >= 1: + offset = ((area - 1) * 94 + (index - 1)) * 32 + with open(font_path, "rb") as f: + f.seek(offset) + font_data = f.read(32) + if len(font_data) == 32: + font_cache[unicode_val] = font_data + except: + pass + print(f"Preloaded {len(font_cache)} high-frequency characters") + +# 启动时初始化字体缓存 +init_font_cache() + # 存储接收到的音频数据 audio_buffer = bytearray() RECORDING_RAW_FILE = "received_audio.raw" RECORDING_MP3_FILE = "received_audio.mp3" -VOLUME_GAIN = 10.0 # 放大倍数 -FONT_FILE = "GB2312-16.bin" +VOLUME_GAIN = 10.0 GENERATED_IMAGE_FILE = "generated_image.png" GENERATED_THUMB_FILE = "generated_thumb.bin" +OUTPUT_DIR = "output_images" + +if not os.path.exists(OUTPUT_DIR): + os.makedirs(OUTPUT_DIR) + +image_counter = 0 + +def get_output_path(): + global image_counter + image_counter += 1 + timestamp = time.strftime("%Y%m%d_%H%M%S") + return os.path.join(OUTPUT_DIR, f"image_{timestamp}_{image_counter}.png") + +THUMB_SIZE = 245 + +# 字体请求队列(用于重试机制) +font_request_queue = {} +FONT_RETRY_MAX = 3 + + +def get_font_data(unicode_val): + """从字体文件获取单个字符数据(带缓存)""" + if unicode_val in font_cache: + return font_cache[unicode_val] + + try: + char = chr(unicode_val) + gb_bytes = char.encode('gb2312') + if len(gb_bytes) == 2: + code = struct.unpack('>H', gb_bytes)[0] + area = (code >> 8) - 0xA0 + index = (code & 0xFF) - 0xA0 + + if area >= 1 and index >= 1: + offset = ((area - 1) * 94 + (index - 1)) * 32 + + script_dir = os.path.dirname(os.path.abspath(__file__)) + font_path = os.path.join(script_dir, FONT_FILE) + if not os.path.exists(font_path): + font_path = os.path.join(script_dir, "..", FONT_FILE) + if not os.path.exists(font_path): + font_path = FONT_FILE + + if os.path.exists(font_path): + with open(font_path, "rb") as f: + f.seek(offset) + font_data = f.read(32) + if len(font_data) == 32: + font_cache[unicode_val] = font_data + return font_data + except: + pass + return None + + +def send_font_batch_with_retry(websocket, code_list, retry_count=0): + """批量发送字体数据(带重试机制)""" + global font_request_queue + + success_codes = set() + failed_codes = [] + + for code_str in code_list: + if not code_str: + continue + + try: + unicode_val = int(code_str) + font_data = get_font_data(unicode_val) + + if font_data: + import binascii + hex_data = binascii.hexlify(font_data).decode('utf-8') + response = f"FONT_DATA:{code_str}:{hex_data}" + asyncio.run_coroutine_threadsafe( + websocket.send_text(response), + asyncio.get_event_loop() + ) + success_codes.add(unicode_val) + else: + failed_codes.append(code_str) + except Exception as e: + print(f"Error processing font {code_str}: {e}") + failed_codes.append(code_str) + + # 记录失败的请求用于重试 + if failed_codes and retry_count < FONT_RETRY_MAX: + req_key = f"retry_{retry_count}_{time.time()}" + font_request_queue[req_key] = { + 'codes': failed_codes, + 'retry': retry_count + 1, + 'timestamp': time.time() + } + + return len(success_codes), failed_codes + + +async def send_font_with_fragment(websocket, unicode_val): + """使用二进制分片方式发送字体数据""" + font_data = get_font_data(unicode_val) + if not font_data: + return False + + # 分片发送 + total_size = len(font_data) + chunk_size = FONT_CHUNK_SIZE + + for i in range(0, total_size, chunk_size): + chunk = font_data[i:i+chunk_size] + seq_num = i // chunk_size + + # 构造二进制消息头: 2字节序列号 + 2字节总片数 + 数据 + header = struct.pack('> 8) - 0xA0 + index = (code & 0xFF) - 0xA0 + if area >= 1 and index >= 1: + offset = ((area - 1) * 94 + (index - 1)) * 32 + script_dir = os.path.dirname(os.path.abspath(__file__)) + font_path = os.path.join(script_dir, FONT_FILE) + if not os.path.exists(font_path): + font_path = os.path.join(script_dir, "..", FONT_FILE) + if os.path.exists(font_path): + with open(font_path, "rb") as f: + f.seek(offset) + font_data = f.read(32) + else: + font_data = None + else: + font_data = None + + if font_data: + import binascii + hex_data = binascii.hexlify(font_data).decode('utf-8') + response = f"FONT_DATA:{code_str}:{hex_data}" + await websocket.send_text(response) + except Exception as e: + print(f"Error handling font request: {e}") class MyRecognitionCallback(RecognitionCallback): def __init__(self, websocket: WebSocket, loop: asyncio.AbstractEventLoop): @@ -72,13 +333,46 @@ def process_chunk_32_to_16(chunk_bytes, gain=1.0): return processed_chunk +def optimize_prompt(asr_text): + """使用大模型优化提示词""" + print(f"Optimizing prompt for: {asr_text}") + + system_prompt = """你是一个AI图像提示词优化专家。将用户简短的语音识别结果转化为详细的、适合AI图像生成的英文提示词。 +要求: +1. 保留核心内容和主要元素 +2. 添加适合AI绘画的描述词(风格、光线、氛围等) +3. 用英文输出 +4. 简洁但描述详细 +5. 不要添加多余解释,直接输出优化后的提示词""" + + try: + response = Generation.call( + model='qwen-turbo', + prompt=f'{system_prompt}\n\n用户语音识别结果:{asr_text}\n\n优化后的提示词:', + max_tokens=200, + temperature=0.8 + ) + + if response.status_code == 200: + optimized = response.output.choices[0].message.content.strip() + print(f"Optimized prompt: {optimized}") + return optimized + else: + print(f"Prompt optimization failed: {response.code} - {response.message}") + return asr_text + + except Exception as e: + print(f"Error optimizing prompt: {e}") + return asr_text + + def generate_image(prompt, websocket=None): """调用万相文生图API生成图片""" print(f"Generating image for prompt: {prompt}") try: response = ImageSynthesis.call( - model='wanx-v1.0-text-to-image', + model='wan2.6-t2i', prompt=prompt, size='512x512', n=1 @@ -92,21 +386,26 @@ def generate_image(prompt, websocket=None): urllib.request.urlretrieve(image_url, GENERATED_IMAGE_FILE) print(f"Image saved to {GENERATED_IMAGE_FILE}") + # 保存一份到 output_images 目录 + output_path = get_output_path() + import shutil + shutil.copy(GENERATED_IMAGE_FILE, output_path) + print(f"Image also saved to {output_path}") + # 缩放图片并转换为RGB565格式 try: from PIL import Image img = Image.open(GENERATED_IMAGE_FILE) - # 缩小到120x120 (屏幕是240x240,但需要考虑内存限制) - thumb_size = 120 - img = img.resize((thumb_size, thumb_size), Image.LANCZOS) + # 缩小到THUMB_SIZE x THUMB_SIZE + img = img.resize((THUMB_SIZE, THUMB_SIZE), Image.LANCZOS) # 转换为RGB565格式的原始数据 # 每个像素2字节 (R5 G6 B5) rgb565_data = bytearray() - for y in range(thumb_size): - for x in range(thumb_size): + for y in range(THUMB_SIZE): + for x in range(THUMB_SIZE): r, g, b = img.getpixel((x, y))[:3] # 转换为RGB565 @@ -255,13 +554,19 @@ async def websocket_endpoint(websocket: WebSocket): # 先发送 ASR 文字到 ESP32 显示 await websocket.send_text(f"ASR:{asr_text}") - await websocket.send_text("GENERATING_IMAGE:正在生成图片,请稍候...") + await websocket.send_text("GENERATING_IMAGE:正在优化提示词...") # 等待一会让 ESP32 显示文字 await asyncio.sleep(0.5) + # 优化提示词 + optimized_prompt = await asyncio.to_thread(optimize_prompt, asr_text) + + await websocket.send_text(f"PROMPT:{optimized_prompt}") + await websocket.send_text("GENERATING_IMAGE:正在生成图片,请稍候...") + # 调用文生图API - image_path = await asyncio.to_thread(generate_image, asr_text) + image_path = await asyncio.to_thread(generate_image, optimized_prompt) if image_path and os.path.exists(image_path): # 读取图片并发送回ESP32 @@ -270,14 +575,14 @@ async def websocket_endpoint(websocket: WebSocket): print(f"Sending image to ESP32, size: {len(image_data)} bytes") - # 将图片转换为base64发送 - image_b64 = base64.b64encode(image_data).decode('utf-8') - await websocket.send_text(f"IMAGE_START:{len(image_data)}") + # 使用hex编码发送(每个字节2个字符) + image_hex = image_data.hex() + await websocket.send_text(f"IMAGE_START:{len(image_data)}:{THUMB_SIZE}") # 分片发送图片数据 - chunk_size = 4096 - for i in range(0, len(image_b64), chunk_size): - chunk = image_b64[i:i+chunk_size] + chunk_size = 1024 + for i in range(0, len(image_hex), chunk_size): + chunk = image_hex[i:i+chunk_size] await websocket.send_text(f"IMAGE_DATA:{chunk}") await websocket.send_text("IMAGE_END")