添加关键词颜色。

This commit is contained in:
Hommy
2025-12-04 18:18:33 +08:00
parent c9e134e1e3
commit 2d25f7f3f3
3 changed files with 163 additions and 22 deletions
+31 -20
View File
@@ -4,7 +4,7 @@ import json
import uuid
from copy import deepcopy
from typing import Dict, Tuple, Any
from typing import Dict, Tuple, Any, List
from typing import Union, Optional, Literal
from .time_util import Timerange, tim
@@ -273,6 +273,9 @@ class TextSegment(VisualSegment):
"""文本气泡效果, 在放入轨道时加入素材列表中"""
effect: Optional[TextEffect]
"""文本花字效果, 在放入轨道时加入素材列表中, 目前仅支持一部分花字效果"""
extra_styles: List[Dict[str, Any]]
"""额外的文本样式,用于关键词高亮等功能"""
def __init__(self, text: str, timerange: Timerange, *,
font: Optional[FontType] = None,
@@ -304,6 +307,7 @@ class TextSegment(VisualSegment):
self.bubble = None
self.effect = None
self.extra_styles = [] # 初始化额外样式列表
@classmethod
def create_from_template(cls, text: str, timerange: Timerange, template: "TextSegment") -> "TextSegment":
@@ -312,6 +316,7 @@ class TextSegment(VisualSegment):
border=deepcopy(template.border), background=deepcopy(template.background),
shadow=deepcopy(template.shadow))
new_segment.font = deepcopy(template.font)
new_segment.extra_styles = deepcopy(template.extra_styles)
# 处理动画等
if template.animations_instance:
@@ -392,27 +397,33 @@ class TextSegment(VisualSegment):
if self.shadow:
check_flag |= 32
content_json = {
"styles": [
{
"fill": {
# 创建基础样式
base_style = {
"fill": {
"alpha": 1.0,
"content": {
"render_type": "solid",
"solid": {
"alpha": 1.0,
"content": {
"render_type": "solid",
"solid": {
"alpha": 1.0,
"color": list(self.style.color)
}
}
},
"range": [0, len(self.text)],
"size": self.style.size,
"bold": self.style.bold,
"italic": self.style.italic,
"underline": self.style.underline,
"strokes": [self.border.export_json()] if self.border else []
"color": list(self.style.color)
}
}
],
},
"range": [0, len(self.text)],
"size": self.style.size,
"bold": self.style.bold,
"italic": self.style.italic,
"underline": self.style.underline,
"strokes": [self.border.export_json()] if self.border else []
}
# 合并基础样式和额外样式
styles = [base_style]
if self.extra_styles:
styles.extend(self.extra_styles)
content_json = {
"styles": styles,
"text": self.text
}
if self.font:
+59 -2
View File
@@ -238,9 +238,13 @@ def add_caption_to_draft(
logger.info(f"Created text segment, material_id: {text_segment.material_id}")
logger.info(f"Text segment details - start: {caption['start']}, duration: {caption_duration}, text: {caption['text'][:50]}")
# 6. TODO: 处理关键词高亮(这需要更复杂的实现)
# 6. 处理关键词高亮
if caption.get('keyword'):
logger.info(f"Keyword highlighting specified but not implemented yet: {caption['keyword']}")
keyword_color = caption.get('keyword_color', '#ff7100') # 默认橙色
keyword_rgb_color = hex_to_rgb(keyword_color)
# 应用关键词颜色到文本样式中
apply_keyword_highlight(text_segment, caption['keyword'], keyword_rgb_color)
logger.info(f"Applied keyword highlighting: {caption['keyword']} with color {keyword_color}")
# 7. TODO: 处理动画效果(需要导入相应的动画类型)
if caption.get('in_animation'):
@@ -270,6 +274,59 @@ def add_caption_to_draft(
raise CustomException(CustomError.CAPTION_ADD_FAILED)
def apply_keyword_highlight(text_segment: TextSegment, keywords: str, keyword_color: tuple):
"""
应用关键词高亮到文本片段
Args:
text_segment: 文本片段对象
keywords: 关键词字符串,用'|'分隔多个关键词
keyword_color: 关键词颜色的RGB元组 (0-1范围)
"""
# 分割关键词
keyword_list = keywords.split('|')
text = text_segment.text
# 为每个关键词创建高亮样式
for keyword in keyword_list:
keyword = keyword.strip()
if not keyword:
continue
# 查找所有匹配的关键词位置
start_pos = 0
while start_pos < len(text):
start_pos = text.find(keyword, start_pos)
if start_pos == -1:
break
end_pos = start_pos + len(keyword)
# 创建关键词高亮样式
highlight_style = {
"fill": {
"alpha": 1.0,
"content": {
"render_type": "solid",
"solid": {
"alpha": 1.0,
"color": list(keyword_color) # 使用关键词颜色
}
}
},
"range": [start_pos, end_pos],
"size": text_segment.style.size,
"bold": text_segment.style.bold,
"italic": text_segment.style.italic,
"underline": text_segment.style.underline,
"strokes": [text_segment.border.export_json()] if text_segment.border else []
}
# 添加到文本片段的额外样式中
text_segment.extra_styles.append(highlight_style)
start_pos = end_pos
def parse_captions_data(json_str: str) -> List[Dict[str, Any]]:
"""
解析字幕数据的JSON字符串,处理可选字段的默认值
+73
View File
@@ -0,0 +1,73 @@
import requests
import json
import time
def test_caption_keywords():
"""测试字幕关键词高亮功能"""
# 1. 先创建一个草稿
create_draft_url = "http://localhost:8000/v1/create_draft"
create_draft_data = {
"width": 1920,
"height": 1080
}
try:
print("Creating draft...")
create_response = requests.post(create_draft_url, json=create_draft_data)
if create_response.status_code != 200:
print(f"Failed to create draft: {create_response.status_code}")
print(create_response.text)
return
draft_url = create_response.json()["draft_url"]
print(f"Draft created successfully: {draft_url}")
# 2. 添加带关键词高亮的字幕
add_captions_url = "http://localhost:8000/v1/add_captions"
captions = [
{
"start": 0,
"end": 5000000, # 5秒
"text": "欢迎使用剪映字幕功能",
"keyword": "剪映|功能", # 关键词
"keyword_color": "#ff0000" # 红色高亮
},
{
"start": 5000000,
"end": 10000000, # 10秒
"text": "这是一个测试字幕",
"keyword": "测试",
"keyword_color": "#00ff00" # 绿色高亮
}
]
add_captions_data = {
"draft_url": draft_url,
"captions": json.dumps(captions),
"text_color": "#ffffff", # 默认白色文本
"font_size": 16
}
print("Adding captions with keyword highlighting...")
add_response = requests.post(add_captions_url, json=add_captions_data)
if add_response.status_code == 200:
result = add_response.json()
print(f"Captions added successfully!")
print(f"Track ID: {result['track_id']}")
print(f"Text IDs: {result['text_ids']}")
print(f"Segment IDs: {result['segment_ids']}")
print(f"Draft URL: {result['draft_url']}")
else:
print(f"Failed to add captions: {add_response.status_code}")
print(add_response.text)
except Exception as e:
print(f"Error occurred: {e}")
print("Make sure the server is running on http://localhost:8000")
if __name__ == "__main__":
test_caption_keywords()