diff --git a/README.md b/README.md index b33013e8..09fe616d 100644 --- a/README.md +++ b/README.md @@ -1216,6 +1216,7 @@ cmd输入命令即可:`doctoc /path/to/file` ### 2023-07-27 - ChatGLM支持上下文,默认启动(GUI未适配) +- 抖音版增加 定时播报任务功能,用户可以自定义是否启用,循环时间和定时任务文案(变量可自行修改源码追加功能) diff --git a/config.json b/config.json index 314bde42..6c841c8e 100644 --- a/config.json +++ b/config.json @@ -17,7 +17,8 @@ "commit_forget_duration": 3, "gift_forget_duration": 10, "entrance_forget_duration": 30, - "talk_forget_duration": 0.1 + "talk_forget_duration": 0.1, + "schedule_forget_duration": 0.1 }, "thanks": { "entrance_enable": true, @@ -235,5 +236,23 @@ "captions": { "enable": true, "file_path": "log/字幕.txt" - } + }, + "schedule": [ + { + "enable": true, + "time": 7, + "copy": [ + "现在是{time}", + "当前时间为{time}" + ] + }, + { + "enable": true, + "time": 10, + "copy": [ + "感谢还在观看直播的{user_num}位兄弟姐妹们", + "感谢{last_username}的支持" + ] + } + ] } \ No newline at end of file diff --git a/config.json.bak b/config.json.bak index 314bde42..6c841c8e 100644 --- a/config.json.bak +++ b/config.json.bak @@ -17,7 +17,8 @@ "commit_forget_duration": 3, "gift_forget_duration": 10, "entrance_forget_duration": 30, - "talk_forget_duration": 0.1 + "talk_forget_duration": 0.1, + "schedule_forget_duration": 0.1 }, "thanks": { "entrance_enable": true, @@ -235,5 +236,23 @@ "captions": { "enable": true, "file_path": "log/字幕.txt" - } + }, + "schedule": [ + { + "enable": true, + "time": 7, + "copy": [ + "现在是{time}", + "当前时间为{time}" + ] + }, + { + "enable": true, + "time": 10, + "copy": [ + "感谢还在观看直播的{user_num}位兄弟姐妹们", + "感谢{last_username}的支持" + ] + } + ] } \ No newline at end of file diff --git a/dy.py b/dy.py index 305c2f23..197309dc 100644 --- a/dy.py +++ b/dy.py @@ -1,24 +1,135 @@ import websocket import json, logging, os +import time +import threading +import schedule +import random + +from functools import partial from utils.common import Common from utils.logger import Configure_logger from utils.my_handle import My_handle +from utils.config import Config + + +config = None +common = None +my_handle = None +last_liveroom_data = None +last_username_list = None def start_server(): + global config, common, my_handle, last_liveroom_data, last_username_list + + config_path = "config.json" + + config = Config(config_path) common = Common() # 日志文件路径 log_path = "./log/log-" + common.get_bj_time(1) + ".txt" Configure_logger(log_path) - my_handle = My_handle("config.json") + # 最新的直播间数据 + last_liveroom_data = { + 'OnlineUserCount': 0, + 'TotalUserCount': 0, + 'TotalUserCountStr': '0', + 'OnlineUserCountStr': '0', + 'MsgId': 0, + 'User': None, + 'Content': '当前直播间人数 0,累计直播间人数 0', + 'RoomId': 0 + } + # 最新入场的用户名列表 + last_username_list = [""] + + my_handle = My_handle(config_path) if my_handle is None: logging.error("程序初始化失败!") os._exit(0) + # 添加用户名到最新的用户名列表 + def add_username_to_last_username_list(data): + global last_username_list + + # 添加数据到 最新入场的用户名列表 + last_username_list.append(data) + + # 保留最新的3个数据 + last_username_list = last_username_list[-3:] + + + # 定时任务 + def schedule_task(index): + global config, common, my_handle, last_liveroom_data, last_username_list + + logging.debug("定时任务执行中...") + hour, min = common.get_bj_time(6) + + if 0 <= hour and hour < 6: + time = f"凌晨{hour}点" + elif 6 <= hour and hour < 9: + time = f"早晨{hour}点" + elif 9 <= hour and hour < 12: + time = f"上午{hour}点" + elif hour == 12: + time = f"中午{hour}点" + elif 13 <= hour and hour < 18: + time = f"下午{hour - 12}点" + elif 18 <= hour and hour < 20: + time = f"傍晚{hour - 12}点" + elif 20 <= hour and hour < 24: + time = f"晚上{hour - 12}点" + + + # 根据对应索引从列表中随机获取一个值 + random_copy = random.choice(config.get("schedule")[index]["copy"]) + + # 根据变量的有无来进行数据替换 + if "{time}" in random_copy: + content = random_copy.format(time=time) + if "{user_num}" in random_copy: + content = random_copy.format(user_num=last_liveroom_data["OnlineUserCount"]) + if "{last_username}" in random_copy: + content = random_copy.format(last_username=last_username_list[0]) + + data = { + "username": None, + "content": content + } + + logging.info(f"定时任务:{content}") + + my_handle.process_data(data, "schedule") + + + # 启动定时任务 + def run_schedule(): + try: + for index, task in enumerate(config.get("schedule")): + if task["enable"]: + # print(task) + # 设置定时任务,每隔n秒执行一次 + schedule.every(task["time"]).seconds.do(partial(schedule_task, index)) + except Exception as e: + logging.error(e) + + while True: + schedule.run_pending() + # time.sleep(1) # 控制每次循环的间隔时间,避免过多占用 CPU 资源 + + + # 创建定时任务子线程并启动 + schedule_thread = threading.Thread(target=run_schedule) + schedule_thread.start() + + def on_message(ws, message): + global last_liveroom_data, last_username_list + message_json = json.loads(message) # logging.debug(message_json) if "Type" in message_json: @@ -56,6 +167,9 @@ def on_message(ws, message): "content": "进入直播间" } + # 添加用户名到最新的用户名列表 + add_username_to_last_username_list(user_name) + my_handle.process_data(data, "entrance") elif type == 4: @@ -108,6 +222,11 @@ def on_message(ws, message): elif type == 6: logging.info(f'[直播间数据] {data_json["Content"]}') + # {'OnlineUserCount': 50, 'TotalUserCount': 22003, 'TotalUserCountStr': '2.2万', 'OnlineUserCountStr': '50', + # 'MsgId': 7260517442466662207, 'User': None, 'Content': '当前直播间人数 50,累计直播间人数 2.2万', 'RoomId': 7260415920948906807} + # print(f"data_json={data_json}") + + last_liveroom_data = data_json pass @@ -116,7 +235,6 @@ def on_message(ws, message): pass - def on_error(ws, error): logging.error("Error:", error) @@ -151,6 +269,9 @@ def on_open(ws): logging.info('关闭连接...可能是直播间不存在或下播或网络问题') os._exit(0) + # 等待子线程结束 + schedule_thread.join() + if __name__ == '__main__': start_server() diff --git a/utils/common.py b/utils/common.py index 092ae059..421a86d3 100644 --- a/utils/common.py +++ b/utils/common.py @@ -28,15 +28,18 @@ def get_bj_time(self, type=0): """获取北京时间 Args: - type (int, optional): 返回时间类型. 默认为 0. + type (int, str): 返回时间类型. 默认为 0. 0 返回数据:年-月-日 时:分:秒 1 返回数据:年-月-日 2 返回数据:当前时间的秒 3 返回数据:自1970年1月1日以来的秒数 4 返回数据:返回自1970年1月1日以来的毫秒数 % 100 + 5 返回数据:当前 时点分 + 6 返回数据:当前时间的 时, 分 Returns: str: 返回指定格式的时间字符串 + int, int """ if type == 0: utc_now = datetime.utcnow().replace(tzinfo=timezone.utc) # 获取当前 UTC 时间 @@ -80,6 +83,13 @@ def get_bj_time(self, type=0): minute = now.tm_min # 获取当前分钟 return str(hour) + "点" + str(minute) + elif type == 6: + now = time.localtime() # 获取当前时间 + + hour = now.tm_hour # 获取当前小时 + minute = now.tm_min # 获取当前分钟 + + return hour, minute # 删除多余单词 def remove_extra_words(self, text="", max_len=30, max_char_len=50): diff --git a/utils/my_handle.py b/utils/my_handle.py index 59c81437..cb206d89 100644 --- a/utils/my_handle.py +++ b/utils/my_handle.py @@ -695,6 +695,26 @@ def entrance_handle(self, data): logging.error(e) + # 定时处理 + def schedule_handle(self, data): + try: + content = data["content"] + + message = { + "type": "entrance", + "tts_type": self.audio_synthesis_type, + "data": self.config.get(self.audio_synthesis_type), + "config": self.filter_config, + "user_name": data['username'], + "content": content + } + + # 音频合成(edge-tts / vits)并播放 + self.audio.audio_synthesis(message) + except Exception as e: + logging.error(e) + + """ 数据丢弃部分 """ @@ -721,6 +741,9 @@ def process_last_data(self, timer_flag): elif timer_flag == "talk": # 聊天暂时共用弹幕处理逻辑 self.commit_handle(timer.last_data) + elif timer_flag == "schedule": + # 定时任务处理 + self.schedule_handle(timer.last_data) # 清空数据 timer.last_data = None @@ -731,7 +754,8 @@ def get_interval(self, timer_flag): "commit": self.config.get("filter", "commit_forget_duration"), "gift": self.config.get("filter", "gift_forget_duration"), "entrance": self.config.get("filter", "entrance_forget_duration"), - "talk": self.config.get("filter", "talk_forget_duration") + "talk": self.config.get("filter", "talk_forget_duration"), + "schedule": self.config.get("filter", "schedule_forget_duration") # 根据需要添加更多计时器及其间隔 }