This commit is contained in:
eric
2025-08-04 14:12:40 +08:00
parent 36b70d2135
commit 1eb1150b84
3 changed files with 53 additions and 25 deletions

View File

@@ -28,6 +28,24 @@ from ws_server import push_to_frontend
import asyncio
from dataclasses import asdict
# TTS 播报引擎(全局只初始化一次)
tts_engine = pyttsx3.init()
tts_engine.setProperty('rate', 170)
tts_engine.setProperty('volume', 1.0)
# 加锁防止多线程同时播报冲突
tts_lock = threading.Lock()
def speak(text: str):
"""线程安全地进行语音播报"""
try:
with tts_lock:
tts_engine.say(text)
tts_engine.runAndWait()
except Exception as e:
print("【X】TTS 播报失败:", e)
@contextmanager
def patched_popen_encoding(encoding='utf-8'):
original_popen_init = subprocess.Popen.__init__
@@ -306,14 +324,34 @@ class DouyinLiveWebFetcher:
user_name = message.user.nick_name
gift_name = message.gift.name
gift_cnt = message.combo_count
print(f"【礼物msg】{user_name} 送出了 {gift_name}x{gift_cnt}")
print('送了礼物呀')
# print(f"【礼物msg】{user_name} 送出了 {gift_name}x{gift_cnt}")
user_data = asdict(message.user)
try:
speak(f"谢谢{user_name}送的小星星")
push_to_frontend(user_data,'gift')
except Exception as e:
print("【礼物播报失败:", e)
def _parseLikeMsg(self, payload):
'''点赞消息'''
message = LikeMessage().parse(payload)
# message = LikeMessage().parse(payload)
user_name = message.user.nick_name
count = message.count
print(f"【点赞msg】{user_name} 点了{count}个赞")
# count = message.count
# print('点了攒')
# # print(f"【点赞msg】{user_name} 点了{count}个赞")
# user_data = asdict(message.user)
try:
message = LikeMessage().parse(payload)
user_name = message.user.nick_name
count = message.count
print('点了攒')
# print(f"【点赞msg】{user_name} 点了{count}个赞")
user_data = asdict(message.user)
speak(f"谢谢{user_name}点赞")
push_to_frontend(user_data,'like')
except Exception as e:
print("【点赞播报失败:", e)
# def _parseMemberMsg(self, payload):
# '''进入直播间消息'''
@@ -326,26 +364,14 @@ class DouyinLiveWebFetcher:
'''进入直播间消息'''
message = MemberMessage().parse(payload)
user_name = message.user.nick_name
user_id = message.user.id
gender = ["", ""][message.user.gender]
# avatar = message.user.avatar
print(f"【进场msg】{user_name} 进入了直播间")
user_data = asdict(message.user)
# user_data = {
# "user_id": user_id,
# "user_name": user_name,
# "gender": gender,
# }
# ✅ 播放语音播报
try:
# engine = pyttsx3.init()
# engine.setProperty('rate', 170) # 语速,建议范围 120-200
# engine.setProperty('volume', 1.0) # 音量 0.0 ~ 1.0
# # engine.say(f"{gender}观众 {user_name} 进入了直播间")
# engine.say(f"{user_name}进入了直播间")
# engine.runAndWait()
# ✅ 播放语音播报
speak(f"{user_name}进入了直播间")
# 推送给 WebSocket 客户端
push_to_frontend(user_data)
push_to_frontend(user_data,'join')
except Exception as e:
print("【X】TTS 播报失败:", e)

View File

@@ -26,6 +26,8 @@ time.sleep(1)
# ✅ 主程序启动直播监听
if __name__ == '__main__':
live_id = '9638535297'
# live_id = '262648053209'
room = DouyinLiveWebFetcher(live_id)
room.get_room_status()
room.start()

View File

@@ -17,10 +17,10 @@ async def ws_handler(websocket):
connected_clients.remove(websocket)
# 推送消息到所有前端
async def push_to_all_clients(user_data: dict):
async def push_to_all_clients(user_data: dict,type: str = "join"):
# ✅ 直接发送结构化 JSON
message = {
"type": "join",
"type": type,
"data": user_data
}
for client in connected_clients.copy():
@@ -35,12 +35,12 @@ async def ws_main():
await asyncio.Future() # 永远挂起,保持服务运行
# 主线程中调用这个方法推送消息
def push_to_frontend(user_data):
def push_to_frontend(user_data, type: str = "join"):
loop = asyncio.get_event_loop()
if loop.is_running():
asyncio.run_coroutine_threadsafe(push_to_all_clients(user_data), loop)
asyncio.run_coroutine_threadsafe(push_to_all_clients(user_data, type), loop)
else:
loop.run_until_complete(push_to_all_clients(user_data))
loop.run_until_complete(push_to_all_clients(user_data, type))
# 在线程中启动服务
def start_ws_server():