肌肉功能,异步下载,解决阻塞问题

This commit is contained in:
liuwei
2025-05-28 09:52:07 +08:00
parent 25e7b444fe
commit c186f3ef49

View File

@@ -2,6 +2,7 @@ import os
import time import time
from typing import Dict, Any, List, Optional, Tuple from typing import Dict, Any, List, Optional, Tuple
import aiohttp
import cv2 import cv2
import requests import requests
from loguru import logger from loguru import logger
@@ -104,7 +105,7 @@ class VideoManPlugin(MessagePluginInterface):
try: try:
# 下载视频 # 下载视频
file_abspath, first_frame = self._download_video("https://api.guiguiya.com/api/video/fuji?type=json") file_abspath, first_frame = await self._download_video("https://api.guiguiya.com/api/video/fuji?type=json")
# FIXME 需要换成web容器地址。否则无法获取。 # FIXME 需要换成web容器地址。否则无法获取。
if not file_abspath: if not file_abspath:
await self.bot.send_text_message((roomid if roomid else sender), f"\n❌视频下载失败,请稍后再试", await self.bot.send_text_message((roomid if roomid else sender), f"\n❌视频下载失败,请稍后再试",
@@ -121,11 +122,11 @@ class VideoManPlugin(MessagePluginInterface):
self.LOG.error(f"处理视频请求出错: {e}") self.LOG.error(f"处理视频请求出错: {e}")
return False, f"处理出错: {e}" return False, f"处理出错: {e}"
def _download_video(self, api_url): async def _download_video(self, api_url):
""" """
从API获取视频URL并下载到本地 从API异步获取视频URL并下载到本地
:param api_url: API的URL :param api_url: API的URL
:return: 下载后的视频文件绝对路径 :return: 下载后的视频文件绝对路径和首帧路径,或 None
""" """
# 确保下载目录存在 # 确保下载目录存在
if not os.path.exists(self.download_dir): if not os.path.exists(self.download_dir):
@@ -134,29 +135,30 @@ class VideoManPlugin(MessagePluginInterface):
save_path = os.path.join(self.download_dir, "video.mp4") save_path = os.path.join(self.download_dir, "video.mp4")
try: try:
# 获取视频URL # 使用 aiohttp 异步获取视频URL
response = requests.get(api_url) async with aiohttp.ClientSession() as session:
if response.status_code != 200: async with session.get(api_url, timeout=20) as response:
self.LOG.error(f"API请求失败HTTP状态码: {response.status_code}") if response.status != 200:
return None self.LOG.error(f"API请求失败HTTP状态码: {response.status}")
return None
data = response.json() data = await response.json()
video_url = data.get("url") video_url = data.get("url")
if not video_url: if not video_url:
self.LOG.error("API响应中没有找到视频URL") self.LOG.error("API响应中没有找到视频URL")
return None return None
# 下载视频 # 异步下载视频
video_response = requests.get(video_url, stream=True) async with session.get(video_url, timeout=20) as video_response:
if video_response.status_code != 200: if video_response.status != 200:
self.LOG.error(f"无法下载视频HTTP状态码: {video_response.status_code}") self.LOG.error(f"无法下载视频HTTP状态码: {video_response.status}")
return None return None
# 保存视频 # 保存视频
with open(save_path, "wb") as file: with open(save_path, "wb") as file:
for chunk in video_response.iter_content(chunk_size=1024): async for chunk in video_response.content.iter_chunked(1024):
if chunk: # 过滤空块 if chunk: # 过滤空块
file.write(chunk) file.write(chunk)
abs_path = os.path.abspath(save_path) abs_path = os.path.abspath(save_path)
self.LOG.info(f"视频已下载至: {abs_path}") self.LOG.info(f"视频已下载至: {abs_path}")
@@ -166,7 +168,7 @@ class VideoManPlugin(MessagePluginInterface):
return abs_path, first_frame return abs_path, first_frame
except requests.RequestException as e: except aiohttp.ClientError as e:
self.LOG.error(f"请求失败: {e}") self.LOG.error(f"请求失败: {e}")
except IOError as e: except IOError as e:
self.LOG.error(f"文件写入失败: {e}") self.LOG.error(f"文件写入失败: {e}")