lizhengwei

jira:NYJ-1540 desc: add my_logger.py

import os
import time
import logging
from aabd.base.enhance_dict import value_or_default
logger = logging.getLogger(__name__)
from utils.football_replay_video_event_by_llm import FootballReplayVideoEvent
from utils.football_replay_match_live import FootballReplayMatchLive
from utils.my_logger import get_logger
logger = get_logger()
class FootballReplayMatch:
def __init__(self, settings):
self.settings = settings
... ... @@ -93,25 +99,25 @@ class FootballReplayMatch:
start_time = time.time()
replay_det_info = self.det_goal_replay(replay_info, task_id)
end_time = time.time()
logger.info(f"判断是否是进球耗时: {end_time - start_time} 秒")
print(f"判断是否是进球耗时: {end_time - start_time} 秒")
logger.info(f"Goal_recognition_all_cost_time:{end_time-start_time:.2f}seconds")
# print(f"判断是否是进球耗时: {end_time - start_time} 秒")
replay_event_name = replay_det_info.get('event_name', '')
if replay_event_name == '进球':
matched_event = self.match_by_llm(replay_info, goal_live_events, task_id)
if matched_event is None:
logger.info(f"{task_id}_LLM认为视频{replay_info['url']}_{replay_start_utc}_{replay_end_utc} 是进球但是未能找到匹配的事件")
print(f"{task_id}_LLM认为视频{replay_info['url']}_{replay_start_utc}_{replay_end_utc} 是进球但是未能找到匹配的事件")
logger.info(f"{task_id}_LLM_think_{replay_info['url']}_{replay_start_utc}_{replay_end_utc}_is_goal_but_no_matched_event")
# print(f"{task_id}_LLM认为视频{replay_info['url']}_{replay_start_utc}_{replay_end_utc} 是进球但是未能找到匹配的事件")
else:
matched_event_id = matched_event.get('video_id')
logger.info(f"{task_id}_LLM认为视频{replay_info['url']}_{replay_start_utc}_{replay_end_utc} 对应的进球的事件视频是{matched_event_id}")
print(f"{task_id}_LLM认为视频{replay_info['url']}_{replay_start_utc}_{replay_end_utc} 对应的进球的事件视频是{matched_event_id}")
logger.info(f"{task_id}_LLM_think_{replay_info['url']}_{replay_start_utc}_{replay_end_utc}_matched_with_{matched_event_id}")
# print(f"{task_id}_LLM认为视频{replay_info['url']}_{replay_start_utc}_{replay_end_utc} 对应的进球的事件视频是{matched_event_id}")
else:
logger.info(f"{task_id}_LLM判断{replay_info['url']}_{replay_start_utc}_{replay_end_utc} 不是进球,无需匹配")
print(f"{task_id}_LLM判断{replay_info['url']}_{replay_start_utc}_{replay_end_utc} 不是进球,无需匹配")
logger.info(f"{task_id}_LLM_think_{replay_info['url']}_{replay_start_utc}_{replay_end_utc}_is_not_goal_no_need_match")
# print(f"{task_id}_LLM判断{replay_info['url']}_{replay_start_utc}_{replay_end_utc} 不是进球,无需匹配")
else:
matched_event_id = matched_event.get('id')
logger.info(f"{task_id}_通过时间找到匹配认为视频{replay_info['url']}_{replay_start_utc}_{replay_end_utc} 对应的进球的事件视频是{matched_event_id}")
print(f"{task_id}_通过时间找到匹配认为视频{replay_info['url']}_{replay_start_utc}_{replay_end_utc} 对应的进球的事件视频是{matched_event_id}")
logger.info(f"{task_id}_matched_by_time{replay_info['url']}_{replay_start_utc}_{replay_end_utc}_matched_with_{matched_event_id}")
# print(f"{task_id}_通过时间找到匹配认为视频{replay_info['url']}_{replay_start_utc}_{replay_end_utc} 对应的进球的事件视频是{matched_event_id}")
return {
"id": task_id,
"match_id": match_id,
... ...
... ... @@ -20,6 +20,10 @@ try:
except ImportError:
from .api import FootballReplayMatch
from pathlib import Path
def get_video_files_pathlib(folder_path, extensions=None):
if extensions is None:
... ... @@ -32,7 +36,7 @@ def get_video_files_pathlib(folder_path, extensions=None):
if f.is_file() and f.suffix.lower() in extensions]
return sorted(image_files)
def _fake_settings(match_by_time_threshold: int = 30):
def _fake_settings(match_by_time_threshold: int = 30, cache_dir_tag: str = "test"):
"""构造一个 settings 伪对象,兼容 api.py 中的 value_or_default 读取逻辑。"""
return SimpleNamespace(
match_by_time_threshold=match_by_time_threshold,
... ... @@ -41,18 +45,34 @@ def _fake_settings(match_by_time_threshold: int = 30):
temperature=0.7,
api_key='no_key'
),
common=SimpleNamespace(cache_dir="/root/lzw/tmp_0527_replay_cache_08/videos_cache",
task_log_dir="/root/lzw/tmp_0527_replay_cache_08/tasks_log"
common=SimpleNamespace(cache_dir=f"/root/lzw/tmp_0528_replay_cache_{cache_dir_tag}/videos_cache",
task_log_dir=f"/root/lzw/tmp_0528_replay_cache_{cache_dir_tag}/tasks_log"
),
save_frames_enable=True,
)
def get_replays_and_events_pair():
videos_dir = rf"/root/lzw/finished"
dir_pairs = []
for video_name in sorted(os.listdir(videos_dir)):
live_dir = os.path.join(videos_dir, video_name, 'live')
live_video_dir = os.path.join(live_dir, 'videos')
def get_event_list():
replays_dir = os.path.join(videos_dir, video_name, 'replays')
replay_videos_dir = os.path.join(replays_dir, 'videos')
dir_pairs.append((replay_videos_dir, live_video_dir))
return dir_pairs
def get_event_list(events_mp4_dir):
# url = "http://video.mam.miguvideo.com/mnt6/fastclip3/wsc/2026/04/29/df760b8d15394cbc9ed0d0a4a9c4b786_1080PS/29133605/vodtmp/3b3e99cf4ca84c3782503d8817242de2.m3u8"
events_mp4_dir = r"/root/lzw/69e4ed7c872d573c9554510b-auto-10154973/goal"
# events_mp4_dir = r"/root/lzw/finished/69dd5845dd0412067b8d5587-auto-1776074760653/live/videos"
events_mp4_names = get_video_files_pathlib(events_mp4_dir)
... ... @@ -60,7 +80,7 @@ def get_event_list():
for mp4 in events_mp4_names:
mp4_path = os.path.join(events_mp4_dir, mp4)
event_lis.append({
"id": f"event_{mp4.split('.')[0]}",
"id": mp4,
"type": "1",
"url": mp4_path,
# "event_utc": None
... ... @@ -73,7 +93,7 @@ def _base_data(i, replay_path, event_lis):
"id": f"task_{str(i).zfill(3)}",
"match_id": f"match_{str(i).zfill(3)}",
"replay": {
"id": f"replay_{str(i).zfill(3)}",
"id": os.path.basename(replay_path),
"url": replay_path,
# "start_utc": None,
# "end_utc": None
... ... @@ -82,24 +102,36 @@ def _base_data(i, replay_path, event_lis):
}
class TestReplayMatchEvent(unittest.TestCase):
@patch("utils.football_replay_match_live.FootballReplayMatchLive")
@patch("utils.football_replay_video_event_by_llm.FootballReplayVideoEvent")
def test_match_by_time_success(self, mock_video_cls, mock_live_cls):
def test_match_by_time_success():
# """场景1:时间差在阈值内,直接通过 match_by_time 命中。"""
settings = _fake_settings(match_by_time_threshold=10) # threshold = 30 * 1000 = 30000 ms
replays_and_events_pair = get_replays_and_events_pair()
for replays_mp4_dir, events_mp4_dir in replays_and_events_pair:
print(100*"=")
print(f"replays_mp4_dir: {replays_mp4_dir}, events_mp4_dir: {events_mp4_dir}")
tag = os.path.basename(os.path.dirname(os.path.dirname(replays_mp4_dir)))
settings = _fake_settings(match_by_time_threshold=30, cache_dir_tag=tag) # threshold = 30 * 1000 = 30000 ms
frm = FootballReplayMatch(settings)
replays_mp4_dir = "/root/lzw/69e4ed7c872d573c9554510b-auto-10154973/replay"
# replays_mp4_dir = "/root/lzw/finished/69dd5845dd0412067b8d5587-auto-1776074760653/replays/videos"
relays_mp4_names = get_video_files_pathlib(replays_mp4_dir)
event_list = get_event_list()
# events_mp4_dir = r"/root/lzw/finished/69dd5845dd0412067b8d5587-auto-1776074760653/live/videos"
event_list = get_event_list(events_mp4_dir)
all_time = 0.0
max_time = 0.0
for i, replay_name in enumerate(relays_mp4_names):
print(100*"*" + f"replay_name: {replay_name}")
print(100*"*")
replay_path = os.path.join(replays_mp4_dir, replay_name)
data = _base_data(i+1, replay_path, event_list)
... ... @@ -115,13 +147,31 @@ class TestReplayMatchEvent(unittest.TestCase):
print(result)
print()
print()
print()
print(100*"#")
print(f"max_time: {max_time}")
print(f"all_time: {all_time}")
# exit()
if __name__ == "__main__":
test_match_by_time_success()
# self.assertEqual(result["id"], "task_001")
# self.assertEqual(result["match_id"], "match_001")
# self.assertEqual(result["replay_id"], "replay_001")
... ... @@ -245,7 +295,3 @@ class TestReplayMatchEvent(unittest.TestCase):
# with self.assertRaises(KeyError):
# frm.replay_match_event(data)
if __name__ == "__main__":
unittest.main()
... ...
import re
import json
import time
import os.path
from pathlib import Path
from datetime import timedelta
... ... @@ -9,9 +10,14 @@ from langchain_openai import ChatOpenAI
try:
from .llm_image import Video2Frame
from .my_logger import get_logger
except:
from llm_image import Video2Frame
from my_logger import get_logger
logger = get_logger()
# req_prompt = """
# # Role
# 你是一名拥有20年经验的足球视频技术分析师,擅长结合**视觉画面**与**解说音频(ASR)**进行跨镜头的事件匹配。你能通过解说员的描述锁定时间背景,并通过视觉特征确认物理细节。
... ... @@ -192,11 +198,14 @@ class FootballReplayMatchLive:
user_contents.append({'type': "text", "text": "\n请根据上述片段进行匹配并按要求输出结果/no_think\n"})
system_message = SystemMessage(content=req_prompt)
user_message = HumanMessage(content=user_contents)
result = self.model.invoke([system_message, user_message]).content
start_time = time.time()
result = self.model.invoke([system_message, user_message]).content
end_time = time.time()
logger.info(f"match_once_invoke_cost_time:{end_time-start_time:.2f}seconds")
# print(100*"3")
# print(result)
# logger.info(f"match once invoke result: {result}")
# print(100*"4")
# try:
# result_json = json.loads(result)
... ... @@ -299,7 +308,7 @@ class FootballReplayMatchLive:
start=event_start,
end=event_end,
roi=None,
max_px_area=400_000,
max_px_area=300_000,
prompt_start="\n【回放片段信息】\n",
prompt_end=f"\n回放解说内容:无\n"
)
... ...
import json
import time
import os.path
from pathlib import Path
from langchain_core.messages import SystemMessage, HumanMessage
from langchain_openai import ChatOpenAI
try:
from .llm_image import Video2Frame
from .my_logger import get_logger
except:
from llm_image import Video2Frame
from my_logger import get_logger
logger = get_logger()
req_prompt = """
... ... @@ -108,7 +117,12 @@ class FootballReplayVideoEvent:
system_message = SystemMessage(content=req_prompt)
video_message = HumanMessage(content=contents)
# asr_message = HumanMessage(content=f"解说内容:{asr_text}")
start_time = time.time()
result = self.model.invoke([system_message, video_message]).content
end_time = time.time()
logger.info(f"video_event_invoke_cost_time:{end_time-start_time:.2f}seconds")
# logger.info(f"video event invoke result: {result}")
try:
result_json = json.loads(result)
except json.JSONDecodeError:
... ...
import os
import time
import logging
from functools import lru_cache
@lru_cache(maxsize=1)
def get_logger():
name = "football_replay_match"
logger = logging.getLogger(name)
logger.setLevel(logging.INFO)
# 1. 配置日志输出格式
# 修改点:增加了 %(filename)s:%(lineno)d 来显示文件名和行号
formatter = logging.Formatter(
'%(asctime)s.%(msecs)03d - %(name)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
# 2. 创建控制台处理器
console_handler = logging.StreamHandler()
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)
# 3. 创建文件处理器
log_dir = "logs"
if not os.path.exists(log_dir):
os.makedirs(log_dir)
log_file = os.path.join(log_dir, f"run_{time.strftime('%Y%m%d')}.log")
file_handler = logging.FileHandler(log_file, encoding='utf-8')
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
return logger
\ No newline at end of file
... ...