准备对AI流式音频发回给前端的机制做较大的修改,先提交1个版本
This commit is contained in:
@@ -152,10 +152,11 @@ def upload_file(tenant_id,mesum_id):
|
||||
|
||||
prompt = (
|
||||
f"作为图片识别和理解助手,您的任务是:"
|
||||
f"\n1. 精确识别图片中的文字内容"
|
||||
f"\n2. 理解文字语义"
|
||||
f"\n3. 从以下候选标题中选择最佳匹配项:"
|
||||
f"\n [{antiques_selected}]"
|
||||
f"\n1. 图片基本上就是展品标题、历史人物或者历史事件"
|
||||
f"\n2. 精确识别图片中的文字内容,理解文字语义,重点分析字体较大的文字"
|
||||
f"\n3. 识别出的文字包含标题或者接近于标题的文字"
|
||||
f"\n4. 从以下候选标题中选择最佳匹配项:"
|
||||
f"\n {antiques_selected}"
|
||||
f"\n\n### 输出要求:"
|
||||
f"\n- 以严格JSON格式输出,包含3个字段:"
|
||||
f"\n • `antique`: 匹配的标题(多个用英文分号';'分割,最多匹配3个,无匹配则空字符串)"
|
||||
|
||||
@@ -71,7 +71,9 @@ class StreamSessionManager:
|
||||
'finished': threading.Event(), # 添加事件对象
|
||||
'sample_rate':sample_rate,
|
||||
'stream_format':stream_format,
|
||||
"tts_chunk_data_valid":False
|
||||
"tts_chunk_data_valid":False,
|
||||
"sentence_complete_event": threading.Event(),
|
||||
"current_processing": False # 标记是否正在处理句子
|
||||
}
|
||||
# 启动任务处理线程
|
||||
threading.Thread(target=self._process_tasks, args=(session_id,), daemon=True).start()
|
||||
@@ -127,7 +129,7 @@ class StreamSessionManager:
|
||||
except Exception as e:
|
||||
logging.error(f"Task processing error: {str(e)}")
|
||||
|
||||
def _generate_audio(self, session_id, text):
|
||||
def _generate_audio1(self, session_id, text):
|
||||
"""实际生成音频(线程池执行)"""
|
||||
session = self.sessions.get(session_id)
|
||||
if not session: return
|
||||
@@ -157,6 +159,27 @@ class StreamSessionManager:
|
||||
session['buffer'].put(f"ERROR:{str(e)}")
|
||||
logging.info(f"--_generate_audio--error {str(e)}")
|
||||
|
||||
def _generate_audio(self, session_id, text):
|
||||
"""实际生成音频(顺序执行)- 用于非流式引擎"""
|
||||
session = self.sessions.get(session_id)
|
||||
if not session:
|
||||
return
|
||||
|
||||
try:
|
||||
# 调用 TTS
|
||||
session['tts_model'].text_tts_call(text)
|
||||
|
||||
# 标记完成
|
||||
session['sentence_complete_event'].set()
|
||||
session['last_active'] = time.time()
|
||||
session['audio_chunk_count'] += 1
|
||||
|
||||
if not session['tts_chunk_data_valid']:
|
||||
session['tts_chunk_data_valid'] = True
|
||||
|
||||
except Exception as e:
|
||||
session['buffer'].put(f"ERROR:{str(e)}".encode())
|
||||
session['sentence_complete_event'].set() # 确保事件被设置
|
||||
|
||||
def close_session(self, session_id):
|
||||
with self.lock:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
TIMEZONE=Asia/Shanghai
|
||||
DASHSCOPE_API_KEY = sk-a47a3fb5f4a94f66bbaf713779101c75
|
||||
DOUBAO_APP_ID = 7282190702
|
||||
|
||||
|
||||
|
||||
@@ -1,467 +1,15 @@
|
||||
INFO: Started server process [50175]
|
||||
INFO: Started server process [2877053]
|
||||
INFO: Waiting for application startup.
|
||||
21:51:05.972 - INFO - 监控服务已启动
|
||||
16:01:53.789 - INFO - 监控服务已启动
|
||||
INFO: Application startup complete.
|
||||
INFO: Uvicorn running on http://0.0.0.0:9580 (Press CTRL+C to quit)
|
||||
WARNING: Invalid HTTP request received.
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
ASR & Monitor Service Start
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
INFO: 35.203.210.77:60796 - "GET / HTTP/1.1" 404 Not Found
|
||||
INFO: 91.196.152.109:33535 - "GET / HTTP/1.1" 404 Not Found
|
||||
INFO: 220.196.160.51:32110 - "GET / HTTP/1.1" 404 Not Found
|
||||
INFO: 180.101.245.250:54556 - "GET / HTTP/1.1" 404 Not Found
|
||||
INFO: 220.196.160.75:44896 - "GET / HTTP/1.1" 404 Not Found
|
||||
INFO: 91.196.152.210:40043 - "GET /favicon.ico HTTP/1.1" 404 Not Found
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
INFO: 221.238.94.141:45448 - "GET / HTTP/1.0" 404 Not Found
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
INFO: 221.238.94.141:45526 - "OPTIONS / HTTP/1.0" 404 Not Found
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
INFO: 221.238.94.141:45640 - "GET /nice%20ports%2C/Trinity.txt.bak HTTP/1.0" 404 Not Found
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
INFO: 221.238.94.141:38084 - "GET /api HTTP/1.0" 404 Not Found
|
||||
WARNING: Invalid HTTP request received.
|
||||
INFO: 221.238.94.141:38098 - "GET /hazelcast/rest/cluster HTTP/1.0" 404 Not Found
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
WARNING: Invalid HTTP request received.
|
||||
INFO: 221.238.94.141:38374 - "GET / HTTP/1.1" 404 Not Found
|
||||
06:57:54.681 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 106.55.206.109:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
06:57:55.071 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 43.144.107.210:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
06:59:18.037 - INFO - Creating TTS request: {'text': '陶鬲形猪首盖盉,商,通高27厘米,腹径20.5厘米,2010年安钢大道M78出土,中国社会科学院考古研究所藏。器型呈猪首状,长嘴,圆眼微凸,双耳直立,憨态可掬。肩部饰三角绳纹,腹及袋足饰细绳纹,作为温酒的容器,加热后美酒从它的口中流出。', 'session_id': '0b4cdbaeaf9111efa53df171065841e8', 'delay_gen_audio': True, 'tts_sample_rate': 48000, 'tts_stream_format': 'mp3', 'model_name': 'cosyvoice-v1/longyuan@Tongyi-Qianwen', 'sample_rate': 48000, 'stream_format': 'mp3'}
|
||||
INFO: 43.144.107.28:0 - "POST /tts/chats/39e9a2ba5a4711f0865bbb55c66f9471/tts?device_id=17513727656058688719 HTTP/1.1" 200 OK
|
||||
INFO: ('1.13.185.116', 50174) - "WebSocket /tts/chats/39e9a2ba5a4711f0865bbb55c66f9471/tts/d45fdb6d-9bcb-4458-9b83-d63f3eb69720" [accepted]
|
||||
06:59:19.472 - INFO - 新连接建立: 414fa19a-4425-4b60-b172-ec661a3457b2
|
||||
06:59:19.472 - INFO - 已经启动 start tts task {audio_stream_id}
|
||||
06:59:19.473 - INFO - ---begin--init QwenTTS-- mp3 48000 cosyvoice-v1/longyuan@Tongyi-Qianwen cosyvoice-v1/longyuan
|
||||
06:59:19.473 - INFO - QwenTTS--get_audio_format-- mp3 48000
|
||||
06:59:19.473 - INFO - setup_tts longyuan MP3 with 48000Hz sample rate, mono channel, 256kbps
|
||||
INFO: connection open
|
||||
06:59:19.617 - INFO - Websocket connected
|
||||
06:59:19.729 - INFO - Qwen CosyVoice tts open
|
||||
06:59:28.170 - INFO - --data_handler on_complete
|
||||
06:59:28.170 - INFO - Qwen CosyVoice tts close
|
||||
06:59:28.170 - INFO - --tts task event set error = None
|
||||
INFO: connection closed
|
||||
07:00:54.600 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 43.144.107.210:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
07:00:54.946 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 43.140.60.44:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
07:04:53.633 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 43.144.107.28:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
07:04:53.793 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 43.140.60.44:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
07:04:57.090 - INFO - Creating TTS request: {'text': '1945年10月,通县民主政府成立,机关设在潮白河西岸侯各庄西北角的一座菩萨庙(圆通庵)内,领导全县人民进行反蒋解放斗争。', 'session_id': '0b4cdbaeaf9111efa53df171065841e8', 'delay_gen_audio': True, 'tts_sample_rate': 48000, 'tts_stream_format': 'mp3', 'model_name': 'cosyvoice-v1/longyuan@Tongyi-Qianwen', 'sample_rate': 48000, 'stream_format': 'mp3'}
|
||||
INFO: 43.140.60.33:0 - "POST /tts/chats/9cb04ecead5111ef99e80242ac120006/tts?device_id=17513727656058688719 HTTP/1.1" 200 OK
|
||||
INFO: ('1.13.185.116', 33684) - "WebSocket /tts/chats/9cb04ecead5111ef99e80242ac120006/tts/c83abcdf-225e-41a1-a20d-0cc228b7c547" [accepted]
|
||||
07:04:57.520 - INFO - 新连接建立: 2025badf-3414-48c6-8382-76c51673d9ef
|
||||
07:04:57.520 - INFO - 已经启动 start tts task {audio_stream_id}
|
||||
07:04:57.520 - INFO - ---begin--init QwenTTS-- mp3 48000 cosyvoice-v1/longyuan@Tongyi-Qianwen cosyvoice-v1/longyuan
|
||||
07:04:57.520 - INFO - QwenTTS--get_audio_format-- mp3 48000
|
||||
07:04:57.520 - INFO - setup_tts longyuan MP3 with 48000Hz sample rate, mono channel, 256kbps
|
||||
INFO: connection open
|
||||
07:04:57.639 - INFO - Websocket connected
|
||||
07:04:57.768 - INFO - Qwen CosyVoice tts open
|
||||
07:05:01.717 - INFO - --data_handler on_complete
|
||||
07:05:01.717 - INFO - Qwen CosyVoice tts close
|
||||
07:05:01.717 - INFO - --tts task event set error = None
|
||||
INFO: connection closed
|
||||
07:06:17.189 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 43.140.60.44:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
07:06:17.383 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 43.140.60.33:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
07:06:20.644 - INFO - Creating TTS request: {'text': '元大都水利建设最终形成了金水河、高梁河两进,坝河、通惠河两出,瓮山泊、积水潭两大蓄水水面格局,水利景观呈现“一心、一廊”的发展特征。城内供水区以积水潭为核心,通惠河漕运走廊连接北运河与白浮泉,串联起自然山水、寺庙、集市、私园、公共桥闸等景观,充分体现了城市、水利、景观三者之间的相互作用。元代水利建设对北京城市水利景观和生态环境具有深远的影响。', 'session_id': '0b4cdbaeaf9111efa53df171065841e8', 'delay_gen_audio': True, 'tts_sample_rate': 48000, 'tts_stream_format': 'mp3', 'model_name': 'cosyvoice-v1/longyuan@Tongyi-Qianwen', 'sample_rate': 48000, 'stream_format': 'mp3'}
|
||||
INFO: 43.140.60.33:0 - "POST /tts/chats/9cb04ecead5111ef99e80242ac120006/tts?device_id=17513727656058688719 HTTP/1.1" 200 OK
|
||||
INFO: ('1.13.185.116', 47246) - "WebSocket /tts/chats/9cb04ecead5111ef99e80242ac120006/tts/7d2bd2dd-dfc0-43e6-9b23-08e5251bb954" [accepted]
|
||||
07:06:21.077 - INFO - 新连接建立: caa0458b-7662-4ebe-9a6b-480c57c400b6
|
||||
07:06:21.077 - INFO - 已经启动 start tts task {audio_stream_id}
|
||||
07:06:21.077 - INFO - ---begin--init QwenTTS-- mp3 48000 cosyvoice-v1/longyuan@Tongyi-Qianwen cosyvoice-v1/longyuan
|
||||
07:06:21.078 - INFO - QwenTTS--get_audio_format-- mp3 48000
|
||||
07:06:21.078 - INFO - setup_tts longyuan MP3 with 48000Hz sample rate, mono channel, 256kbps
|
||||
INFO: connection open
|
||||
07:06:21.194 - INFO - Websocket connected
|
||||
07:06:21.324 - INFO - Qwen CosyVoice tts open
|
||||
07:06:32.422 - INFO - --data_handler on_complete
|
||||
07:06:32.422 - INFO - Qwen CosyVoice tts close
|
||||
07:06:32.422 - INFO - --tts task event set error = None
|
||||
INFO: connection closed
|
||||
07:44:06.202 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
07:44:06.290 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
07:44:52.287 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
07:44:52.440 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
07:45:23.056 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
07:45:23.159 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
07:54:21.106 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
07:54:21.161 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
07:54:28.720 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
07:54:28.799 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
07:54:35.913 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
07:54:36.001 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
07:54:36.411 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
07:54:36.509 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
07:55:22.522 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
07:55:22.582 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
07:56:58.308 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
07:56:58.385 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
08:07:38.414 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
08:07:38.499 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
08:10:57.429 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
08:10:57.486 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
08:11:53.340 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
08:11:53.398 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
08:16:33.756 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
08:16:33.813 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
08:17:30.384 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
08:17:30.490 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
08:18:33.644 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
08:18:33.709 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
08:19:50.951 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
08:19:51.034 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
08:21:37.950 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
08:21:38.023 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
08:22:05.386 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
08:22:05.441 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
08:23:13.075 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
08:23:13.153 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
08:24:49.462 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
08:24:49.563 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
08:26:08.181 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
08:26:08.282 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
08:26:49.301 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
08:26:49.374 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
08:27:41.833 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
08:27:41.893 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
08:28:50.023 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
08:28:50.083 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
08:29:21.179 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
08:29:21.387 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
08:30:19.839 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
08:30:20.031 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
08:31:11.560 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
08:31:11.723 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
08:33:16.896 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
08:33:17.108 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
08:33:51.413 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
08:33:51.479 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
08:35:10.447 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
08:35:10.505 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
08:36:24.091 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
08:36:24.187 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
08:37:18.392 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
08:37:18.507 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
08:38:42.906 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 106.55.206.109:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
08:38:43.148 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 43.140.60.33:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
08:49:31.793 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 106.55.206.109:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
08:49:31.991 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 43.140.60.33:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
08:51:30.837 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
08:51:30.938 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
08:55:28.363 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
08:55:28.421 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
08:56:53.353 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
08:56:53.419 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
09:00:01.531 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
09:00:01.590 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
09:00:07.397 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
09:00:07.486 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
09:00:47.232 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
09:00:47.306 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
09:01:19.694 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
09:01:19.959 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
09:02:46.650 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
09:02:46.718 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
09:03:29.115 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
09:03:29.384 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
09:05:12.089 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
09:05:12.145 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
09:10:24.333 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
09:10:24.586 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
09:11:14.693 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
09:11:14.781 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
09:11:45.666 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
09:11:45.755 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
09:12:29.573 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
09:12:29.813 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
10:36:24.208 - INFO - verify_token user={'user_id': '689cac0d-062e-45df-88bf-d7c4b16ff226', 'openid': 'obKSz7bHxzDFWnLHmOrnY_-8D6fI', 'phone': '13810887276', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2ODljYWMwZC0wNjJlLTQ1ZGYtODhiZi1kN2M0YjE2ZmYyMjYiLCJleHAiOjE3NTIwMzM3NzV9.Go3vld8ijajTsYSwzA45YS47O9thXdnLtrF0G7x1BAM', 'balance': 0, 'status': 1, 'last_login_time': 1751428975, 'create_time': 1748951630, 'create_date': datetime.datetime(2025, 6, 3, 19, 53, 50), 'update_time': 1751428975, 'update_date': datetime.datetime(2025, 7, 2, 12, 2, 55)}
|
||||
INFO: 223.104.41.17:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
10:36:24.285 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 223.104.41.17:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
10:36:34.664 - INFO - verify_token user={'user_id': '689cac0d-062e-45df-88bf-d7c4b16ff226', 'openid': 'obKSz7bHxzDFWnLHmOrnY_-8D6fI', 'phone': '13810887276', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2ODljYWMwZC0wNjJlLTQ1ZGYtODhiZi1kN2M0YjE2ZmYyMjYiLCJleHAiOjE3NTIwMzM3NzV9.Go3vld8ijajTsYSwzA45YS47O9thXdnLtrF0G7x1BAM', 'balance': 0, 'status': 1, 'last_login_time': 1751428975, 'create_time': 1748951630, 'create_date': datetime.datetime(2025, 6, 3, 19, 53, 50), 'update_time': 1751428975, 'update_date': datetime.datetime(2025, 7, 2, 12, 2, 55)}
|
||||
INFO: 223.104.41.17:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
10:36:34.746 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 223.104.41.17:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
10:36:38.066 - INFO - Creating TTS request: {'text': '铜条形驭马器,商,长18.3厘米,宽1.4厘米,高2.2厘米,2021年邵家棚M109出土,安阳市文物考古研究院藏。\n', 'session_id': '0b4cdbaeaf9111efa53df171065841e8', 'delay_gen_audio': True, 'tts_sample_rate': 48000, 'tts_stream_format': 'mp3', 'model_name': 'cosyvoice-v1/longyuan@Tongyi-Qianwen', 'sample_rate': 48000, 'stream_format': 'mp3'}
|
||||
INFO: 223.104.41.17:0 - "POST /tts/chats/39e9a2ba5a4711f0865bbb55c66f9471/tts?device_id=17507669394291632844 HTTP/1.1" 200 OK
|
||||
INFO: ('1.13.185.116', 36130) - "WebSocket /tts/chats/39e9a2ba5a4711f0865bbb55c66f9471/tts/de035ae4-81d8-408b-b551-2eac17b07e50" [accepted]
|
||||
10:36:38.312 - INFO - 新连接建立: 733148f7-d2ac-4fa2-ad3a-b41fb684d08e
|
||||
10:36:38.312 - INFO - 已经启动 start tts task {audio_stream_id}
|
||||
INFO: connection open
|
||||
10:36:38.313 - INFO - ---begin--init QwenTTS-- mp3 48000 cosyvoice-v1/longyuan@Tongyi-Qianwen cosyvoice-v1/longyuan
|
||||
10:36:38.313 - INFO - QwenTTS--get_audio_format-- mp3 48000
|
||||
10:36:38.313 - INFO - setup_tts longyuan MP3 with 48000Hz sample rate, mono channel, 256kbps
|
||||
10:36:38.425 - INFO - Websocket connected
|
||||
10:36:38.560 - INFO - Qwen CosyVoice tts open
|
||||
10:36:42.366 - INFO - --data_handler on_complete
|
||||
10:36:42.366 - INFO - Qwen CosyVoice tts close
|
||||
10:36:42.366 - INFO - --tts task event set error = None
|
||||
INFO: connection closed
|
||||
10:36:49.363 - INFO - verify_token user={'user_id': '689cac0d-062e-45df-88bf-d7c4b16ff226', 'openid': 'obKSz7bHxzDFWnLHmOrnY_-8D6fI', 'phone': '13810887276', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2ODljYWMwZC0wNjJlLTQ1ZGYtODhiZi1kN2M0YjE2ZmYyMjYiLCJleHAiOjE3NTIwMzM3NzV9.Go3vld8ijajTsYSwzA45YS47O9thXdnLtrF0G7x1BAM', 'balance': 0, 'status': 1, 'last_login_time': 1751428975, 'create_time': 1748951630, 'create_date': datetime.datetime(2025, 6, 3, 19, 53, 50), 'update_time': 1751428975, 'update_date': datetime.datetime(2025, 7, 2, 12, 2, 55)}
|
||||
INFO: 223.104.41.17:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
10:36:49.440 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 223.104.41.17:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
10:36:53.851 - INFO - Creating TTS request: {'text': '铜铙,商,①高18厘米,口长13.2厘米,口宽10.1厘米;②高13厘米,口长11.6厘米,口宽8.7厘米;③高11.9厘米,口长9.4厘米,口宽7厘米;1983年戚家庄东地出土,安阳市文物考古研究院藏。\n', 'session_id': '0b4cdbaeaf9111efa53df171065841e8', 'delay_gen_audio': True, 'tts_sample_rate': 48000, 'tts_stream_format': 'mp3', 'model_name': 'cosyvoice-v1/longyuan@Tongyi-Qianwen', 'sample_rate': 48000, 'stream_format': 'mp3'}
|
||||
INFO: 223.104.41.17:0 - "POST /tts/chats/39e9a2ba5a4711f0865bbb55c66f9471/tts?device_id=17507669394291632844 HTTP/1.1" 200 OK
|
||||
INFO: ('1.13.185.116', 49668) - "WebSocket /tts/chats/39e9a2ba5a4711f0865bbb55c66f9471/tts/c6355d58-9d94-4726-bf00-0581bcdb0e28" [accepted]
|
||||
10:36:54.094 - INFO - 新连接建立: fc397484-625d-4db9-9fba-6d5a8949a57a
|
||||
10:36:54.094 - INFO - 已经启动 start tts task {audio_stream_id}
|
||||
10:36:54.094 - INFO - ---begin--init QwenTTS-- mp3 48000 cosyvoice-v1/longyuan@Tongyi-Qianwen cosyvoice-v1/longyuan
|
||||
10:36:54.094 - INFO - QwenTTS--get_audio_format-- mp3 48000
|
||||
10:36:54.094 - INFO - setup_tts longyuan MP3 with 48000Hz sample rate, mono channel, 256kbps
|
||||
INFO: connection open
|
||||
10:36:54.202 - INFO - Websocket connected
|
||||
10:36:54.341 - INFO - Qwen CosyVoice tts open
|
||||
10:37:05.913 - INFO - --data_handler on_complete
|
||||
10:37:05.914 - INFO - Qwen CosyVoice tts close
|
||||
10:37:05.914 - INFO - --tts task event set error = None
|
||||
INFO: connection closed
|
||||
INFO: ('1.13.185.116', 59460) - "WebSocket /tts/chats/39e9a2ba5a4711f0865bbb55c66f9471/tts/9d5e77cc-ad9b-4a60-812f-880d2f182543" [accepted]
|
||||
10:37:23.067 - INFO - 新连接建立: d3f6a319-1597-4283-8330-a26c2582c91c
|
||||
INFO: connection open
|
||||
10:37:23.121 - INFO - 代理文本流: completions_url=http://localhost:9380/api/v1/chats/39e9a2ba5a4711f0865bbb55c66f9471/completions {'question': '请介绍铜铙', 'stream': True, 'tts_model': 'cosyvoice-v1/longyuan@Tongyi-Qianwen', 'tts_sample_rate': 8000, 'tts_stream_format': 'mp3', 'tts_disable': True}
|
||||
10:37:23.121 - INFO - ---begin--init QwenTTS-- mp3 8000 cosyvoice-v1/longyuan@Tongyi-Qianwen cosyvoice-v1/longyuan
|
||||
10:37:23.121 - INFO - QwenTTS--get_audio_format-- mp3 8000
|
||||
10:37:23.121 - INFO - setup_tts longyuan MP3 with 8000Hz sample rate, mono channel, 128kbps
|
||||
10:37:26.511 - INFO - HTTP Request: POST http://localhost:9380/api/v1/chats/39e9a2ba5a4711f0865bbb55c66f9471/completions "HTTP/1.1 200 OK"
|
||||
10:37:26.511 - INFO - 响应状态: HTTP 200
|
||||
10:37:26.511 - INFO - 开始处理SSE流
|
||||
10:37:26.651 - INFO - Websocket connected
|
||||
10:37:26.775 - INFO - Qwen CosyVoice tts open
|
||||
INFO: ('1.13.185.116', 49122) - "WebSocket /tts/chats/39e9a2ba5a4711f0865bbb55c66f9471/tts/64880966-3b94-4fae-ac7e-e37e16768c2a" [accepted]
|
||||
10:37:26.927 - INFO - 新连接建立: f666fc5e-48bd-4451-ac13-65c656784d3f
|
||||
INFO: connection open
|
||||
10:37:39.969 - INFO - SSE流处理完成,事件数: 23
|
||||
INFO: connection closed
|
||||
INFO: connection closed
|
||||
10:37:45.801 - INFO - 发送时检测到断开连接: f666fc5e-48bd-4451-ac13-65c656784d3f,
|
||||
10:38:00.989 - ERROR - error from callback <bound method SpeechSynthesizer.on_message of <dashscope.audio.tts_v2.speech_synthesizer.SpeechSynthesizer object at 0x7f25f18a86a0>>: {"header":{"task_id":"8ed5859fd51746068babf1776c7c84df","event":"task-failed","error_code":"InvalidParameter","error_message":"request timeout after 23 seconds.","attributes":{}},"payload":{}}
|
||||
10:38:00.989 - ERROR - error from callback <bound method SpeechSynthesizer.on_error of <dashscope.audio.tts_v2.speech_synthesizer.SpeechSynthesizer object at 0x7f25f18a86a0>>: websocket closed due to websocket closed due to {"header":{"task_id":"8ed5859fd51746068babf1776c7c84df","event":"task-failed","error_code":"InvalidParameter","error_message":"request timeout after 23 seconds.","attributes":{}},"payload":{}}
|
||||
10:38:00.989 - INFO - tearing down on exception websocket closed due to websocket closed due to websocket closed due to {"header":{"task_id":"8ed5859fd51746068babf1776c7c84df","event":"task-failed","error_code":"InvalidParameter","error_message":"request timeout after 23 seconds.","attributes":{}},"payload":{}}
|
||||
10:38:00.989 - ERROR - close status: 1007
|
||||
Qwen tts error {"header":{"task_id":"8ed5859fd51746068babf1776c7c84df","event":"task-failed","error_code":"InvalidParameter","error_message":"request timeout after 23 seconds.","attributes":{}},"payload":{}}
|
||||
websocket closed due to {"header":{"task_id":"8ed5859fd51746068babf1776c7c84df","event":"task-failed","error_code":"InvalidParameter","error_message":"request timeout after 23 seconds.","attributes":{}},"payload":{}}
|
||||
websocket closed due to websocket closed due to {"header":{"task_id":"8ed5859fd51746068babf1776c7c84df","event":"task-failed","error_code":"InvalidParameter","error_message":"request timeout after 23 seconds.","attributes":{}},"payload":{}}
|
||||
websocket closed due to websocket closed due to websocket closed due to {"header":{"task_id":"8ed5859fd51746068babf1776c7c84df","event":"task-failed","error_code":"InvalidParameter","error_message":"request timeout after 23 seconds.","attributes":{}},"payload":{}}
|
||||
INFO: 183.163.60.214:0 - "GET /auth/get_museum_list HTTP/1.1" 401 Unauthorized
|
||||
Exception in thread Thread-1544 (_process_tasks):
|
||||
Traceback (most recent call last):
|
||||
File "/usr/lib/python3.10/threading.py", line 1016, in _bootstrap_inner
|
||||
self.run()
|
||||
File "/usr/lib/python3.10/threading.py", line 953, in run
|
||||
self._target(*self._args, **self._kwargs)
|
||||
File "/home/ubuntu/ragflow/asr-monitor-test/app/tts_service.py", line 192, in _process_tasks
|
||||
session['tts_model'].end_streaming_call()
|
||||
File "/home/ubuntu/ragflow/asr-monitor-test/app/tts_service.py", line 1005, in end_streaming_call
|
||||
self.synthesizer.streaming_complete()
|
||||
File "/home/ubuntu/ragflow/asr-monitor/venv/lib/python3.10/site-packages/dashscope/audio/tts_v2/speech_synthesizer.py", line 374, in streaming_complete
|
||||
self.__send_str(request)
|
||||
File "/home/ubuntu/ragflow/asr-monitor/venv/lib/python3.10/site-packages/dashscope/audio/tts_v2/speech_synthesizer.py", line 285, in __send_str
|
||||
self.ws.send(data)
|
||||
File "/home/ubuntu/ragflow/asr-monitor/venv/lib/python3.10/site-packages/websocket/_app.py", line 291, in send
|
||||
raise WebSocketConnectionClosedException("Connection is already closed.")
|
||||
websocket._exceptions.WebSocketConnectionClosedException: Connection is already closed.
|
||||
INFO: 183.163.60.214:0 - "GET /auth/get_museum_list HTTP/1.1" 401 Unauthorized
|
||||
INFO: 123.115.202.182:0 - "GET /auth/get_museum_list HTTP/1.1" 401 Unauthorized
|
||||
11:23:13.037 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
11:23:13.104 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
11:25:03.125 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
11:25:03.187 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
11:26:37.995 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
11:26:38.077 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
11:27:45.347 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
11:27:45.695 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
11:28:25.996 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 61.141.77.65:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
11:28:26.062 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 61.141.77.65:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
11:29:40.340 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
11:29:40.639 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
11:30:15.537 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 61.141.77.65:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
11:30:15.603 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 61.141.77.65:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
11:30:52.210 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 61.141.77.65:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
11:30:52.288 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 61.141.77.65:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
11:35:02.399 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
11:35:02.737 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
11:36:02.938 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
11:36:03.034 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
11:37:17.719 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
11:37:17.802 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
11:37:47.273 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 61.141.77.65:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
11:37:47.367 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 61.141.77.65:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
11:39:13.999 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
11:39:14.337 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
11:41:51.134 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
11:41:51.495 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
11:43:01.977 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 163.125.202.178:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
11:43:02.050 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 163.125.202.178:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
11:44:30.162 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 43.144.107.210:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
11:44:30.345 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 43.140.60.44:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
11:45:40.101 - INFO - verify_token user={'user_id': '76538cf0-a6cf-4aa8-8440-382dd2330384', 'openid': 'obKSz7V6a-avAF-vtQrnk_rnuSGE', 'phone': '18676776176', 'email': None, 'token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3NjUzOGNmMC1hNmNmLTRhYTgtODQ0MC0zODJkZDIzMzAzODQiLCJleHAiOjE3NTI1ODI1ODN9.GONQPAzcWnYQN2i14zfNhjU8OT1to7fWn6ZA6lNdSHY', 'balance': 0, 'status': 1, 'last_login_time': 1751977783, 'create_time': 1748960538, 'create_date': datetime.datetime(2025, 6, 3, 22, 22, 18), 'update_time': 1751977783, 'update_date': datetime.datetime(2025, 7, 8, 20, 29, 43)}
|
||||
INFO: 43.144.107.210:0 - "GET /auth/verify HTTP/1.1" 200 OK
|
||||
11:45:40.260 - INFO - get_museum_id_auth=[1, 2, 3]
|
||||
INFO: 43.140.60.44:0 - "GET /auth/get_museum_id_auth HTTP/1.1" 200 OK
|
||||
|
||||
@@ -5,6 +5,7 @@ from contextlib import contextmanager
|
||||
from config import DATABASE_CONFIG
|
||||
from datetime import datetime,timedelta
|
||||
import logging
|
||||
from zoneinfo import ZoneInfo # Python 3.9+ 内置
|
||||
from typing import Union, List, Dict, Optional
|
||||
from tenacity import retry, stop_after_attempt, wait_fixed, retry_if_exception_type
|
||||
from dateutil.relativedelta import relativedelta
|
||||
@@ -415,6 +416,21 @@ def get_users(status: int = None, email: str = None, phone: str = None,openid: s
|
||||
|
||||
# 按用户ID获取用户
|
||||
def get_user_by_id(user_id: str):
|
||||
"""
|
||||
根据用户ID获取用户信息
|
||||
|
||||
功能说明:
|
||||
- 通过用户ID查询用户基本信息
|
||||
|
||||
参数说明:
|
||||
- user_id: 用户ID
|
||||
|
||||
返回:
|
||||
- 用户信息的字典,如果不存在则返回None
|
||||
|
||||
重要逻辑:
|
||||
- 直接查询用户表的所有字段
|
||||
"""
|
||||
sql = "SELECT * FROM rag_flow.users_info WHERE user_id = %s"
|
||||
result = execute_query(sql, (user_id,))
|
||||
return result[0] if result else None
|
||||
@@ -720,7 +736,7 @@ def update_order(order_id: str, update_data: dict) -> int:
|
||||
|
||||
from typing import Union, List, Dict, Optional
|
||||
|
||||
def get_order_by_id(order_id: str = None, user_id: str = None,combined = None) -> Union[Dict, List[Dict], None]:
|
||||
def get_order_by_id(order_id: str = None, user_id: str = None,combined:bool = False,museum_id:int = None) -> Union[Dict, List[Dict], None]:
|
||||
"""
|
||||
根据订单ID或用户ID查询订单信息
|
||||
|
||||
@@ -742,9 +758,25 @@ def get_order_by_id(order_id: str = None, user_id: str = None,combined = None) -
|
||||
- 使用参数化查询防止 SQL 注入
|
||||
- 当同时传入 order_id 和 user_id 时,优先使用 order_id
|
||||
"""
|
||||
if not order_id and not user_id:
|
||||
return None # 两个参数都未传入,直接返回 None
|
||||
sql_wo_condition= """
|
||||
# 无任何参数时返回 None
|
||||
if not any([order_id, user_id, museum_id]):
|
||||
return None
|
||||
# ========== 简单查询模式 ==========
|
||||
if not combined:
|
||||
# 优先使用 order_id 查询
|
||||
if order_id:
|
||||
sql = "SELECT * FROM subscription_orders WHERE order_id = %s"
|
||||
result = execute_query(sql, (order_id,))
|
||||
return result[0] if result and len(result) > 0 else None
|
||||
|
||||
# 使用 user_id 查询
|
||||
if user_id:
|
||||
sql = "SELECT * FROM subscription_orders WHERE user_id = %s"
|
||||
result = execute_query(sql, (user_id,))
|
||||
return result if result else []
|
||||
|
||||
# ========== 复杂查询模式 ==========
|
||||
base_sql= """
|
||||
SELECT
|
||||
o.order_id,
|
||||
o.user_id,
|
||||
@@ -774,25 +806,39 @@ def get_order_by_id(order_id: str = None, user_id: str = None,combined = None) -
|
||||
LEFT JOIN rag_flow.user_subscriptions us ON o.order_id = us.order_id
|
||||
LEFT JOIN rag_flow.mesum_overview mo ON ms.museum_id = mo.id
|
||||
"""
|
||||
# 优先使用 order_id 查询
|
||||
if order_id and not combined:
|
||||
sql = "SELECT * FROM subscription_orders WHERE order_id = %s"
|
||||
result = execute_query(sql, (order_id,))
|
||||
return result[0] if result and len(result) > 0 else None # 返回单个订单
|
||||
# 构建查询条件和参数
|
||||
conditions = []
|
||||
params = []
|
||||
|
||||
# 如果 order_id 不存在,使用 user_id 查询
|
||||
if user_id and not combined:
|
||||
sql = "SELECT * FROM subscription_orders WHERE user_id = %s"
|
||||
result = execute_query(sql, (user_id,))
|
||||
return result if result else [] # 返回所有订单(列表)
|
||||
if user_id and combined:
|
||||
sql = sql_wo_condition + f"\n WHERE o.user_id = %s"
|
||||
result = execute_query(sql, (user_id,))
|
||||
return result if result else [] # 返回所有订单(列表)
|
||||
if order_id and combined:
|
||||
sql = sql_wo_condition + f"\n WHERE o.order_id = %s"
|
||||
result = execute_query(sql, (order_id,))
|
||||
return result[0] if result and len(result) > 0 else None # 返回单个订单
|
||||
# 添加条件(按优先级)
|
||||
if order_id:
|
||||
conditions.append("o.order_id = %s")
|
||||
params.append(order_id)
|
||||
elif user_id:
|
||||
conditions.append("o.user_id = %s")
|
||||
params.append(user_id)
|
||||
|
||||
# 新增博物馆ID条件(可与其他条件组合)
|
||||
if museum_id:
|
||||
conditions.append("ms.museum_id = %s")
|
||||
params.append(museum_id)
|
||||
|
||||
# 构建完整SQL
|
||||
if conditions:
|
||||
where_clause = " WHERE " + " AND ".join(conditions)
|
||||
sql = base_sql + where_clause
|
||||
else:
|
||||
sql = base_sql
|
||||
|
||||
# 执行查询
|
||||
result = execute_query(sql, tuple(params))
|
||||
|
||||
# 处理返回结果
|
||||
if not result:
|
||||
return [] if user_id or museum_id else None
|
||||
|
||||
# 当有order_id时返回单个对象,否则返回列表
|
||||
return result[0] if order_id and not museum_id else result
|
||||
|
||||
def create_user_subscription(data: dict) -> int:
|
||||
"""
|
||||
@@ -875,27 +921,6 @@ def deactivate_previous_subscriptions(user_id: str, museum_subscription_id: str)
|
||||
return execute_query(sql, (user_id, museum_subscription_id), autocommit=True)
|
||||
|
||||
|
||||
def get_user_by_id(user_id: str) -> dict:
|
||||
"""
|
||||
根据用户ID获取用户信息
|
||||
|
||||
功能说明:
|
||||
- 通过用户ID查询用户基本信息
|
||||
|
||||
参数说明:
|
||||
- user_id: 用户ID
|
||||
|
||||
返回:
|
||||
- 用户信息的字典,如果不存在则返回None
|
||||
|
||||
重要逻辑:
|
||||
- 直接查询用户表的所有字段
|
||||
"""
|
||||
sql = "SELECT * FROM users_info WHERE user_id = %s"
|
||||
result = execute_query(sql, (user_id,))
|
||||
return result[0] if result else None
|
||||
|
||||
|
||||
def get_subscription_template_by_id(template_id: int) -> dict:
|
||||
"""
|
||||
根据模板ID获取订阅模板信息
|
||||
@@ -1175,6 +1200,75 @@ def check_user_subscription(user_id: str, museum_id: int) -> dict:
|
||||
return None
|
||||
|
||||
|
||||
def is_museum_free_period(museum_id: int) -> bool:
|
||||
"""
|
||||
检查博物馆当前是否处于免费时段
|
||||
|
||||
参数:
|
||||
- museum_id: 博物馆ID
|
||||
|
||||
返回:
|
||||
- True: 当前是免费时段
|
||||
- False: 当前不是免费时段
|
||||
"""
|
||||
# 查询博物馆的免费时段配置
|
||||
sql = """
|
||||
SELECT t.validity_type, t.valid_time_range, t.valid_week_days
|
||||
FROM museum_subscriptions ms
|
||||
JOIN subscription_templates t ON ms.template_id = t.id
|
||||
WHERE ms.museum_id = %s
|
||||
AND t.validity_type = 'free_interval'
|
||||
AND t.is_active = 1
|
||||
AND ms.is_active = 1
|
||||
LIMIT 1
|
||||
"""
|
||||
result = execute_query(sql, (museum_id,))
|
||||
if not result:
|
||||
return False
|
||||
|
||||
subscription = result[0]
|
||||
return is_subscription_valid(subscription)
|
||||
|
||||
|
||||
def get_user_valid_subscription(user_id: str, museum_id: int) -> bool:
|
||||
"""
|
||||
检查用户是否有有效的博物馆订阅
|
||||
|
||||
参数:
|
||||
- user_id: 用户ID
|
||||
- museum_id: 博物馆ID
|
||||
|
||||
返回:
|
||||
- True: 用户有有效订阅
|
||||
- False: 用户无有效订阅
|
||||
"""
|
||||
# 查询用户的有效订阅
|
||||
sql = """
|
||||
SELECT
|
||||
t.validity_type,
|
||||
t.valid_time_range,
|
||||
t.valid_week_days,
|
||||
us.start_date,
|
||||
us.end_date
|
||||
FROM user_subscriptions us
|
||||
JOIN museum_subscriptions ms ON us.museum_subscription_id = ms.sub_id
|
||||
JOIN subscription_templates t ON ms.template_id = t.id
|
||||
WHERE us.user_id = %s
|
||||
AND ms.museum_id = %s
|
||||
AND us.is_active = 1
|
||||
AND ms.is_active = 1
|
||||
AND t.is_active = 1
|
||||
AND us.start_date <= NOW()
|
||||
AND us.end_date >= NOW()
|
||||
"""
|
||||
subscriptions = execute_query(sql, (user_id, museum_id))
|
||||
|
||||
# 检查每个订阅是否在当前时间有效
|
||||
for sub in subscriptions:
|
||||
if is_subscription_valid(sub):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def calculate_subscription_expiry(start_date: datetime, validity_type: str) -> datetime:
|
||||
"""
|
||||
@@ -1203,3 +1297,64 @@ def calculate_subscription_expiry(start_date: datetime, validity_type: str) -> d
|
||||
# 未知类型默认30天
|
||||
logger.warning(f"未知有效期类型: {validity_type}, 使用默认30天")
|
||||
return start_date + timedelta(days=30)
|
||||
|
||||
|
||||
def is_subscription_valid(subscription: dict) -> bool:
|
||||
"""
|
||||
检查订阅在当前时间是否有效
|
||||
|
||||
参数:
|
||||
subscription: 包含订阅信息的字典,包含以下字段:
|
||||
- validity_type: 有效期类型
|
||||
- valid_time_range: 有效时间段 (格式: "08:00-20:00")
|
||||
- valid_week_days: 有效星期 (格式: "1,3,5")
|
||||
- start_date: 订阅开始日期 (datetime 对象)
|
||||
- end_date: 订阅结束日期 (datetime 对象)
|
||||
"""
|
||||
# 设置时区(根据服务器实际时区调整)
|
||||
tz = ZoneInfo('Asia/Shanghai')
|
||||
now = datetime.now(tz)
|
||||
|
||||
# 1. 检查永久免费订阅
|
||||
if subscription['validity_type'] == 'free':
|
||||
return True
|
||||
|
||||
# 2. 检查时间间隔类型订阅
|
||||
if subscription['validity_type'] == 'free_interval':
|
||||
# 时间间隔类型不需要检查有效期范围
|
||||
pass
|
||||
else:
|
||||
# 3. 检查有效期是否在范围内
|
||||
if subscription['validity_type'] in ['1month', '1year', 'permanent']:
|
||||
start_date = subscription['start_date'].astimezone(tz)
|
||||
end_date = subscription['end_date'].astimezone(tz)
|
||||
|
||||
if not (start_date <= now <= end_date):
|
||||
return False
|
||||
|
||||
# 4. 检查星期限制
|
||||
if subscription.get('valid_week_days'):
|
||||
week_day = now.isoweekday() # 1=周一, 7=周日
|
||||
valid_days = [int(d) for d in str(subscription['valid_week_days']).split(',')]
|
||||
if week_day not in valid_days:
|
||||
return False
|
||||
|
||||
# 5. 检查时间范围限制
|
||||
if subscription.get('valid_time_range'):
|
||||
try:
|
||||
start_str, end_str = subscription['valid_time_range'].split('-')
|
||||
start_time = datetime.strptime(start_str, '%H:%M').time()
|
||||
end_time = datetime.strptime(end_str, '%H:%M').time()
|
||||
current_time = now.time()
|
||||
# 处理跨夜时段
|
||||
if end_time < start_time:
|
||||
if not (current_time >= start_time or current_time <= end_time):
|
||||
return False
|
||||
else:
|
||||
if not (start_time <= current_time <= end_time):
|
||||
return False
|
||||
except (ValueError, AttributeError):
|
||||
# 时间格式无效,跳过时间检查
|
||||
pass
|
||||
|
||||
return True
|
||||
@@ -468,12 +468,14 @@ async def get_museum_subscriptions_by_museum_id(
|
||||
result = get_museum_subscriptions_by_museum(museum_id)
|
||||
return CustomJSONResponse(result)
|
||||
|
||||
@payment_router.get("/get_order_list")
|
||||
@payment_router.post("/get_order_list")
|
||||
async def get_order_list(
|
||||
request: Request,
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
result = get_order_by_id(user_id = current_user["user_id"],combined=True)
|
||||
data = await request.json()
|
||||
museum_id = data.get("museum_id")
|
||||
result = get_order_by_id(user_id = current_user["user_id"],combined=True,museum_id=museum_id)
|
||||
return CustomJSONResponse({
|
||||
"code": 0,
|
||||
"msg": "success",
|
||||
@@ -490,6 +492,35 @@ async def get_order_detial(
|
||||
"code": 0,
|
||||
"msg": "success",
|
||||
"data": result})
|
||||
|
||||
@payment_router.post("/get_user_museum_subscriptions")
|
||||
async def get_user_museum_subscriptions(
|
||||
request: Request,
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
data = await request.json()
|
||||
museum_id = data.get("museum_id")
|
||||
user_id = current_user["user_id"] # 用户id
|
||||
is_free = False
|
||||
museum_info = get_museum_by_id(museum_id=museum_id)
|
||||
if museum_info and museum_info['free']:
|
||||
is_free = True
|
||||
is_free_period = is_museum_free_period(museum_id)
|
||||
is_subscription_valid = get_user_valid_subscription(user_id, museum_id)
|
||||
can_access = False
|
||||
can_access = is_free or is_free_period or is_subscription_valid
|
||||
result = {
|
||||
'can_access': can_access,
|
||||
'is_free': is_free,
|
||||
'is_free_period': is_free_period,
|
||||
'is_subscription_valid': is_subscription_valid
|
||||
}
|
||||
return CustomJSONResponse({
|
||||
"code": 0,
|
||||
"msg": "success",
|
||||
"data": result})
|
||||
|
||||
|
||||
# --- 支付工具函数 ---
|
||||
|
||||
async def generate_wx_prepay_params_v2(order_id: str, total_fee: int, openid: str, body: str):
|
||||
|
||||
@@ -14,6 +14,9 @@ from typing import Optional, Dict, Any
|
||||
import asyncio, httpx
|
||||
from collections import deque
|
||||
|
||||
import websockets
|
||||
import uuid
|
||||
|
||||
from fastapi import WebSocket, APIRouter, WebSocketDisconnect, Request, Body, Query
|
||||
from fastapi import FastAPI, UploadFile, File, Form, Header
|
||||
from fastapi.responses import StreamingResponse, JSONResponse, Response
|
||||
@@ -90,12 +93,23 @@ class StreamSessionManager:
|
||||
try:
|
||||
self.sessions[session_id]['last_active'] = time.time()
|
||||
self.sessions[session_id]['buffer'].put(data)
|
||||
self.sessions[session_id]['audio_chunk_size'] += len(data)
|
||||
#logging.info(f"StreamSessionManager on_data {len(data)} {self.sessions[session_id]['audio_chunk_size']}")
|
||||
except queue.Full:
|
||||
logging.warning(f"Audio buffer full for session {session_id}")
|
||||
|
||||
"""
|
||||
elif data is None: # 结束信号
|
||||
# 仅对非流式引擎触发完成事件
|
||||
if not streaming_call:
|
||||
logging.info(f"StreamSessionManager on_data sentence_complete_event set")
|
||||
self.sessions[session_id]['sentence_complete_event'].set()
|
||||
self.sessions[session_id]['current_processing'] = False
|
||||
"""
|
||||
# 创建完成事件
|
||||
completion_event = threading.Event()
|
||||
# 设置TTS流式传输
|
||||
tts_instance.setup_tts(on_data)
|
||||
|
||||
tts_instance.setup_tts(on_data,completion_event)
|
||||
# 创建会话
|
||||
self.sessions[session_id] = {
|
||||
'tts_model': tts_model,
|
||||
'buffer': queue.Queue(maxsize=300), # 线程安全队列
|
||||
@@ -103,6 +117,7 @@ class StreamSessionManager:
|
||||
'active': True,
|
||||
'last_active': time.time(),
|
||||
'audio_chunk_count': 0,
|
||||
'audio_chunk_size': 0,
|
||||
'finished': threading.Event(), # 添加事件对象
|
||||
'sample_rate': sample_rate,
|
||||
'stream_format': stream_format,
|
||||
@@ -110,7 +125,9 @@ class StreamSessionManager:
|
||||
"text_buffer": "", # 新增文本缓冲区
|
||||
"last_text_time": time.time(), # 最后文本到达时间
|
||||
"streaming_call": streaming_call,
|
||||
"tts_stream_started": False # 标记是否已启动流
|
||||
"tts_stream_started": False, # 标记是否已启动流
|
||||
"sentence_complete_event": completion_event, #threading.Event(),
|
||||
"current_processing": False # 标记是否正在处理句子
|
||||
}
|
||||
# 启动任务处理线程
|
||||
threading.Thread(target=self._process_tasks, args=(session_id,), daemon=True).start()
|
||||
@@ -129,7 +146,7 @@ class StreamSessionManager:
|
||||
except queue.Full:
|
||||
logging.warning(f"Session {session_id} task queue full")
|
||||
|
||||
def _process_tasks(self, session_id):
|
||||
def _process_tasks1(self, session_id):
|
||||
"""任务处理线程(每个会话独立)"""
|
||||
session = self.sessions.get(session_id)
|
||||
if not session or not session['active']:
|
||||
@@ -204,7 +221,138 @@ class StreamSessionManager:
|
||||
# 休眠避免CPU空转
|
||||
time.sleep(0.05) # 50ms检查间隔
|
||||
|
||||
def _generate_audio(self, session_id, text):
|
||||
def _process_tasks(self, session_id): # 20250718 新更新
|
||||
"""任务处理线程(每个会话独立)- 保留原有处理逻辑"""
|
||||
session = self.sessions.get(session_id)
|
||||
if not session or not session['active']:
|
||||
return
|
||||
|
||||
# 根据引擎类型选择处理函数
|
||||
if session.get('streaming_call'):
|
||||
gen_tts_audio_func = self._stream_audio
|
||||
else:
|
||||
gen_tts_audio_func = self._generate_audio
|
||||
|
||||
while session['active']:
|
||||
current_time = time.time()
|
||||
text_to_process = ""
|
||||
|
||||
# 1. 获取待处理文本
|
||||
with self.lock:
|
||||
if session['text_buffer']:
|
||||
text_to_process = session['text_buffer']
|
||||
|
||||
|
||||
# 2. 处理文本
|
||||
if text_to_process and not session['current_processing'] :
|
||||
session['text_buffer'] = ""
|
||||
# 分割完整句子
|
||||
complete_sentences, remaining_text = self._split_and_extract(text_to_process)
|
||||
|
||||
# 保存剩余文本
|
||||
if remaining_text:
|
||||
with self.lock:
|
||||
session['text_buffer'] = remaining_text + session['text_buffer']
|
||||
|
||||
# 合并并处理完整句子
|
||||
if complete_sentences:
|
||||
# 智能合并句子(最长300字符)
|
||||
buffer = []
|
||||
current_length = 0
|
||||
|
||||
# 处理每个句子
|
||||
for sentence in complete_sentences:
|
||||
sent_length = len(sentence)
|
||||
|
||||
# 添加到当前缓冲区
|
||||
if current_length + sent_length <= 300:
|
||||
buffer.append(sentence)
|
||||
current_length += sent_length
|
||||
else:
|
||||
# 处理已缓冲的文本
|
||||
if buffer:
|
||||
combined_text = "".join(buffer)
|
||||
|
||||
# 重置完成事件状态
|
||||
session['sentence_complete_event'].clear()
|
||||
session['current_processing'] = True
|
||||
|
||||
# 生成音频
|
||||
gen_tts_audio_func(session_id, combined_text)
|
||||
|
||||
# 等待完成
|
||||
if not session['sentence_complete_event'].wait(timeout=120.0):
|
||||
logging.warning(f"Timeout waiting for TTS completion: {combined_text}")
|
||||
# 重置处理状态
|
||||
time.sleep(5.0)
|
||||
session['current_processing'] = False
|
||||
logging.info(f"StreamSessionManager _process_tasks 转换结束!!!")
|
||||
# 重置缓冲区
|
||||
buffer = [sentence]
|
||||
current_length = sent_length
|
||||
|
||||
# 处理剩余的缓冲文本
|
||||
if buffer:
|
||||
combined_text = "".join(buffer)
|
||||
|
||||
# 重置完成事件状态
|
||||
session['sentence_complete_event'].clear()
|
||||
session['current_processing'] = True
|
||||
|
||||
# 生成音频
|
||||
gen_tts_audio_func(session_id, combined_text)
|
||||
|
||||
# 等待完成
|
||||
if not session['sentence_complete_event'].wait(timeout=120.0):
|
||||
logging.warning(f"Timeout waiting for TTS completion: {combined_text}")
|
||||
# 重置处理状态
|
||||
time.sleep(1.0)
|
||||
session['current_processing'] = False
|
||||
logging.info(f"StreamSessionManager _process_tasks 转换结束!!!")
|
||||
|
||||
# 3. 检查超时未处理的文本
|
||||
if current_time - session['last_text_time'] > self.sentence_timeout:
|
||||
with self.lock:
|
||||
if session['text_buffer']:
|
||||
# 直接处理剩余文本
|
||||
session['sentence_complete_event'].clear()
|
||||
session['current_processing'] = True
|
||||
gen_tts_audio_func(session_id, session['text_buffer'])
|
||||
session['text_buffer'] = ""
|
||||
|
||||
# 等待完成
|
||||
if not session['sentence_complete_event'].wait(timeout=120.0):
|
||||
logging.warning(f"Timeout waiting for TTS completion: {combined_text}")
|
||||
# 重置处理状态
|
||||
session['current_processing'] = False
|
||||
|
||||
# 4. 会话超时检查
|
||||
if current_time - session['last_active'] > self.gc_interval:
|
||||
# 处理剩余文本
|
||||
with self.lock:
|
||||
if session['text_buffer']:
|
||||
# 重置完成事件状态
|
||||
session['sentence_complete_event'].clear()
|
||||
session['current_processing'] = True
|
||||
|
||||
# 处理最后一段文本
|
||||
gen_tts_audio_func(session_id, session['text_buffer'])
|
||||
session['text_buffer'] = ""
|
||||
|
||||
# 等待完成
|
||||
if not session['sentence_complete_event'].wait(timeout=120.0):
|
||||
logging.warning(f"Timeout waiting for TTS completion: {combined_text}")
|
||||
# 重置处理状态
|
||||
session['current_processing'] = False
|
||||
|
||||
# 关闭会话
|
||||
self.close_session(session_id)
|
||||
break
|
||||
|
||||
# 5. 休眠避免CPU空转
|
||||
time.sleep(0.05) # 50ms检查间隔
|
||||
|
||||
def _generate_audio1(self, session_id, text):
|
||||
"""实际生成音频(线程池执行)"""
|
||||
session = self.sessions.get(session_id)
|
||||
if not session: return
|
||||
@@ -236,6 +384,26 @@ class StreamSessionManager:
|
||||
except Exception as e:
|
||||
session['buffer'].put(f"ERROR:{str(e)}")
|
||||
|
||||
def _generate_audio(self, session_id, text): # 20250718 新更新
|
||||
"""实际生成音频(顺序执行)- 用于非流式引擎"""
|
||||
session = self.sessions.get(session_id)
|
||||
if not session:
|
||||
return
|
||||
|
||||
try:
|
||||
logging.info(f"StreamSessionManager _generate_audio--0 {text}")
|
||||
# 调用 TTS
|
||||
session['tts_model'].text_tts_call(text)
|
||||
session['last_active'] = time.time()
|
||||
session['audio_chunk_count'] += 1
|
||||
|
||||
if not session['tts_chunk_data_valid']:
|
||||
session['tts_chunk_data_valid'] = True
|
||||
|
||||
except Exception as e:
|
||||
session['buffer'].put(f"ERROR:{str(e)}".encode())
|
||||
session['sentence_complete_event'].set() # 确保事件被设置
|
||||
|
||||
def _stream_audio(self, session_id, text):
|
||||
"""流式传输文本到TTS服务"""
|
||||
session = self.sessions.get(session_id)
|
||||
@@ -247,9 +415,12 @@ class StreamSessionManager:
|
||||
# 使用流式调用发送文本
|
||||
session['tts_model'].streaming_call(text)
|
||||
session['last_active'] = time.time()
|
||||
# 流式引擎不需要等待完成事件
|
||||
session['sentence_complete_event'].set()
|
||||
except Exception as e:
|
||||
logging.error(f"Error in streaming_call: {str(e)}")
|
||||
session['buffer'].put(f"ERROR:{str(e)}".encode())
|
||||
session['sentence_complete_event'].set()
|
||||
|
||||
async def get_tts_buffer_data(self, session_id):
|
||||
"""异步流式返回 TTS 音频数据(适配同步 queue.Queue,带 10 秒超时)"""
|
||||
@@ -298,6 +469,8 @@ class StreamSessionManager:
|
||||
|
||||
# 标记会话为不活跃
|
||||
self.sessions[session_id]['active'] = False
|
||||
# 设置完成事件(确保任何等待的线程被唤醒)
|
||||
self.sessions[session_id]['sentence_complete_event'].set()
|
||||
# 延迟2秒后清理资源
|
||||
threading.Timer(1, self._clean_session, args=[session_id]).start()
|
||||
|
||||
@@ -827,7 +1000,8 @@ from dashscope.audio.tts_v2 import (
|
||||
|
||||
|
||||
class QwenTTS:
|
||||
def __init__(self, key, format="mp3", sample_rate=44100, model_name="cosyvoice-v1/longxiaochun"):
|
||||
def __init__(self, key, format="mp3", sample_rate=44100, model_name="cosyvoice-v1/longxiaochun",
|
||||
special_characters: Optional[Dict[str, str]] = None):
|
||||
import dashscope
|
||||
import ssl
|
||||
logging.info(f"---begin--init QwenTTS-- {format} {sample_rate} {model_name} {model_name.split('@')[0]}") # cyx
|
||||
@@ -844,14 +1018,22 @@ class QwenTTS:
|
||||
if '/' in self.model_name:
|
||||
parts = self.model_name.split('/', 1)
|
||||
# 返回分离后的两个字符串parts[0], parts[1]
|
||||
if parts[0] == 'cosyvoice-v1':
|
||||
if parts[0] == 'cosyvoice-v1' or parts[0] == 'cosyvoice-v2':
|
||||
self.is_cosyvoice = True
|
||||
self.voice = parts[1]
|
||||
self.completion_event = None # 新增:用于通知任务完成
|
||||
# 特殊字符及其拼音映射
|
||||
self.special_characters = special_characters or {
|
||||
"㼽": "chuang3",
|
||||
"䡇": "yue4"
|
||||
# 可以添加更多特殊字符的映射
|
||||
}
|
||||
|
||||
class Callback(TTSResultCallback):
|
||||
def __init__(self) -> None:
|
||||
def __init__(self,data_callback=None,completion_event=None) -> None:
|
||||
self.dque = deque()
|
||||
|
||||
self.data_callback = data_callback
|
||||
self.completion_event = completion_event # 新增完成事件引用
|
||||
def _run(self):
|
||||
while True:
|
||||
if not self.dque:
|
||||
@@ -867,7 +1049,13 @@ class QwenTTS:
|
||||
pass
|
||||
|
||||
def on_complete(self):
|
||||
logging.info(f"---QwenTTS Callback on_complete--")
|
||||
self.dque.append(None)
|
||||
if self.data_callback:
|
||||
self.data_callback(None) # 发送结束信号
|
||||
# 通知任务完成
|
||||
if self.completion_event:
|
||||
self.completion_event.set()
|
||||
|
||||
def on_error(self, response: SpeechSynthesisResponse):
|
||||
print("Qwen tts error", str(response))
|
||||
@@ -877,15 +1065,22 @@ class QwenTTS:
|
||||
pass
|
||||
|
||||
def on_event(self, result: TTSSpeechSynthesisResult):
|
||||
if result.get_audio_frame() is not None:
|
||||
self.dque.append(result.get_audio_frame())
|
||||
data =result.get_audio_frame()
|
||||
if data is not None:
|
||||
if len(data) > 0:
|
||||
if self.data_callback:
|
||||
self.data_callback(data)
|
||||
else:
|
||||
self.dque.append(data)
|
||||
#self.dque.append(result.get_audio_frame())
|
||||
|
||||
# --------------------------
|
||||
|
||||
class Callback_Cosy(CosyResultCallback):
|
||||
def __init__(self, data_callback=None) -> None:
|
||||
def __init__(self, data_callback=None,completion_event=None) -> None:
|
||||
self.dque = deque()
|
||||
self.data_callback = data_callback
|
||||
self.completion_event = completion_event # 新增完成事件引用
|
||||
|
||||
def _run(self):
|
||||
while True:
|
||||
@@ -906,6 +1101,9 @@ class QwenTTS:
|
||||
self.dque.append(None)
|
||||
if self.data_callback:
|
||||
self.data_callback(None) # 发送结束信号
|
||||
# 通知任务完成
|
||||
if self.completion_event:
|
||||
self.completion_event.set()
|
||||
|
||||
def on_error(self, response: SpeechSynthesisResponse):
|
||||
print("Qwen tts error", str(response))
|
||||
@@ -938,23 +1136,28 @@ class QwenTTS:
|
||||
|
||||
# --------------------------
|
||||
|
||||
def tts(self, text):
|
||||
def tts(self, text, on_data = None,completion_event=None):
|
||||
# logging.info(f"---QwenTTS tts begin-- {text} {self.is_cosyvoice} {self.voice}") # cyx
|
||||
# text = self.normalize_text(text)
|
||||
print(f"--QwenTTS--tts_stream begin-- {text} {self.is_cosyvoice} {self.voice}") # cyx
|
||||
# text = self.normalize_text(text)
|
||||
|
||||
try:
|
||||
# if self.model_name != 'cosyvoice-v1':
|
||||
if self.is_cosyvoice is False:
|
||||
self.callback = self.Callback()
|
||||
self.callback = self.Callback(
|
||||
data_callback=on_data,
|
||||
completion_event=completion_event
|
||||
)
|
||||
TTSSpeechSynthesizer.call(model=self.model_name,
|
||||
text=text,
|
||||
callback=self.callback,
|
||||
format="wav") # format="mp3")
|
||||
format=self.format) # format="mp3")
|
||||
else:
|
||||
self.callback = self.Callback_Cosy()
|
||||
format = self.get_audio_format(self.format, self.sample_rate)
|
||||
self.synthesizer = CosySpeechSynthesizer(
|
||||
model='cosyvoice-v1',
|
||||
model='cosyvoice-v2',
|
||||
# voice="longyuan", #"longfei",
|
||||
voice=self.voice,
|
||||
callback=self.callback,
|
||||
@@ -974,26 +1177,68 @@ class QwenTTS:
|
||||
except Exception as e:
|
||||
raise RuntimeError(f"**ERROR**: {e}")
|
||||
|
||||
def setup_tts(self, on_data):
|
||||
"""设置 TTS 回调,返回配置好的 synthesizer"""
|
||||
if not self.is_cosyvoice:
|
||||
raise NotImplementedError("Only CosyVoice supported")
|
||||
def setup_tts(self, on_data,completion_event=None):
|
||||
|
||||
# 创建 CosyVoice 回调
|
||||
self.callback = self.Callback_Cosy(on_data)
|
||||
"""设置 TTS 回调,返回配置好的 synthesizer"""
|
||||
#if not self.is_cosyvoice:
|
||||
# raise NotImplementedError("Only CosyVoice supported")
|
||||
|
||||
if self.is_cosyvoice:
|
||||
# 创建 CosyVoice 回调
|
||||
self.callback = self.Callback_Cosy(
|
||||
data_callback=on_data,
|
||||
completion_event=completion_event)
|
||||
else:
|
||||
self.callback = self.Callback(
|
||||
data_callback=on_data,
|
||||
completion_event=completion_event)
|
||||
format_val = self.get_audio_format(self.format, self.sample_rate)
|
||||
logging.info(f"setup_tts {self.voice} {format_val}")
|
||||
self.synthesizer = CosySpeechSynthesizer(
|
||||
model='cosyvoice-v1',
|
||||
voice=self.voice, # voice="longyuan", #"longfei",
|
||||
callback=self.callback,
|
||||
format=format_val
|
||||
)
|
||||
logging.info(f"Qwen setup_tts {self.voice} {format_val}")
|
||||
if self.is_cosyvoice:
|
||||
self.synthesizer = CosySpeechSynthesizer(
|
||||
model='cosyvoice-v1',
|
||||
voice=self.voice, # voice="longyuan", #"longfei",
|
||||
callback=self.callback,
|
||||
format=format_val
|
||||
)
|
||||
|
||||
return self.synthesizer
|
||||
|
||||
def apply_phoneme_tags(self, text: str) -> str:
|
||||
"""
|
||||
在文本中查找特殊字符并用<phoneme>标签包裹它们
|
||||
"""
|
||||
# 如果文本已经是SSML格式,直接返回
|
||||
if text.strip().startswith("<speak>") and text.strip().endswith("</speak>"):
|
||||
return text
|
||||
|
||||
# 为特殊字符添加SSML标签
|
||||
for char, pinyin in self.special_characters.items():
|
||||
# 使用正则表达式确保只替换整个字符(避免部分匹配)
|
||||
pattern = r'([^<]|^)' + re.escape(char) + r'([^>]|$)'
|
||||
replacement = r'\1<phoneme alphabet="py" ph="' + pinyin + r'">' + char + r'</phoneme>\2'
|
||||
text = re.sub(pattern, replacement, text)
|
||||
|
||||
# 如果文本中已有SSML标签,直接返回
|
||||
if "<speak>" in text:
|
||||
return text
|
||||
|
||||
# 否则包裹在<speak>标签中
|
||||
return f"<speak>{text}</speak>"
|
||||
|
||||
def text_tts_call(self, text):
|
||||
if self.synthesizer:
|
||||
if self.special_characters and self.is_cosyvoice is False:
|
||||
text = self.apply_phoneme_tags(text)
|
||||
#logging.info(f"Applied SSML phoneme tags to text: {text}")
|
||||
|
||||
if self.synthesizer and self.is_cosyvoice:
|
||||
self.synthesizer.call(text)
|
||||
if self.is_cosyvoice is False:
|
||||
logging.info(f"Qwen text_tts_call {text}")
|
||||
TTSSpeechSynthesizer.call(model=self.model_name,
|
||||
text=text,
|
||||
callback=self.callback,
|
||||
format=self.format)
|
||||
|
||||
def streaming_call(self, text):
|
||||
if self.synthesizer:
|
||||
@@ -1027,22 +1272,178 @@ class QwenTTS:
|
||||
return format_map.get((sample_rate, format), AudioFormat.MP3_16000HZ_MONO_128KBPS)
|
||||
|
||||
|
||||
import threading
|
||||
import uuid
|
||||
import time
|
||||
import asyncio
|
||||
import logging
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from io import BytesIO
|
||||
class DoubaoTTS:
|
||||
def __init__(self, key, format="mp3", sample_rate=8000, model_name="doubao-tts"):
|
||||
logging.info(f"---begin--init DoubaoTTS-- {format} {sample_rate} {model_name}")
|
||||
# 解析豆包认证信息 (appid, token, cluster, voice_type)
|
||||
try:
|
||||
self.appid = "7282190702"
|
||||
self.token = "v64Fj-fwLLKIHBgqH2_fWx5dsBEShXd9"
|
||||
self.cluster = "volcano_tts"
|
||||
self.voice_type ="zh_female_qingxinnvsheng_mars_bigtts" # "zh_male_jieshuonansheng_mars_bigtts" #"zh_male_ruyaqingnian_mars_bigtts" #"zh_male_jieshuonansheng_mars_bigtts"
|
||||
except Exception as e:
|
||||
raise ValueError(f"Invalid Doubao key format: {str(e)}")
|
||||
|
||||
import threading
|
||||
import uuid
|
||||
import time
|
||||
import asyncio
|
||||
import logging
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from collections import deque
|
||||
from io import BytesIO
|
||||
self.format = format
|
||||
self.sample_rate = sample_rate
|
||||
self.model_name = model_name
|
||||
self.callback = None
|
||||
self.ws = None
|
||||
self.loop = None
|
||||
self.task = None
|
||||
self.event = threading.Event()
|
||||
self.data_queue = deque()
|
||||
self.host = "openspeech.bytedance.com"
|
||||
self.api_url = f"wss://{self.host}/api/v1/tts/ws_binary"
|
||||
self.default_header = bytearray(b'\x11\x10\x11\x00')
|
||||
self.total_data_size = 0
|
||||
self.completion_event = None # 新增:用于通知任务完成
|
||||
|
||||
|
||||
class Callback:
|
||||
def __init__(self, data_callback=None,completion_event=None):
|
||||
self.data_callback = data_callback
|
||||
self.data_queue = deque()
|
||||
self.completion_event = completion_event # 完成事件引用
|
||||
|
||||
def on_data(self, data):
|
||||
if self.data_callback:
|
||||
self.data_callback(data)
|
||||
else:
|
||||
self.data_queue.append(data)
|
||||
# 通知任务完成
|
||||
if self.completion_event:
|
||||
self.completion_event.set()
|
||||
|
||||
def on_complete(self):
|
||||
if self.data_callback:
|
||||
self.data_callback(None)
|
||||
|
||||
def on_error(self, error):
|
||||
if self.data_callback:
|
||||
self.data_callback(f"ERROR:{error}".encode())
|
||||
|
||||
def setup_tts(self, on_data,completion_event):
|
||||
|
||||
"""设置回调,返回自身(因为豆包需要异步启动)"""
|
||||
self.callback = self.Callback(
|
||||
data_callback=on_data,
|
||||
completion_event=completion_event
|
||||
)
|
||||
return self
|
||||
|
||||
def text_tts_call(self, text):
|
||||
"""同步调用,启动异步任务并等待完成"""
|
||||
self.total_data_size = 0
|
||||
self.loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(self.loop)
|
||||
self.task = self.loop.create_task(self._async_tts(text))
|
||||
try:
|
||||
self.loop.run_until_complete(self.task)
|
||||
except Exception as e:
|
||||
logging.error(f"DoubaoTTS--0 call error: {e}")
|
||||
self.callback.on_error(str(e))
|
||||
|
||||
async def _async_tts(self, text):
|
||||
"""异步执行TTS请求"""
|
||||
header = {"Authorization": f"Bearer; {self.token}"}
|
||||
request_json = {
|
||||
"app": {
|
||||
"appid": self.appid,
|
||||
"token": "access_token", # 固定值
|
||||
"cluster": self.cluster
|
||||
},
|
||||
"user": {
|
||||
"uid": str(uuid.uuid4()) # 随机用户ID
|
||||
},
|
||||
"audio": {
|
||||
"voice_type": self.voice_type,
|
||||
"encoding": self.format,
|
||||
"speed_ratio": 1.0,
|
||||
"volume_ratio": 1.0,
|
||||
"pitch_ratio": 1.0,
|
||||
},
|
||||
"request": {
|
||||
"reqid": str(uuid.uuid4()),
|
||||
"text": text,
|
||||
"text_type": "plain",
|
||||
"operation": "submit" # 使用submit模式支持流式
|
||||
}
|
||||
}
|
||||
|
||||
# 构建请求数据
|
||||
payload_bytes = str.encode(json.dumps(request_json))
|
||||
payload_bytes = gzip.compress(payload_bytes)
|
||||
full_client_request = bytearray(self.default_header)
|
||||
full_client_request.extend(len(payload_bytes).to_bytes(4, 'big'))
|
||||
full_client_request.extend(payload_bytes)
|
||||
|
||||
try:
|
||||
async with websockets.connect(self.api_url, extra_headers=header, ping_interval=None) as ws:
|
||||
self.ws = ws
|
||||
await ws.send(full_client_request)
|
||||
|
||||
# 接收音频数据
|
||||
while True:
|
||||
res = await ws.recv()
|
||||
done = self._parse_response(res)
|
||||
if done:
|
||||
self.callback.on_complete()
|
||||
break
|
||||
except Exception as e:
|
||||
logging.error(f"DoubaoTTS--1 WebSocket error: {e}")
|
||||
self.callback.on_error(str(e))
|
||||
finally:
|
||||
# 通知任务完成
|
||||
if self.completion_event:
|
||||
self.completion_event.set()
|
||||
|
||||
|
||||
def _parse_response(self, res):
|
||||
"""解析豆包返回的二进制响应"""
|
||||
# 协议头解析 (4字节)
|
||||
header_size = res[0] & 0x0f
|
||||
message_type = res[1] >> 4
|
||||
payload = res[header_size * 4:]
|
||||
|
||||
# 音频数据响应
|
||||
if message_type == 0xb: # audio-only server response
|
||||
message_flags = res[1] & 0x0f
|
||||
|
||||
# ACK消息,忽略
|
||||
if message_flags == 0:
|
||||
return False
|
||||
|
||||
# 音频数据消息
|
||||
sequence_number = int.from_bytes(payload[:4], "big", signed=True)
|
||||
payload_size = int.from_bytes(payload[4:8], "big", signed=False)
|
||||
audio_data = payload[8:8 + payload_size]
|
||||
|
||||
if audio_data:
|
||||
self.total_data_size = self.total_data_size + len(audio_data)
|
||||
self.callback.on_data(audio_data)
|
||||
|
||||
#logging.info(f"doubao _parse_response: {sequence_number} {len(audio_data)} {self.total_data_size}")
|
||||
# 序列号为负表示结束
|
||||
return sequence_number < 0
|
||||
|
||||
# 错误响应
|
||||
elif message_type == 0xf:
|
||||
code = int.from_bytes(payload[:4], "big", signed=False)
|
||||
msg_size = int.from_bytes(payload[4:8], "big", signed=False)
|
||||
error_msg = payload[8:8 + msg_size]
|
||||
|
||||
try:
|
||||
# 尝试解压错误消息
|
||||
error_msg = gzip.decompress(error_msg).decode()
|
||||
except:
|
||||
error_msg = error_msg.decode(errors='ignore')
|
||||
|
||||
logging.error(f"DoubaoTTS error: {error_msg}")
|
||||
self.callback.on_error(error_msg)
|
||||
return False
|
||||
|
||||
return False
|
||||
|
||||
|
||||
class UnifiedTTSEngine:
|
||||
@@ -1144,13 +1545,29 @@ class UnifiedTTSEngine:
|
||||
return
|
||||
|
||||
try:
|
||||
# 创建完成事件
|
||||
completion_event = threading.Event()
|
||||
# 创建TTS实例
|
||||
tts = QwenTTS(
|
||||
key=task['key'],
|
||||
format=task['format'],
|
||||
sample_rate=task['sample_rate'],
|
||||
model_name=task['model_name']
|
||||
)
|
||||
# 根据model_name选择TTS引擎
|
||||
# 前端传入 cosyvoice-v1/longhua@Tongyi-Qianwen
|
||||
model_name_wo_brand = task['model_name'].split('@')[0]
|
||||
model_name_version = model_name_wo_brand.split('/')[0]
|
||||
if "longhua" in task['model_name'] or "zh_female_qingxinnvsheng_mars_bigtts" in task['model_name']:
|
||||
# 豆包TTS
|
||||
tts = DoubaoTTS(
|
||||
key=task['key'],
|
||||
format=task['format'],
|
||||
sample_rate=task['sample_rate'],
|
||||
model_name=task['model_name']
|
||||
)
|
||||
else:
|
||||
# 通义千问TTS
|
||||
tts = QwenTTS(
|
||||
key=task['key'],
|
||||
format=task['format'],
|
||||
sample_rate=task['sample_rate'],
|
||||
model_name=task['model_name']
|
||||
)
|
||||
|
||||
# 定义同步数据处理函数
|
||||
def data_handler(data):
|
||||
@@ -1165,20 +1582,28 @@ class UnifiedTTSEngine:
|
||||
else: # 音频数据
|
||||
task['data_queue'].append(data)
|
||||
|
||||
# 设置并执行TTS
|
||||
synthesizer = tts.setup_tts(data_handler)
|
||||
synthesizer.call(task['text'])
|
||||
|
||||
# 设置并执行TTS
|
||||
synthesizer = tts.setup_tts(data_handler,completion_event)
|
||||
#synthesizer.call(task['text'])
|
||||
tts.text_tts_call(task['text'])
|
||||
# 等待完成或超时
|
||||
if not task['event'].wait(timeout=300): # 5分钟超时
|
||||
# 等待完成或超时
|
||||
if not completion_event.wait(timeout=300): # 5分钟超时
|
||||
task['error'] = "TTS generation timeout"
|
||||
task['completed'] = True
|
||||
|
||||
logging.info(f"--tts task event set error = {task['error']}")
|
||||
|
||||
except Exception as e:
|
||||
logging.info(f"UnifiedTTSEngine _run_tts_sync ERROR: {str(e)}")
|
||||
task['error'] = f"ERROR:{str(e)}"
|
||||
task['completed'] = True
|
||||
finally:
|
||||
# 确保清理TTS资源
|
||||
logging.info("UnifiedTTSEngine _run_tts_sync finally")
|
||||
if hasattr(tts, 'loop') and tts.loop:
|
||||
tts.loop.close()
|
||||
|
||||
def _merge_audio_data(self, audio_stream_id):
|
||||
"""将任务的所有音频数据合并到ByteIO缓冲区"""
|
||||
@@ -1219,7 +1644,7 @@ class UnifiedTTSEngine:
|
||||
# 如果是延迟任务且未启动,现在启动 status 为 pending
|
||||
if task['delay_gen_audio'] and task['status'] == 'pending':
|
||||
self._start_tts_task(audio_stream_id)
|
||||
|
||||
total_audio_data_size = 0
|
||||
# 等待任务启动
|
||||
while task['status'] == 'pending':
|
||||
await asyncio.sleep(0.1)
|
||||
@@ -1228,7 +1653,8 @@ class UnifiedTTSEngine:
|
||||
while not task['completed'] or task['data_queue']:
|
||||
while task['data_queue']:
|
||||
data = task['data_queue'].popleft()
|
||||
# logging.info(f"yield data {len(data)}")
|
||||
total_audio_data_size += len(data)
|
||||
#logging.info(f"yield audio data {len(data)} {total_audio_data_size}")
|
||||
yield data
|
||||
|
||||
# 短暂等待新数据
|
||||
@@ -1318,6 +1744,7 @@ async def proxy_aichat_audio_stream(client_id: str, audio_url: str):
|
||||
|
||||
|
||||
# 代理函数 - 文本流
|
||||
# 在微信小程序中,原来APK使用的SSE机制不能正常工作,需要使用WebSocket
|
||||
async def proxy_aichat_text_stream(client_id: str, completions_url: str, payload: dict):
|
||||
"""代理大模型文本流请求 - 兼容现有Flask实现"""
|
||||
try:
|
||||
@@ -1328,13 +1755,19 @@ async def proxy_aichat_text_stream(client_id: str, completions_url: str, payload
|
||||
"Content-Type": "application/json",
|
||||
'Authorization': 'Bearer ragflow-NhZTY5Y2M4YWQ1MzExZWY4Zjc3MDI0Mm'
|
||||
}
|
||||
tts_model_name = payload.get('tts_model', 'cosyvoice-v1/longyuan@Tongyi-Qianwen')
|
||||
#if 'longyuan' in tts_model_name:
|
||||
# tts_model_name = "cosyvoice-v2/longyuan_v2@Tongyi-Qianwen"
|
||||
# 创建TTS实例
|
||||
tts_model = QwenTTS(
|
||||
key=ALI_KEY,
|
||||
format=payload.get('tts_stream_format', 'mp3'),
|
||||
sample_rate=payload.get('tts_sample_rate', 48000),
|
||||
model_name=payload.get('tts_model', 'cosyvoice-v1/longyuan@Tongyi-Qianwen')
|
||||
model_name=tts_model_name
|
||||
)
|
||||
streaming_call = False
|
||||
if tts_model.is_cosyvoice:
|
||||
streaming_call = True
|
||||
|
||||
# 创建流会话
|
||||
tts_stream_session_id = stream_manager.create_session(
|
||||
@@ -1342,7 +1775,7 @@ async def proxy_aichat_text_stream(client_id: str, completions_url: str, payload
|
||||
sample_rate=payload.get('tts_sample_rate', 48000),
|
||||
stream_format=payload.get('tts_stream_format', 'mp3'),
|
||||
session_id=None,
|
||||
streaming_call=True
|
||||
streaming_call= streaming_call
|
||||
)
|
||||
# logging.info(f"---tts_stream_session_id = {tts_stream_session_id}")
|
||||
tts_stream_session_id_sent = False
|
||||
@@ -1399,7 +1832,6 @@ async def proxy_aichat_text_stream(client_id: str, completions_url: str, payload
|
||||
data_obj.get('data')['audio_stream_url'] = f"/tts_stream/{tts_stream_session_id}"
|
||||
data_str = json.dumps(data_obj)
|
||||
tts_stream_session_id_sent = True
|
||||
|
||||
# 直接转发原始数据
|
||||
await manager.send_text(client_id, json.dumps({
|
||||
"type": "text",
|
||||
@@ -1717,12 +2149,14 @@ async def websocket_tts_endpoint(
|
||||
audio_url = f"http://localhost:9380/api/v1/tts_stream/{audio_stream_id}"
|
||||
# await proxy_aichat_audio_stream(connection_id, audio_url)
|
||||
sample_rate = stream_manager.get_session(audio_stream_id).get('sample_rate')
|
||||
audio_data_size =0
|
||||
await manager.send_json(connection_id, {"command": "sample_rate", "params": sample_rate})
|
||||
async for data in stream_manager.get_tts_buffer_data(audio_stream_id):
|
||||
audio_data_size += len(data)
|
||||
if not await manager.send_bytes(connection_id, data):
|
||||
break
|
||||
completed_successfully = True
|
||||
|
||||
logging.info(f"--- proxy AiChatTts audio_data_size={audio_data_size}")
|
||||
elif service_type == "AiChatText":
|
||||
# 文本代理服务
|
||||
# 等待客户端发送初始请求数据 进行大模型对话代理时,需要前端连接后发送payload
|
||||
|
||||
@@ -1,263 +0,0 @@
|
||||
"""
|
||||
ALI_KEY = "sk-a47a3fb5f4a94f66bbaf713779101c75"
|
||||
class QwenTTS:
|
||||
def __init__(self, key,format="mp3",sample_rate=44100, model_name="cosyvoice-v1/longxiaochun"):
|
||||
import dashscope
|
||||
print("---begin--init dialog_service QwenTTS--") # cyx
|
||||
self.model_name = model_name
|
||||
dashscope.api_key = key
|
||||
self.synthesizer = None
|
||||
self.callback = None
|
||||
self.is_cosyvoice = False
|
||||
self.voice = ""
|
||||
self.format = format
|
||||
self.sample_rate = sample_rate
|
||||
if '/' in model_name:
|
||||
parts = model_name.split('/', 1)
|
||||
# 返回分离后的两个字符串parts[0], parts[1]
|
||||
if parts[0] == 'cosyvoice-v1':
|
||||
self.is_cosyvoice = True
|
||||
self.voice = parts[1]
|
||||
|
||||
def init_streaming_call(self, audio_call_back):
|
||||
from dashscope.api_entities.dashscope_response import SpeechSynthesisResponse
|
||||
# cyx 2025 01 19 测试cosyvoice 使用tts_v2 版本
|
||||
from dashscope.audio.tts_v2 import ResultCallback, SpeechSynthesizer, AudioFormat # , SpeechSynthesisResult
|
||||
from dashscope.audio.tts import SpeechSynthesisResult
|
||||
from collections import deque
|
||||
|
||||
print(f"--QwenTTS--tts_stream begin-- {self.is_cosyvoice} {self.voice}") # cyx
|
||||
|
||||
class Callback_v2(ResultCallback):
|
||||
def __init__(self) -> None:
|
||||
self.dque = deque()
|
||||
|
||||
def _run(self):
|
||||
while True:
|
||||
if not self.dque:
|
||||
time.sleep(0)
|
||||
continue
|
||||
val = self.dque.popleft()
|
||||
if val:
|
||||
yield val
|
||||
else:
|
||||
break
|
||||
|
||||
def on_open(self):
|
||||
logging.info("Qwen tts open")
|
||||
pass
|
||||
|
||||
def on_complete(self):
|
||||
self.dque.append(None)
|
||||
|
||||
def on_error(self, response: SpeechSynthesisResponse):
|
||||
print("Qwen tts error", str(response))
|
||||
raise RuntimeError(str(response))
|
||||
|
||||
def on_close(self):
|
||||
# print("---Qwen call back close") # cyx
|
||||
logging.info("Qwen tts close")
|
||||
pass
|
||||
|
||||
# canceled for test 语音大模型CosyVoice
|
||||
#def on_event(self, result: SpeechSynthesisResult):
|
||||
# if result.get_audio_frame() is not None:
|
||||
# self.dque.append(result.get_audio_frame())
|
||||
#
|
||||
|
||||
def on_event(self, message):
|
||||
# print(f"recv speech synthsis message {message}")
|
||||
pass
|
||||
|
||||
# 以下适合语音大模型CosyVoice
|
||||
def on_data(self, data: bytes) -> None:
|
||||
if len(data) > 0:
|
||||
#self.dque.append(data)
|
||||
if audio_call_back:
|
||||
audio_call_back(data)
|
||||
# --------------------------
|
||||
|
||||
# text = self.normalize_text(text)
|
||||
|
||||
try:
|
||||
self.callback = Callback_v2()
|
||||
format =self.get_audio_format(self.format,self.sample_rate)
|
||||
self.synthesizer = SpeechSynthesizer(
|
||||
model='cosyvoice-v1',
|
||||
# voice="longyuan", #"longfei",
|
||||
voice=self.voice,
|
||||
callback=self.callback,
|
||||
format=format
|
||||
)
|
||||
#self.synthesizer.call(text)
|
||||
except Exception as e:
|
||||
print(f"---dale---20 error {e}") # cyx
|
||||
# -----------------------------------
|
||||
# print(f"---Qwen return data {num_tokens_from_string(text)}")
|
||||
# yield num_tokens_from_string(text)
|
||||
|
||||
except Exception as e:
|
||||
raise RuntimeError(f"**ERROR**: {e}")
|
||||
|
||||
def get_audio_format(self, format: str, sample_rate: int):
|
||||
# 动态获取音频格式
|
||||
from dashscope.audio.tts_v2 import AudioFormat
|
||||
logging.info(f"QwenTTS--get_audio_format-- {format} {sample_rate}")
|
||||
format_map = {
|
||||
(8000, 'mp3'): AudioFormat.MP3_8000HZ_MONO_128KBPS,
|
||||
(8000, 'pcm'): AudioFormat.PCM_8000HZ_MONO_16BIT,
|
||||
(8000, 'wav'): AudioFormat.WAV_8000HZ_MONO_16BIT,
|
||||
(16000, 'pcm'): AudioFormat.PCM_16000HZ_MONO_16BIT,
|
||||
(22050, 'mp3'): AudioFormat.MP3_22050HZ_MONO_256KBPS,
|
||||
(22050, 'pcm'): AudioFormat.PCM_22050HZ_MONO_16BIT,
|
||||
(22050, 'wav'): AudioFormat.WAV_22050HZ_MONO_16BIT,
|
||||
(44100, 'mp3'): AudioFormat.MP3_44100HZ_MONO_256KBPS,
|
||||
(44100, 'pcm'): AudioFormat.PCM_44100HZ_MONO_16BIT,
|
||||
(44100, 'wav'): AudioFormat.WAV_44100HZ_MONO_16BIT,
|
||||
(48800, 'mp3'): AudioFormat.MP3_48000HZ_MONO_256KBPS,
|
||||
(48800, 'pcm'): AudioFormat.PCM_48000HZ_MONO_16BIT,
|
||||
(48800, 'wav'):AudioFormat.WAV_48000HZ_MONO_16BIT
|
||||
|
||||
}
|
||||
return format_map.get((sample_rate, format), AudioFormat.MP3_16000HZ_MONO_128KBPS)
|
||||
def streaming_call(self,text):
|
||||
if self.synthesizer:
|
||||
self.synthesizer.streaming_call(text)
|
||||
def end_streaming_call(self):
|
||||
if self.synthesizer:
|
||||
self.synthesizer.streaming_complete()
|
||||
|
||||
class StreamSessionManager1:
|
||||
def __init__(self):
|
||||
self.sessions = {} # {session_id: {'tts_model': obj, 'buffer': queue, 'task_queue': Queue}}
|
||||
self.lock = threading.Lock()
|
||||
self.executor = ThreadPoolExecutor(max_workers=30) # 固定大小线程池
|
||||
self.gc_interval = 300 # 5分钟清理一次 5 x 60 300秒
|
||||
self.gc_tts = 10 # 10s 大模型开始输出文本有可能需要比较久,2025年5 24 从3s->10s
|
||||
self.inited = False
|
||||
self.tts_model = None
|
||||
def create_session(self, tts_model,sample_rate =8000, stream_format='mp3'):
|
||||
session_id = str(uuid.uuid4())
|
||||
with self.lock:
|
||||
self.sessions[session_id] = {
|
||||
'tts_model': tts_model,
|
||||
'buffer': queue.Queue(maxsize=300), # 线程安全队列
|
||||
'task_queue': queue.Queue(),
|
||||
'active': True,
|
||||
'last_active': time.time(),
|
||||
'audio_chunk_count':0,
|
||||
'finished': threading.Event(), # 添加事件对象
|
||||
'sample_rate':sample_rate,
|
||||
'stream_format':stream_format,
|
||||
"tts_chunk_data_valid":False
|
||||
}
|
||||
# 启动任务处理线程
|
||||
threading.Thread(target=self._process_tasks, args=(session_id,), daemon=True).start()
|
||||
|
||||
|
||||
return session_id
|
||||
|
||||
def append_text(self, session_id, text):
|
||||
with self.lock:
|
||||
session = self.sessions.get(session_id)
|
||||
if not session: return
|
||||
# 将文本放入任务队列(非阻塞)
|
||||
#logging.info(f"StreamSessionManager append_text {text}")
|
||||
try:
|
||||
session['task_queue'].put(text, block=False)
|
||||
except queue.Full:
|
||||
logging.warning(f"Session {session_id} task queue full")
|
||||
|
||||
def _process_tasks(self, session_id):
|
||||
#任务处理线程(每个会话独立)
|
||||
session = self.sessions.get(session_id)
|
||||
def audio_call_back(chunk):
|
||||
logging.info(f"audio_call_back {len(chunk)}")
|
||||
if session['stream_format'] == 'wav':
|
||||
if first_chunk:
|
||||
chunk_len = len(chunk)
|
||||
if chunk_len > 2048:
|
||||
session['buffer'].put(audio_fade_in(chunk, 1024))
|
||||
else:
|
||||
session['buffer'].put(audio_fade_in(chunk, chunk_len))
|
||||
first_chunk = False
|
||||
else:
|
||||
session['buffer'].put(chunk)
|
||||
else:
|
||||
session['buffer'].put(chunk)
|
||||
session['last_active'] = time.time()
|
||||
session['audio_chunk_count'] = session['audio_chunk_count'] + 1
|
||||
if session['tts_chunk_data_valid'] is False:
|
||||
session['tts_chunk_data_valid'] = True # 20250510 增加,表示连接TTS后台已经返回,可以通知前端了
|
||||
while True:
|
||||
if not session or not session['active']:
|
||||
break
|
||||
if not self.inited:
|
||||
self.inited = True
|
||||
self.tts_model = QwenTTS(ALI_KEY, session['stream_format'], session['sample_rate'])
|
||||
self.tts_model.init_streaming_call(audio_call_back)
|
||||
try:
|
||||
#logging.info(f"StreamSessionManager _process_tasks {session['task_queue'].qsize()}")
|
||||
# 合并多个文本块(最多等待50ms)
|
||||
texts = []
|
||||
while len(texts) < 5: # 最大合并5个文本块
|
||||
try:
|
||||
text = session['task_queue'].get(timeout=0.1)
|
||||
#logging.info(f"StreamSessionManager _process_tasks --0 {len(texts)}")
|
||||
texts.append(text)
|
||||
except queue.Empty:
|
||||
break
|
||||
|
||||
if texts:
|
||||
session['last_active'] = time.time() # 如果有处理文本,重置活跃时间
|
||||
# 提交到线程池处理
|
||||
future=self.executor.submit(
|
||||
self._generate_audio,
|
||||
session_id,
|
||||
' '.join(texts) # 合并文本减少请求次数
|
||||
)
|
||||
future.result() # 等待转换任务执行完毕
|
||||
session['last_active'] = time.time()
|
||||
# 会话超时检查
|
||||
if time.time() - session['last_active'] > self.gc_interval:
|
||||
self.close_session(session_id)
|
||||
break
|
||||
if time.time() - session['last_active'] > self.gc_tts:
|
||||
session['finished'].set()
|
||||
if self.tts_model:
|
||||
self.tts_model.end_streaming_call()
|
||||
break
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"Task processing error: {str(e)}")
|
||||
|
||||
def _generate_audio(self, session_id, text):
|
||||
#实际生成音频(线程池执行)
|
||||
session = self.sessions.get(session_id)
|
||||
if not session: return
|
||||
# logging.info(f"_generate_audio:{text}")
|
||||
first_chunk = True
|
||||
|
||||
try:
|
||||
self.tts_model.streaming_call(text)
|
||||
except Exception as e:
|
||||
session['buffer'].put(f"ERROR:{str(e)}")
|
||||
logging.info(f"--streaming_call--error {str(e)}")
|
||||
|
||||
|
||||
def close_session(self, session_id):
|
||||
with self.lock:
|
||||
if session_id in self.sessions:
|
||||
# 标记会话为不活跃
|
||||
self.sessions[session_id]['active'] = False
|
||||
# 延迟2秒后清理资源
|
||||
threading.Timer(1, self._clean_session, args=[session_id]).start()
|
||||
|
||||
def _clean_session(self, session_id):
|
||||
with self.lock:
|
||||
if session_id in self.sessions:
|
||||
del self.sessions[session_id]
|
||||
|
||||
def get_session(self, session_id):
|
||||
return self.sessions.get(session_id)
|
||||
"""
|
||||
@@ -1,32 +0,0 @@
|
||||
# ------------- 第一阶段:构建依赖 -------------
|
||||
FROM python:3.10-slim AS builder
|
||||
|
||||
# 安装系统依赖
|
||||
RUN apt update && apt install -y --no-install-recommends \
|
||||
libsndfile1 ffmpeg \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# 安装Python依赖
|
||||
WORKDIR /app
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# ------------- 第二阶段:运行时镜像 -------------
|
||||
FROM python:3.10-slim
|
||||
|
||||
# 从构建阶段复制已安装的依赖
|
||||
COPY --from=builder /usr/lib /usr/lib # 共享系统库
|
||||
COPY --from=builder /usr/local/lib/python3.10/site-packages /usr/local/lib/python3.10/site-packages
|
||||
|
||||
# 设置工作目录和Python路径
|
||||
WORKDIR /app
|
||||
ENV PYTHONPATH=/app
|
||||
|
||||
# 复制代码
|
||||
COPY app ./app
|
||||
|
||||
# 暴露端口
|
||||
EXPOSE 9480
|
||||
|
||||
# 启动命令
|
||||
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "9480"]
|
||||
Reference in New Issue
Block a user