第23章:字幕添加服务
字幕添加服务是剪映小助手的核心功能模块,负责将字幕内容添加到剪映草稿中。该服务支持批量字幕添加,提供了完整的字幕处理流程,包括字幕样式设置、关键词高亮、动画效果、轨道管理和时间轴控制等功能。
第23章:字幕添加服务
23.1 概述
字幕添加服务是剪映小助手的核心功能模块,负责将字幕内容添加到剪映草稿中。该服务支持批量字幕添加,提供了完整的字幕处理流程,包括字幕样式设置、关键词高亮、动画效果、轨道管理和时间轴控制等功能。
字幕添加服务采用模块化设计,将复杂的字幕处理逻辑封装成简单的API调用,用户只需要提供字幕文本和时间信息,系统就能自动完成字幕的创建、样式设置和添加操作。
23.2 核心功能
23.2.1 批量字幕添加
add_captions函数是字幕添加服务的主入口,负责处理批量字幕添加的完整流程。
核心实现
def add_captions(
draft_url: str,
captions: str,
text_color: str = "#ffffff",
border_color: Optional[str] = None,
alignment: int = 1,
alpha: float = 1.0,
font: Optional[str] = None,
font_size: int = 15,
letter_spacing: Optional[float] = None,
line_spacing: Optional[float] = None,
scale_x: float = 1.0,
scale_y: float = 1.0,
transform_x: int = 0,
transform_y: int = 0,
style_text: bool = False
) -> Tuple[str, str, List[str], List[str]]:
"""
批量添加字幕到剪映草稿的业务逻辑
Args:
draft_url: 草稿URL
captions: 字幕信息列表的JSON字符串,格式如下:
[
{
"start": 0, # 字幕开始时间(微秒)
"end": 10000000, # 字幕结束时间(微秒)
"text": "你好,剪映", # 字幕文本内容
"keyword": "好", # 关键词(用|分隔多个关键词),可选参数
"keyword_color": "#457616", # 关键词颜色,可选参数
"keyword_font_size": 15, # 关键词字体大小,可选参数
"font_size": 15, # 文本字体大小,可选参数
"in_animation": None, # 入场动画,可选参数
"out_animation": None, # 出场动画,可选参数
"loop_animation": None, # 循环动画,可选参数
"in_animation_duration": None, # 入场动画时长,可选参数
"out_animation_duration": None, # 出场动画时长,可选参数
"loop_animation_duration": None # 循环动画时长,可选参数
}
]
text_color: 文本颜色(十六进制),默认"#ffffff"
border_color: 边框颜色(十六进制),默认None
alignment: 文本对齐方式(0-5),默认1
alpha: 文本透明度(0.0-1.0),默认1.0
font: 字体名称,默认None
font_size: 字体大小,默认15
letter_spacing: 字间距,默认None
line_spacing: 行间距,默认None
scale_x: 水平缩放,默认1.0
scale_y: 垂直缩放,默认1.0
transform_x: 水平位移,默认0
transform_y: 垂直位移,默认0
style_text: 是否使用样式文本,默认False
Returns:
draft_url: 草稿URL
track_id: 字幕轨道ID
text_ids: 字幕ID列表
segment_ids: 字幕片段ID列表
Raises:
CustomException: 字幕添加失败
"""
logger.info(f"add_captions started, draft_url: {draft_url}, captions count: {len(json.loads(captions) if captions else [])}")
# 1. 提取草稿ID
draft_id = helper.get_url_param(draft_url, "draft_id")
if (not draft_id) or (draft_id not in DRAFT_CACHE):
logger.error(f"Invalid draft_url or draft not found in cache: {draft_url}")
raise CustomException(CustomError.INVALID_DRAFT_URL)
# 2. 解析字幕信息
caption_items = parse_captions_data(json_str=captions)
if len(caption_items) == 0:
logger.info(f"No caption info provided, draft_id: {draft_id}")
raise CustomError.INVALID_CAPTION_INFO
logger.info(f"Parsed {len(caption_items)} caption items")
# 3. 从缓存中获取草稿
script: ScriptFile = DRAFT_CACHE[draft_id]
# 4. 添加字幕轨道
track_name = f"caption_track_{helper.gen_unique_id()}"
script.add_track(track_type=TrackType.text, track_name=track_name)
logger.info(f"Added caption track: {track_name}")
# 5. 遍历字幕信息,添加字幕到草稿中的指定轨道,收集片段ID
segment_ids = []
text_ids = []
for i, caption in enumerate(caption_items):
try:
logger.info(f"Processing caption {i+1}/{len(caption_items)}, text: {caption['text'][:20]}...")
segment_id, text_id = add_caption_to_draft(
script, track_name,
caption=caption,
text_color=text_color,
border_color=border_color,
alignment=alignment,
alpha=alpha,
font=font,
font_size=font_size,
letter_spacing=letter_spacing,
line_spacing=line_spacing,
scale_x=scale_x,
scale_y=scale_y,
transform_x=transform_x,
transform_y=transform_y,
style_text=style_text
)
segment_ids.append(segment_id)
text_ids.append(text_id)
logger.info(f"Added caption {i+1}/{len(caption_items)}, segment_id: {segment_id}")
except Exception as e:
logger.error(f"Failed to add caption {i+1}/{len(caption_items)}, error: {str(e)}")
raise
# 6. 保存草稿
script.save()
logger.info(f"Draft saved successfully")
# 7. 获取当前字幕轨道ID
track_id = ""
for key in script.tracks.keys():
if script.tracks[key].name == track_name:
track_id = script.tracks[key].track_id
break
logger.info(f"Caption track created, draft_id: {draft_id}, track_id: {track_id}")
logger.info(f"add_captions completed successfully - draft_id: {draft_id}, track_id: {track_id}, captions_added: {len(caption_items)}")
return draft_url, track_id, text_ids, segment_ids
处理流程
- 参数验证:验证草稿URL和缓存状态
- 数据解析:解析和验证字幕信息JSON
- 轨道创建:添加新的字幕轨道
- 批量添加:遍历添加每个字幕到轨道
- 草稿保存:持久化草稿更改
- 信息返回:返回轨道ID、字幕ID和片段ID列表
23.2.2 单个字幕添加
add_caption_to_draft函数负责将单个字幕添加到指定的轨道中,支持样式设置和动画效果。
核心实现
def add_caption_to_draft(
script: ScriptFile,
track_name: str,
caption: dict,
text_color: str = "#ffffff",
border_color: Optional[str] = None,
alignment: int = 1,
alpha: float = 1.0,
font: Optional[str] = None,
font_size: int = 15,
letter_spacing: Optional[float] = None,
line_spacing: Optional[float] = None,
scale_x: float = 1.0,
scale_y: float = 1.0,
transform_x: int = 0,
transform_y: int = 0,
style_text: bool = False
) -> Tuple[str, str]:
"""
向剪映草稿中添加单个字幕
Args:
script: 草稿文件对象
track_name: 字幕轨道名称
caption: 字幕信息字典,包含以下字段:
start: 字幕开始时间(微秒)
end: 字幕结束时间(微秒)
text: 字幕文本内容
keyword: 关键词(用|分隔多个关键词),可选
keyword_color: 关键词颜色,可选
keyword_font_size: 关键词字体大小,可选
font_size: 文本字体大小,可选
in_animation: 入场动画,可选
out_animation: 出场动画,可选
loop_animation: 循环动画,可选
in_animation_duration: 入场动画时长,可选
out_animation_duration: 出场动画时长,可选
loop_animation_duration: 循环动画时长,可选
其他参数:字幕样式设置
Returns:
segment_id: 片段ID
text_id: 文本ID(material_id)
Raises:
CustomException: 添加字幕失败
"""
try:
# 1. 创建时间范围
caption_duration = caption['end'] - caption['start']
timerange = Timerange(start=caption['start'], duration=caption_duration)
# 2. 解析颜色
rgb_color = hex_to_rgb(text_color)
# 3. 创建文本样式
align_value: Literal[0, 1, 2] = 0
if alignment == 1:
align_value = 1
elif alignment == 2:
align_value = 2
text_style = TextStyle(
size=float(caption.get('font_size', font_size)),
color=rgb_color,
alpha=alpha,
align=align_value,
letter_spacing=int(letter_spacing) if letter_spacing is not None else 0,
line_spacing=int(line_spacing) if line_spacing is not None else 0,
auto_wrapping=True # 字幕默认开启自动换行
)
# 4. 创建图像调节设置
clip_settings = ClipSettings(
scale_x=scale_x,
scale_y=scale_y,
transform_x=float(transform_x) / script.width * 2, # 转换为半画布宽度单位
transform_y=float(transform_y) / script.height * 2 # 转换为半画布高度单位
)
# 5. 创建文本片段
text_segment = TextSegment(
text=caption['text'],
timerange=timerange,
style=text_style,
clip_settings=clip_settings
)
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: 处理关键词高亮(这需要更复杂的实现)
if caption.get('keyword'):
logger.info(f"Keyword highlighting specified but not implemented yet: {caption['keyword']}")
# 7. TODO: 处理动画效果(需要导入相应的动画类型)
if caption.get('in_animation'):
logger.info(f"In animation specified but not implemented yet: {caption['in_animation']}")
if caption.get('out_animation'):
logger.info(f"Out animation specified but not implemented yet: {caption['out_animation']}")
if caption.get('loop_animation'):
logger.info(f"Loop animation specified but not implemented yet: {caption['loop_animation']}")
# 8. 向指定轨道添加片段
script.add_segment(text_segment, track_name)
return text_segment.segment_id, text_segment.material_id
except CustomException:
logger.error(f"Add caption to draft failed, caption: {caption}")
raise
except Exception as e:
logger.error(f"Add caption to draft failed, error: {str(e)}")
raise CustomException(CustomError.CAPTION_ADD_FAILED)
23.2.3 字幕数据解析
parse_captions_data函数负责解析和验证字幕数据的JSON字符串,处理可选字段的默认值。
核心实现
def parse_captions_data(json_str: str) -> List[Dict[str, Any]]:
"""
解析字幕数据的JSON字符串,处理可选字段的默认值
Args:
json_str: 包含字幕数据的JSON字符串,格式如下:
[
{
"start": 0, # [必选] 字幕开始时间(微秒)
"end": 10000000, # [必选] 字幕结束时间(微秒)
"text": "你好,剪映", # [必选] 字幕文本内容
"keyword": "好", # [可选] 关键词(用|分隔多个关键词)
"keyword_color": "#457616", # [可选] 关键词颜色,默认"#ff7100"
"keyword_font_size": 15, # [可选] 关键词字体大小,默认15
"font_size": 15, # [可选] 文本字体大小,默认15
"in_animation": None, # [可选] 入场动画,默认None
"out_animation": None, # [可选] 出场动画,默认None
"loop_animation": None, # [可选] 循环动画,默认None
"in_animation_duration": None, # [可选] 入场动画时长,默认None
"out_animation_duration": None, # [可选] 出场动画时长,默认None
"loop_animation_duration": None # [可选] 循环动画时长,默认None
}
]
Returns:
包含字幕对象的数组,每个对象都处理了默认值
Raises:
CustomException: 当JSON格式错误或缺少必选字段时抛出
"""
try:
# 解析JSON字符串
data = json.loads(json_str)
except json.JSONDecodeError as e:
logger.error(f"JSON parse error: {e.msg}")
raise CustomException(CustomError.INVALID_CAPTION_INFO, f"JSON parse error: {e.msg}")
# 确保输入是列表
if not isinstance(data, list):
logger.error("captions should be a list")
raise CustomException(CustomError.INVALID_CAPTION_INFO, "captions should be a list")
result = []
for i, item in enumerate(data):
if not isinstance(item, dict):
logger.error(f"the {i}th item should be a dict")
raise CustomException(CustomError.INVALID_CAPTION_INFO, f"the {i}th item should be a dict")
# 检查必选字段
required_fields = ["start", "end", "text"]
missing_fields = [field for field in required_fields if field not in item]
if missing_fields:
logger.error(f"the {i}th item is missing required fields: {', '.join(missing_fields)}")
raise CustomException(CustomError.INVALID_CAPTION_INFO, f"the {i}th item is missing required fields: {', '.join(missing_fields)}")
# 创建处理后的对象,设置默认值
processed_item = {
"start": item["start"],
"end": item["end"],
"text": item["text"],
"keyword": item.get("keyword", None),
"keyword_color": item.get("keyword_color", "#ff7100"),
"keyword_font_size": item.get("keyword_font_size", 15),
"font_size": item.get("font_size", 15),
"in_animation": item.get("in_animation", None),
"out_animation": item.get("out_animation", None),
"loop_animation": item.get("loop_animation", None),
"in_animation_duration": item.get("in_animation_duration", None),
"out_animation_duration": item.get("out_animation_duration", None),
"loop_animation_duration": item.get("loop_animation_duration", None)
}
# 验证数值类型和范围
if not isinstance(processed_item["start"], (int, float)) or processed_item["start"] < 0:
logger.error(f"the {i}th item has invalid start time: {processed_item['start']}")
raise CustomException(CustomError.INVALID_CAPTION_INFO, f"the {i}th item has invalid start time")
if not isinstance(processed_item["end"], (int, float)) or processed_item["end"] <= processed_item["start"]:
logger.error(f"the {i}th item has invalid end time: {processed_item['end']}")
raise CustomException(CustomError.INVALID_CAPTION_INFO, f"the {i}th item has invalid end time")
if not isinstance(processed_item["text"], str) or len(processed_item["text"].strip()) == 0:
logger.error(f"the {i}th item has invalid text: {processed_item['text']}")
raise CustomException(CustomError.INVALID_CAPTION_INFO, f"the {i}th item has invalid text")
# 验证字体大小
if not isinstance(processed_item["font_size"], (int, float)) or processed_item["font_size"] <= 0:
processed_item["font_size"] = 15
if not isinstance(processed_item["keyword_font_size"], (int, float)) or processed_item["keyword_font_size"] <= 0:
processed_item["keyword_font_size"] = 15
result.append(processed_item)
logger.info(f"Successfully parsed {len(result)} caption items")
return result
23.3 数据模型设计
23.3.1 请求响应模型
字幕添加服务定义了清晰的数据模型:
class AddCaptionsRequest(BaseModel):
"""批量添加字幕请求参数"""
draft_url: str = Field(default="", description="草稿URL")
captions: str = Field(default="", description="字幕信息列表, 用JSON字符串表示")
text_color: str = Field(default="#ffffff", description="文本颜色(十六进制)")
border_color: Optional[str] = Field(default=None, description="边框颜色(十六进制)")
alignment: int = Field(default=1, ge=0, le=5, description="文本对齐方式(0-5)")
alpha: float = Field(default=1.0, ge=0.0, le=1.0, description="文本透明度(0.0-1.0)")
font: Optional[str] = Field(default=None, description="字体名称")
font_size: int = Field(default=15, ge=1, description="字体大小")
letter_spacing: Optional[float] = Field(default=None, description="字间距")
line_spacing: Optional[float] = Field(default=None, description="行间距")
scale_x: float = Field(default=1.0, description="水平缩放")
scale_y: float = Field(default=1.0, description="垂直缩放")
transform_x: int = Field(default=0, description="水平位移")
transform_y: int = Field(default=0, description="垂直位移")
style_text: bool = Field(default=False, description="是否使用样式文本")
class CaptionItem(BaseModel):
"""单个字幕信息"""
start: int = Field(..., description="字幕开始时间(微秒)")
end: int = Field(..., description="字幕结束时间(微秒)")
text: str = Field(..., description="字幕文本内容")
keyword: Optional[str] = Field(default=None, description="关键词(用|分隔多个关键词)")
keyword_color: str = Field(default="#ff7100", description="关键词颜色")
keyword_font_size: int = Field(default=15, ge=1, description="关键词字体大小")
font_size: int = Field(default=15, ge=1, description="文本字体大小")
in_animation: Optional[str] = Field(default=None, description="入场动画")
out_animation: Optional[str] = Field(default=None, description="出场动画")
loop_animation: Optional[str] = Field(default=None, description="循环动画")
in_animation_duration: Optional[int] = Field(default=None, description="入场动画时长")
out_animation_duration: Optional[int] = Field(default=None, description="出场动画时长")
loop_animation_duration: Optional[int] = Field(default=None, description="循环动画时长")
class AddCaptionsResponse(BaseModel):
"""添加字幕响应参数"""
draft_url: str = Field(default="", description="草稿URL")
track_id: str = Field(default="", description="字幕轨道ID")
text_ids: List[str] = Field(default=[], description="字幕ID列表")
segment_ids: List[str] = Field(default=[], description="字幕片段ID列表")
23.3.2 字幕参数配置
字幕添加服务支持以下参数配置:
| 参数名 | 类型 | 必选 | 默认值 | 取值范围 | 说明 |
|---|---|---|---|---|---|
| start | int | 是 | - | ≥0 | 字幕开始时间(微秒) |
| end | int | 是 | - | >start | 字幕结束时间(微秒) |
| text | string | 是 | - | - | 字幕文本内容 |
| keyword | string | 否 | None | - | 关键词(用 |
| keyword_color | string | 否 | “#ff7100” | - | 关键词颜色 |
相关资源
- GitHub代码仓库: https://github.com/Hommy-master/capcut-mate
- Gitee代码仓库: https://gitee.com/taohongmin-gitee/capcut-mate
- API文档地址: https://docs.jcaigc.cn
代码仓库地址
- GitHub:
https://github.com/Hommy-master/capcut-mate - Gitee:
https://gitee.com/taohongmin-gitee/capcut-mate
接口文档地址
- API文档地址:
https://docs.jcaigc.cn
| keyword_font_size | int | 否 | 15 | ≥1 | 关键词字体大小 |
| font_size | int | 否 | 15 | ≥1 | 文本字体大小 |
| in_animation | string | 否 | None | - | 入场动画 |
| out_animation | string | 否 | None | - | 出场动画 |
| loop_animation | string | 否 | None | - | 循环动画 |
| in_animation_duration | int | 否 | None | - | 入场动画时长(微秒) |
| out_animation_duration | int | 否 | None | - | 出场动画时长(微秒) |
| loop_animation_duration | int | 否 | None | - | 循环动画时长(微秒) |
23.4 字幕处理特性
23.4.1 颜色转换系统
字幕添加服务实现了十六进制颜色到RGB的转换:
def hex_to_rgb(hex_color: str) -> tuple:
"""
将十六进制颜色值转换为RGB三元组(0-1范围)
Args:
hex_color: 十六进制颜色值,如"#ffffff"或"ffffff"
Returns:
RGB三元组,取值范围为[0, 1]
"""
# 移除#号(如果存在)
hex_color = hex_color.lstrip('#')
# 确保是6位十六进制
if len(hex_color) != 6:
logger.warning(f"Invalid hex color format: {hex_color}, using white as default")
return (1.0, 1.0, 1.0)
try:
# 转换为RGB值(0-255)
r = int(hex_color[0:2], 16)
g = int(hex_color[2:4], 16)
b = int(hex_color[4:6], 16)
# 转换为0-1范围
return (r / 255.0, g / 255.0, b / 255.0)
except ValueError:
logger.warning(f"Invalid hex color format: {hex_color}, using white as default")
return (1.0, 1.0, 1.0)
23.4.2 文本样式设置
系统支持丰富的文本样式设置:
# 创建文本样式
text_style = TextStyle(
size=float(caption.get('font_size', font_size)),
color=rgb_color,
alpha=alpha,
align=align_value,
letter_spacing=int(letter_spacing) if letter_spacing is not None else 0,
line_spacing=int(line_spacing) if line_spacing is not None else 0,
auto_wrapping=True # 字幕默认开启自动换行
)
23.4.3 坐标转换系统
字幕位置采用智能坐标转换:
# 创建图像调节设置
clip_settings = ClipSettings(
scale_x=scale_x,
scale_y=scale_y,
transform_x=float(transform_x) / script.width * 2, # 转换为半画布宽度单位
transform_y=float(transform_y) / script.height * 2 # 转换为半画布高度单位
)
23.4.4 关键词高亮框架
系统预留了关键词高亮功能接口:
# TODO: 处理关键词高亮(这需要更复杂的实现)
if caption.get('keyword'):
logger.info(f"Keyword highlighting specified but not implemented yet: {caption['keyword']}")
23.4.5 动画效果框架
系统预留了丰富的动画效果接口:
# TODO: 处理动画效果(需要导入相应的动画类型)
if caption.get('in_animation'):
logger.info(f"In animation specified but not implemented yet: {caption['in_animation']}")
if caption.get('out_animation'):
logger.info(f"Out animation specified but not implemented yet: {caption['out_animation']}")
if caption.get('loop_animation'):
logger.info(f"Loop animation specified but not implemented yet: {caption['loop_animation']}")
23.5 缓存集成
字幕添加服务深度集成了草稿缓存机制:
# 从缓存获取草稿对象
script: ScriptFile = DRAFT_CACHE[draft_id]
# 操作完成后更新缓存
script.save()
23.6 错误处理
字幕添加服务实现了完善的错误处理机制:
try:
# 字幕添加逻辑
segment_id, text_id = add_caption_to_draft(
script, track_name, caption=caption,
text_color=text_color, border_color=border_color,
alignment=alignment, alpha=alpha, font=font,
font_size=font_size, letter_spacing=letter_spacing,
line_spacing=line_spacing, scale_x=scale_x,
scale_y=scale_y, transform_x=transform_x,
transform_y=transform_y, style_text=style_text
)
except CustomException:
logger.error(f"Add caption to draft failed, caption: {caption}")
raise
except Exception as e:
logger.error(f"Add caption to draft failed, error: {str(e)}")
raise CustomException(CustomError.CAPTION_ADD_FAILED)
23.7 日志记录
字幕添加服务提供了详细的日志记录:
logger.info(f"add_captions started, draft_url: {draft_url}, captions count: {len(json.loads(captions) if captions else [])}")
logger.info(f"Parsed {len(caption_items)} caption items")
logger.info(f"Added caption track: {track_name}")
logger.info(f"Processing caption {i+1}/{len(caption_items)}, text: {caption['text'][:20]}...")
logger.info(f"Added caption {i+1}/{len(caption_items)}, segment_id: {segment_id}")
logger.info(f"Draft saved successfully")
logger.info(f"Caption track created, draft_id: {draft_id}, track_id: {track_id}")
logger.info(f"add_captions completed successfully - draft_id: {draft_id}, track_id: {track_id}, captions_added: {len(caption_items)}")
23.8 性能优化
23.8.1 批量处理
字幕添加服务支持批量处理,减少I/O操作次数:
# 批量添加字幕
for i, caption in enumerate(caption_items):
segment_id, text_id = add_caption_to_draft(
script, track_name, caption=caption,
text_color=text_color, border_color=border_color,
alignment=alignment, alpha=alpha, font=font,
font_size=font_size, letter_spacing=letter_spacing,
line_spacing=line_spacing, scale_x=scale_x,
scale_y=scale_y, transform_x=transform_x,
transform_y=transform_y, style_text=style_text
)
segment_ids.append(segment_id)
text_ids.append(text_id)
23.8.2 缓存优化
利用草稿缓存机制,避免重复加载:
# 从缓存获取草稿
script: ScriptFile = DRAFT_CACHE[draft_id]
23.9 安全性考虑
23.9.1 输入验证
对所有输入参数进行严格验证:
# 验证时间范围
if not isinstance(processed_item["start"], (int, float)) or processed_item["start"] < 0:
logger.error(f"the {i}th item has invalid start time: {processed_item['start']}")
raise CustomException(CustomError.INVALID_CAPTION_INFO, f"the {i}th item has invalid start time")
if not isinstance(processed_item["end"], (int, float)) or processed_item["end"] <= processed_item["start"]:
logger.error(f"the {i}th item has invalid end time: {processed_item['end']}")
raise CustomException(CustomError.INVALID_CAPTION_INFO, f"the {i}th item has invalid end time")
# 验证文本内容
if not isinstance(processed_item["text"], str) or len(processed_item["text"].strip()) == 0:
logger.error(f"the {i}th item has invalid text: {processed_item['text']}")
raise CustomException(CustomError.INVALID_CAPTION_INFO, f"the {i}th item has invalid text")
# 验证字体大小
if not isinstance(processed_item["font_size"], (int, float)) or processed_item["font_size"] <= 0:
processed_item["font_size"] = 15
if not isinstance(processed_item["keyword_font_size"], (int, float)) or processed_item["keyword_font_size"] <= 0:
processed_item["keyword_font_size"] = 15
23.9.2 颜色安全
颜色转换过程中进行异常处理:
try:
# 转换为RGB值(0-255)
r = int(hex_color[0:2], 16)
g = int(hex_color[2:4], 16)
b = int(hex_color[4:6], 16)
# 转换为0-1范围
return (r / 255.0, g / 255.0, b / 255.0)
except ValueError:
logger.warning(f"Invalid hex color format: {hex_color}, using white as default")
return (1.0, 1.0, 1.0)
23.10 扩展性设计
23.10.1 关键词高亮扩展
关键词高亮采用预留接口设计,便于扩展:
# TODO: 处理关键词高亮(这需要更复杂的实现)
if caption.get('keyword'):
logger.info(f"Keyword highlighting specified but not implemented yet: {caption['keyword']}")
23.10.2 动画效果扩展
动画效果支持多种类型,易于扩展:
# TODO: 处理动画效果(需要导入相应的动画类型)
if caption.get('in_animation'):
logger.info(f"In animation specified but not implemented yet: {caption['in_animation']}")
if caption.get('out_animation'):
logger.info(f"Out animation specified but not implemented yet: {caption['out_animation']}")
if caption.get('loop_animation'):
logger.info(f"Loop animation specified but not implemented yet: {caption['loop_animation']}")
23.10.3 样式参数扩展
字幕参数采用字典结构,便于添加新参数:
processed_item = {
"start": item["start"],
"end": item["end"],
"text": item["text"],
"keyword": item.get("keyword", None),
"keyword_color": item.get("keyword_color", "#ff7100"),
"keyword_font_size": item.get("keyword_font_size", 15),
"font_size": item.get("font_size", 15),
# 可以轻松添加新参数
}
23.11 总结
字幕添加服务提供了完整的字幕处理解决方案,具有以下特点:
- 功能完整:支持批量字幕添加、单个字幕处理、样式设置和动画效果
- 样式丰富:支持文本颜色、透明度、字体大小、对齐方式、字间距、行间距等多种样式参数
- 关键词支持:预留了关键词高亮功能接口,支持关键词颜色和字体大小设置
- 动画框架:预留了入场动画、出场动画、循环动画的效果接口
- 坐标智能:实现了像素坐标到画布坐标的智能转换
- 颜色转换:支持十六进制颜色到RGB的智能转换
- 错误处理:完善的异常处理和错误恢复机制
- 性能优化:批量处理、缓存优化和异步处理
- 扩展性强:插件式动画效果设计和灵活的参数结构
- 安全可靠:输入验证和异常处理保护
该服务为剪映小助手提供了强大的字幕处理能力,是视频编辑功能的重要组成部分,特别是在制作教学视频、解说视频、字幕翻译等场景中发挥重要作用。
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)