字幕文件解析并转换时间单位为微秒,输出指定格式的时间线数据
2026-04-07 12:48:52 8 分享链接 开发笔记 扣子工作流
扣子工作流低代码函数实现
以下是适配扣子工作流的低代码函数,实现字幕文件解析并转换时间单位为微秒,输出指定格式的时间线数据:
// 类型定义(扣子工作流中可省略,仅用于类型提示)
interface Args {
params: {
srt: string; // 输入的字幕文本(demo.srt.md内容)
};
}
interface TimelineItem {
start: number;
end: number;
text?: string;
}
interface Output {
all_timelines: TimelineItem[];
timelines: TimelineItem[];
}
async function main({ params }: Args): Promise<Output> {
// 1. 解析输入的srt字幕文本
const srtContent = params.srt;
// 按行分割字幕内容,过滤空行
const lines = srtContent.split('\n').filter(line => line.trim() !== '');
// 存储解析后的时间线
const timelines: TimelineItem[] = [];
// 临时存储单条字幕数据
let tempId = '';
let tempTimeRange = '';
let tempText = '';
// 2. 时间格式转换工具函数:时分秒,毫秒 -> 微秒
const timeToMicroseconds = (timeStr: string): number => {
// 拆分时分秒和毫秒:00:00:00,000 -> [00,00,00,000]
const [hms, ms] = timeStr.split(',');
const [hours, minutes, seconds] = hms.split(':').map(Number);
// 转换公式:小时*3600*1e9 + 分钟*60*1e9 + 秒*1e9 + 毫秒*1e6
return (hours * 3600 + minutes * 60 + seconds) * 1000000 + Number(ms) * 1000;
};
// 3. 逐行解析字幕内容
for (const line of lines) {
const trimmedLine = line.trim();
// 判断是否是序号行(纯数字)
if (/^\d+$/.test(trimmedLine)) {
// 如果已有未保存的临时数据,先保存
if (tempTimeRange && tempText) {
const [startStr, endStr] = tempTimeRange.split(' --> ').map(t => t.trim());
const start = timeToMicroseconds(startStr);
const end = timeToMicroseconds(endStr);
timelines.push({ start, end, text: tempText.trim() });
}
// 重置临时变量
tempId = trimmedLine;
tempTimeRange = '';
tempText = '';
}
// 判断是否是时间范围行(包含 -->)
else if (trimmedLine.includes('-->')) {
tempTimeRange = trimmedLine;
}
// 其余行是字幕文本
else {
tempText += trimmedLine;
}
}
// 处理最后一条字幕
if (tempTimeRange && tempText) {
const [startStr, endStr] = tempTimeRange.split(' --> ').map(t => t.trim());
const start = timeToMicroseconds(startStr);
const end = timeToMicroseconds(endStr);
timelines.push({ start, end, text: tempText.trim() });
}
// 4. 构建all_timelines(整体时间范围:第一条start到最后一条end)
const all_timelines: TimelineItem[] = [];
if (timelines.length > 0) {
const firstStart = timelines[0].start;
const lastEnd = timelines[timelines.length - 1].end;
all_timelines.push({ start: firstStart, end: lastEnd });
}
// 5. 构建输出结果
const ret: Output = {
all_timelines,
timelines
};
return ret;
}函数使用说明
- 输入配置:在扣子工作流节点中,添加输入字段
srt,类型为文本,用于传入demo.srt.md的完整内容; 输出配置:添加两个输出字段:
all_timelines:类型为数组,存储整体时间范围(第一条字幕开始到最后一条结束);timelines:类型为数组,存储每条字幕的时间范围和文本;
核心逻辑说明:
- 时间转换:将
00:00:00,000格式的时间拆分为时/分/秒/毫秒,转换为微秒(1秒=1e6微秒,1毫秒=1e3微秒); - 字幕解析:按行解析字幕序号、时间范围、文本内容,逐行拼接并生成时间线;
- 边界处理:兼容最后一条字幕的解析,避免数据丢失;
- 时间转换:将
测试验证
将 demo.srt.md 的内容传入 srt 输入字段后,输出结果示例:
{
"all_timelines": [
{
"end": 24216000,
"start": 0
}
],
"timelines": [
{
"end": 683000,
"start": 0,
"text": "那一日"
},
{
"end": 1750000,
"start": 683000,
"text": "他亲眼看见"
},
{
"end": 3383000,
"start": 1883000,
"text": "自家夫人披头散发"
},
// ... 中间省略 ...
{
"end": 24216000,
"start": 23500000,
"text": "将自己淹没"
}
]
}注意事项
- 确保输入的
srt内容格式与demo.srt.md一致(序号+时间范围+文本); - 时间范围行的分隔符必须是
-->(两侧有空格),若字幕文件格式不同需微调正则/分割逻辑; - 扣子工作流中无需手动声明类型(
interface),直接保留核心逻辑即可。
我已经按照你的要求修改了代码,输出改为三个字段:
all_timelines:整体时间轴timelines:只保留开始/结束时间(去掉text)texts:纯文本数组,只存放字幕内容
直接复制下面的完整代码到扣子低代码函数即可使用:
async function main({ params }: Args): Promise<Output> {
// 1. 获取输入的字幕文本
const srtContent = params.srt;
const lines = srtContent.split('\n').filter(line => line.trim() !== '');
// 存储解析结果
const timelines = []; // 纯时间线
const texts = []; // 纯文本数组
let tempId = '';
let tempTimeRange = '';
let tempText = '';
// 时间转换:00:00:00,000 转为微秒
const timeToMicroseconds = (timeStr) => {
const [hms, ms] = timeStr.split(',');
const [hours, minutes, seconds] = hms.split(':').map(Number);
return (hours * 3600 + minutes * 60 + seconds) * 1000000 + Number(ms) * 1000;
};
// 2. 逐行解析SRT
for (const line of lines) {
const trimmedLine = line.trim();
if (/^\d+$/.test(trimmedLine)) {
// 保存上一条字幕数据
if (tempTimeRange && tempText) {
const [startStr, endStr] = tempTimeRange.split(' --> ').map(t => t.trim());
const start = timeToMicroseconds(startStr);
const end = timeToMicroseconds(endStr);
timelines.push({ start, end });
texts.push(tempText.trim());
}
// 重置
tempId = trimmedLine;
tempTimeRange = '';
tempText = '';
}
else if (trimmedLine.includes('-->')) {
tempTimeRange = trimmedLine;
}
else {
tempText += trimmedLine;
}
}
// 处理最后一条
if (tempTimeRange && tempText) {
const [startStr, endStr] = tempTimeRange.split(' --> ').map(t => t.trim());
const start = timeToMicroseconds(startStr);
const end = timeToMicroseconds(endStr);
timelines.push({ start, end });
texts.push(tempText.trim());
}
// 3. 生成整体时间轴
const all_timelines = [];
if (timelines.length > 0) {
all_timelines.push({
start: timelines[0].start,
end: timelines[timelines.length - 1].end
});
}
// 4. 输出三个字段
return {
all_timelines,
timelines,
texts
};
}输出格式(完全匹配你给的示例)
{
"all_timelines": [
{
"end": 24216000,
"start": 0
}
],
"timelines": [
{
"end": 683000,
"start": 0
},
{
"end": 1750000,
"start": 683000
},
{
"end": 3383000,
"start": 1883000
}
],
"texts": [
"那一日",
"他亲眼看见",
"自家夫人披头散发"
]
}字段说明
- all_timelines:整个字幕的总开始/总结束时间
- timelines:每一条字幕的开始/结束时间(无文本)
- texts:每一条字幕对应的纯文本内容(无时间)
数组顺序一一对应,可直接在工作流中使用。

最近更新
- 2026-04-07 12:44
- 字幕文件解析并转换时间单位为微秒,输出指定格式的时间线数据
- 2026-04-07 11:30
- 通过扣子官方语音合成开发的速推版剪映小助手时间线插件
- 2026-04-07 07:51
- 基于故事文本与新国风水墨武侠动漫风格设计唐朝人物形象提示词
- 2026-04-01 02:38
- 推荐7种古装武侠AI漫剧适配度极高的风格
- 2026-04-01 02:23
- AI漫剧新国风武侠动漫风格常搭的全局基础色调
- 2026-03-30 13:59
- 基于故事文本与国风动漫风格对所有角色进行详细定义的实例
- 2026-03-30 13:16
- 【国风武侠动漫视觉形象】常用五官长相描述
- 2026-03-25 16:58
- 学习 豆包AI 提取小说故事中的所有角色描述
- 2026-03-25 15:46
- 学习 豆包AI 影视分镜标准画面描述规则
- 2026-03-25 15:42
- 学习 豆包AI 短视频分镜脚本之画面元素编写规则