Toggle navigation
Toggle navigation
This project
Loading...
Sign in
lizhengwei
/
aigc-embedding-service
Go to a project
Toggle navigation
Projects
Groups
Snippets
Help
Toggle navigation pinning
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
lizhengwei
2026-05-29 14:39:15 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
4eda21f1c7f992f654b01419dfdd44ede1aa7300
4eda21f1
1 parent
992c7bc8
jira:NYJ-1540 desc: add my_logger.py
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
144 additions
and
35 deletions
src/football_replay_match/core/api.py
src/football_replay_match/core/api_test.py
src/football_replay_match/core/utils/football_replay_match_live.py
src/football_replay_match/core/utils/football_replay_video_event_by_llm.py
src/football_replay_match/core/utils/my_logger.py
src/football_replay_match/core/api.py
View file @
4eda21f
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
,
...
...
src/football_replay_match/core/api_test.py
View file @
4eda21f
...
...
@@ -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
()
...
...
src/football_replay_match/core/utils/football_replay_match_live.py
View file @
4eda21f
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
=
4
00
_000
,
max_px_area
=
3
00
_000
,
prompt_start
=
"
\n
【回放片段信息】
\n
"
,
prompt_end
=
f
"
\n
回放解说内容:无
\n
"
)
...
...
src/football_replay_match/core/utils/football_replay_video_event_by_llm.py
View file @
4eda21f
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
:
...
...
src/football_replay_match/core/utils/my_logger.py
0 → 100644
View file @
4eda21f
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)03
d -
%(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
...
...
Please
register
or
login
to post a comment