* Merge branch 'main' into feature/modal-cluster-gemini * ADD 增加大模型输出错误时间值的处理 * Merge branch 'main' into feature/modal-cluster-gemini * FIX 修复推理问题 * Merge branch 'main' into feature/modal-cluster-gemini * FIX 修复拼接网格图的异步失效问题 * FIX 修复拼接网格图的异步失效问题 * Merge branch 'main' into feature/modal-cluster-gemini * Merge branch 'main' into feature/modal-cluster-gemini * FIX 调高合成网格图容器配置 * Merge branch 'main' into feature/modal-cluster-gemini * FIX 修复带图片模态推理接口 * PERF 优化Gemini Prompt词 * Merge remote-tracking branch 'origin/main' into feature/modal-cluster-gemini * ADD 增加网格图片创建接口 ADD gemini推理打点增加商品封面模态 PERF gemini打点结果相邻时间线同商品合并 * Merge branch 'main' into feature/modal-cluster-gemini * FIX 429重试机制 * FIX 修复Gemini推理函数入参 * Merge branch 'main' into feature/modal-cluster-gemini * PERF gemini修改参数类型 ADD 增加批量删除Gemini文件接口 * PERF gemini修改prompt * Merge branch 'feature/modal-cluster' into feature/modal-cluster-gemini * PERF gemini修改prompt * 录制HLS时 结果复制到S3挂载点增加一个fallback处理 * Merge branch 'feature/modal-cluster' into feature/modal-cluster-gemini * PERF gemini修改prompt * PERF gemini增加图像模态 * PERF gemini增加图像模态 * fix : TikHub的Logger换为Loguru * fix : 修复直播切分视频接口 * Merge branch 'feature/modal-cluster' into feature/modal-cluster-gemini * PERF tikhub接口增加随机延迟 * Merge remote-tracking branch 'origin/feature/modal-cluster' into feature/modal-cluster * 合并分支 * fix : hls录制缓存读写问题 * FIX 修改冲突 * ADD 增加获取直播间指定商品数量接口 * Merge branch 'feature/modal-cluster' into feature/modal-cluster-gemini * PERF 修改tikhub到aws * fix : 增加s3分片上传接口 * PERF Gemini推理直接从参数列表获取商品列表 ADD Tikhub增加获取置顶|讲解中商品接口 * PERF Gemini推理直接从参数获取商品列表 * Merge branch 'feature/modal-cluster' into feature/modal-cluster-gemini * fix 处理jpg图片的codec_name应为mjpg * Merge branch 'feature/modal-cluster' into feature/modal-cluster-gemini * PERF 优化返回值 * fix 获取媒体metadata的类型报错,modal client升级到1.0.2 * Merge branch 'feature/modal-cluster' into feature/modal-cluster-gemini * PERF 风控后爬虫直接退出避免cookie失效 PERF 分离tikhub api, 使用更低的保持时间以更换IP FIX 修复Dict键不存在报错的bug * fix 一些webhook相关的bug,添加了更详细的接口说明 * 更新直播录制为可跳转时间的hls流接口,用于替代掉腾讯VOD+火山云拉流转推,片段保证每片开头为关键帧,时间精度准确到毫秒级 * ADD 增加直播间商品增量缓存触发器 * Merge branch 'feature/modal-cluster' into feature/modal-cluster-gemini * PERF 调整gemini prompt * - KVCache类改为可拓展,基于环境变量设置KV space - test 环境配置与CF测试环境对齐 * FIX 修复Gemini推理视频切条的问题 PERF 优化视频切条函数性能 * ADD 基本完成gemini视频推理API * ADD 添加内联的tikhub * 对齐预发环境 --------- Merge request URL: https://g-ldyi2063.coding.net/p/dev/d/modalDeploy/git/merge/4802 Co-authored-by: 康宇佳,shuohigh@gmail.com
153 lines
5.8 KiB
Python
153 lines
5.8 KiB
Python
from datetime import timedelta, datetime
|
||
|
||
|
||
class TimeDelta(timedelta):
|
||
@classmethod
|
||
def from_timedelta(cls, delta: timedelta) -> "TimeDelta":
|
||
return cls(days=delta.days, seconds=delta.seconds, microseconds=delta.microseconds)
|
||
|
||
@classmethod
|
||
def from_format_string(cls, format_string: str) -> "TimeDelta":
|
||
formated_time = datetime.strptime(format_string, "%H:%M:%S.%f")
|
||
return cls(hours=formated_time.hour, minutes=formated_time.minute, seconds=formated_time.second,
|
||
microseconds=formated_time.microsecond)
|
||
|
||
def toFormatStr(self) -> str:
|
||
return (datetime(year=2000, month=1, day=1) + self).strftime("%H:%M:%S.%f")[:-3]
|
||
|
||
|
||
def parse_time(time_str):
|
||
"""解析时间字符串为datetime对象,支持两种格式:HH:MM:SS.fff 和 MM:SS.fff"""
|
||
# 尝试按两种格式解析
|
||
try:
|
||
# 先尝试完整格式 HH:MM:SS.fff
|
||
return datetime.strptime(time_str, '%H:%M:%S.%f')
|
||
except ValueError:
|
||
try:
|
||
# 如果失败,尝试 MM:SS.fff 格式
|
||
dt = datetime.strptime(time_str, '%M:%S.%f')
|
||
# 将小时设为0,只保留分钟和秒
|
||
return datetime.combine(dt.date(), dt.time().replace(hour=0))
|
||
except ValueError:
|
||
try:
|
||
# 如果失败,尝试 MM:SS:fff 格式
|
||
dt = datetime.strptime(time_str, '%M:%S:%f')
|
||
# 将小时设为0,只保留分钟和秒
|
||
return datetime.combine(dt.date(), dt.time().replace(hour=0))
|
||
except ValueError:
|
||
# 如果失败,尝试 HH:MM:SS:fff 格式
|
||
return datetime.strptime(time_str, '%H:%M:%S:%f')
|
||
|
||
|
||
def format_time(dt):
|
||
"""将datetime对象格式化为时间字符串"""
|
||
return dt.strftime('%H:%M:%S.%f')[:-3] # 保留3位小数
|
||
|
||
|
||
def parse_timeline_item(item):
|
||
"""解析时间线项目,提取开始和结束时间"""
|
||
time_range, _ = item.split(' (', 1)
|
||
start_time_str, end_time_str = time_range.split(' - ')
|
||
return parse_time(start_time_str), parse_time(end_time_str)
|
||
|
||
|
||
def format_timeline_item(start_time, end_time, activity):
|
||
"""格式化时间线项目"""
|
||
return f"{format_time(start_time)} - {format_time(end_time)} ({activity})"
|
||
|
||
|
||
def merge_timeline_items(items):
|
||
"""合并相邻的时间线项目,保留不同的活动描述"""
|
||
if not items:
|
||
return []
|
||
|
||
# 解析所有项目
|
||
parsed_items = []
|
||
for item in items:
|
||
start_time, end_time = parse_timeline_item(item)
|
||
activity = item.split(' (', 1)[1].rstrip(')')
|
||
parsed_items.append((start_time, end_time, activity))
|
||
|
||
# 按开始时间排序
|
||
parsed_items.sort(key=lambda x: x[0])
|
||
|
||
# 合并相邻的时间段
|
||
merged_items = [parsed_items[0]]
|
||
for current in parsed_items[1:]:
|
||
last = merged_items[-1]
|
||
|
||
# 如果当前项目的开始时间与上一个项目的结束时间相邻或重叠
|
||
if current[0] <= last[1]:
|
||
# 更新结束时间为两个结束时间的最大值
|
||
new_end_time = max(last[1], current[1])
|
||
|
||
# 检查活动描述是否相同
|
||
if last[2] == current[2]:
|
||
# 活动描述相同,直接合并
|
||
merged_items[-1] = (last[0], new_end_time, last[2])
|
||
else:
|
||
# 活动描述不同,需要保留两个时间段
|
||
# 先分割上一个项目
|
||
if last[1] < current[1]:
|
||
# 当前项目的结束时间更晚,需要分割
|
||
merged_items[-1] = (last[0], current[0], last[2])
|
||
merged_items.append((current[0], new_end_time, current[2]))
|
||
else:
|
||
# 上一个项目的结束时间更晚,需要分割
|
||
merged_items[-1] = (last[0], current[0], last[2])
|
||
merged_items.append((current[0], current[1], current[2]))
|
||
merged_items.append((current[1], last[1], last[2]))
|
||
else:
|
||
# 不相邻,添加新项目
|
||
merged_items.append(current)
|
||
|
||
# 格式化回原始字符串格式
|
||
return [format_timeline_item(start, end, activity) for start, end, activity in merged_items]
|
||
|
||
|
||
def convert_time(time_str):
|
||
# 去除秒字段并转换为标准时间
|
||
parts = time_str.split(':')
|
||
if len(parts) == 3:
|
||
new_time_str = f"00:{parts[0]}:{parts[1]}.{parts[2].split('.')[1]}"
|
||
return new_time_str
|
||
return time_str
|
||
|
||
|
||
def merge_product_data(data, start_time_str, end_time_str):
|
||
"""合并相同产品的数据"""
|
||
start_time = parse_time(start_time_str)
|
||
end_time = parse_time(end_time_str)
|
||
duration = end_time - start_time
|
||
|
||
product_dict = {}
|
||
|
||
# 按产品名称分组
|
||
for item in data:
|
||
product = item["product"]
|
||
if product not in product_dict:
|
||
product_dict[product] = {"product": product, "timeline": []}
|
||
product_dict[product]["timeline"].extend(item["timeline"])
|
||
|
||
# 合并每个产品的时间线
|
||
for product in product_dict:
|
||
timeline = product_dict[product]["timeline"]
|
||
new_timeline = []
|
||
for item in timeline:
|
||
start, end = parse_timeline_item(item)
|
||
# 比较起始时间与时间差
|
||
if (start - datetime.min) > duration:
|
||
# 处理时间字符串
|
||
start_str = format_time(start)
|
||
end_str = format_time(end)
|
||
new_start_str = convert_time(start_str)
|
||
new_end_str = convert_time(end_str)
|
||
activity = item.split(' (', 1)[1].rstrip(')')
|
||
new_item = f"{new_start_str} - {new_end_str} ({activity})"
|
||
new_timeline.append(new_item)
|
||
else:
|
||
new_timeline.append(item)
|
||
product_dict[product]["timeline"] = merge_timeline_items(new_timeline)
|
||
|
||
# 返回合并后的列表
|
||
return list(product_dict.values()) |