mirror of
https://github.com/Hommy-master/capcut-mate.git
synced 2026-08-28 23:27:50 +08:00
添加关键词颜色。
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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字符串,处理可选字段的默认值
|
||||
|
||||
@@ -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()
|
||||
Reference in New Issue
Block a user