通过扣子官方语音合成开发的速推版剪映小助手时间线插件
2026-04-07 11:47:17 10 分享链接 开发笔记 扣子插件
扣子工作流javascript代码
// 类型定义(扣子环境已内置,仅作提示)
interface Args {
params: {
durations: number[]; // 各音频时长(秒)
links: string[]; // 音频链接列表
medias: Array<{ // 媒体索引映射
index: number;
start: number;
end: number;
}>;
};
}
interface TimeLineItem {
start: number; // 起始时间(微秒)
end: number; // 结束时间(微秒)
}
interface Output {
all_timelines: TimeLineItem[]; // 总时长时间线
timelines: TimeLineItem[]; // 单个音频时间线
media_timelines: TimeLineItem[]; // 按medias分组的时间线
}
async function main({ params }: Args): Promise<Output> {
// 1. 获取输入参数并兜底处理
const durations = params.durations || [];
const links = params.links || [];
const medias = params.medias || [];
// 2. 核心验证:durations与links长度必须一致
if (durations.length !== links.length) {
throw new Error(`参数验证失败:durations长度(${durations.length})与links长度(${links.length})不一致`);
}
// 3. 常量定义:秒转微秒(1秒 = 1000000 微秒)
const SEC_TO_US = 1000000;
// 4. 计算单个音频的时间线(timelines)
const timelines: TimeLineItem[] = [];
let currentStart = 0; // 累计起始时间(微秒)
durations.forEach((durationSec) => {
// 转换时长为微秒(避免浮点精度问题,先乘1000000再取整)
const durationUs = Math.round(durationSec * SEC_TO_US);
const end = currentStart + durationUs;
timelines.push({
start: currentStart,
end: end
});
// 更新下一个音频的起始时间
currentStart = end;
});
// 5. 计算总时长时间线(all_timelines)
const allTimelines: TimeLineItem[] = [];
if (timelines.length > 0) {
allTimelines.push({
start: 0,
end: timelines[timelines.length - 1].end // 总结束时间 = 最后一个音频的结束时间
});
} else {
allTimelines.push({ start: 0, end: 0 }); // 空数据兜底
}
// 6. 计算按medias分组的时间线(media_timelines)
const mediaTimelines: TimeLineItem[] = [];
medias.forEach((media) => {
const { start: linkStartIdx, end: linkEndIdx } = media;
// 边界校验:确保medias的start/end在links索引范围内
if (linkStartIdx < 0 || linkEndIdx >= links.length || linkStartIdx > linkEndIdx) {
throw new Error(`medias索引越界:index=${media.index} 的start(${linkStartIdx})/end(${linkEndIdx})超出links范围`);
}
// 取分组第一个音频的start作为media的start
const mediaStart = timelines[linkStartIdx].start;
// 取分组最后一个音频的end作为media的end
const mediaEnd = timelines[linkEndIdx].end;
mediaTimelines.push({
start: mediaStart,
end: mediaEnd
});
});
// 7. 构建最终输出
const ret: Output = {
all_timelines: allTimelines,
timelines: timelines,
media_timelines: mediaTimelines
};
return ret;
}输入(input)
{
"durations": [
0.525,
0.778,
1.085,
0.665,
0.865,
0.865,
0.685,
1.078,
0.738,
1.151,
0.985,
1.631,
2.418,
0.551,
1.365,
0.931,
0.771
],
"links": [
"https://lf3-appstore-sign.oceancloudapi.com/ocean-cloud-tos/VolcanoUserVoice/speech_7481299960424759350_d042d4cd-30cf-4230-afd0-43798f246c2f.mp3?lk3s=da27ec82&x-expires=1775640956&x-signature=DowjhJ3RpP47Zs%2FBDIgmxhd7NKk%3D",
"https://lf9-appstore-sign.oceancloudapi.com/ocean-cloud-tos/VolcanoUserVoice/speech_7481299960424759350_339e3ede-07e8-4fb5-b83f-b1ab53082dd9.mp3?lk3s=da27ec82&x-expires=1775640956&x-signature=YWEWUNZkYUC%2FfO0Txl4dCrC7orM%3D",
"https://lf26-appstore-sign.oceancloudapi.com/ocean-cloud-tos/VolcanoUserVoice/speech_7481299960424759350_533384b9-7503-438b-ad06-fadef1be4932.mp3?lk3s=da27ec82&x-expires=1775640956&x-signature=%2F%2BiYuE3Di%2F382iUQYMmO%2BNsQUdQ%3D",
"https://lf6-appstore-sign.oceancloudapi.com/ocean-cloud-tos/VolcanoUserVoice/speech_7481299960424759350_020acb28-0295-409a-8447-1e5a93cc32e0.mp3?lk3s=da27ec82&x-expires=1775640957&x-signature=wxNiEWbQgrwSTnS1Vg0zOzFfzwU%3D",
"https://lf3-appstore-sign.oceancloudapi.com/ocean-cloud-tos/VolcanoUserVoice/speech_7481299960424759350_d6d00e0a-2c8b-4852-9b9e-c0082a579fcf.mp3?lk3s=da27ec82&x-expires=1775640957&x-signature=0TbZXeTH9tL3mIKv3b44uHRGTPA%3D",
"https://lf26-appstore-sign.oceancloudapi.com/ocean-cloud-tos/VolcanoUserVoice/speech_7481299960424759350_391e021d-8ed9-4864-b1ff-3f45a4751816.mp3?lk3s=da27ec82&x-expires=1775640957&x-signature=ZvrO2kPJ8dZ8XCKdcoBHS4VWbXw%3D",
"https://lf6-appstore-sign.oceancloudapi.com/ocean-cloud-tos/VolcanoUserVoice/speech_7481299960424759350_720efc5e-64c8-4faa-9c9a-a50e352757b4.mp3?lk3s=da27ec82&x-expires=1775640957&x-signature=2W1jhRMzAYttZFk8IzZx%2B1tzgUY%3D",
"https://lf9-appstore-sign.oceancloudapi.com/ocean-cloud-tos/VolcanoUserVoice/speech_7481299960424759350_fb20945c-b7a3-4e8e-92c0-2aaec62eca7c.mp3?lk3s=da27ec82&x-expires=1775640958&x-signature=RURiqbqYU%2B1S0l9gexvp24CqeyU%3D",
"https://lf6-appstore-sign.oceancloudapi.com/ocean-cloud-tos/VolcanoUserVoice/speech_7481299960424759350_acd40bef-166a-43c8-9a79-40e90c78483c.mp3?lk3s=da27ec82&x-expires=1775640958&x-signature=jUVAJsYgPQg2nmnlmaDEuOBLtD4%3D",
"https://lf6-appstore-sign.oceancloudapi.com/ocean-cloud-tos/VolcanoUserVoice/speech_7481299960424759350_164b54d2-db1e-4c66-9271-7f14ce1b675c.mp3?lk3s=da27ec82&x-expires=1775640958&x-signature=vZrcziKx91EwI0comDVneW8heQA%3D",
"https://lf26-appstore-sign.oceancloudapi.com/ocean-cloud-tos/VolcanoUserVoice/speech_7481299960424759350_078634b3-1dad-4fb5-98a2-58cc41c15b20.mp3?lk3s=da27ec82&x-expires=1775640959&x-signature=YR%2Fm7235kIm%2FIFS07fjZg%2BJO1yc%3D",
"https://lf9-appstore-sign.oceancloudapi.com/ocean-cloud-tos/VolcanoUserVoice/speech_7481299960424759350_98d041e1-c8fe-46d9-aa6d-89e865102efb.mp3?lk3s=da27ec82&x-expires=1775640959&x-signature=vmIMPc87KcZxBIAX9D5gS6Kw4yE%3D",
"https://lf26-appstore-sign.oceancloudapi.com/ocean-cloud-tos/VolcanoUserVoice/speech_7481299960424759350_fe23dcf8-7088-4156-8ef7-a5fb1395595f.mp3?lk3s=da27ec82&x-expires=1775640960&x-signature=hnBP7VQmDD6ljTITQM4lMRlsDts%3D",
"https://lf3-appstore-sign.oceancloudapi.com/ocean-cloud-tos/VolcanoUserVoice/speech_7481299960424759350_aa4ac4d8-343e-4123-ab66-6c6e3758fa22.mp3?lk3s=da27ec82&x-expires=1775640960&x-signature=SrJfa8v8qp4SlCanmMhcmNdkJno%3D",
"https://lf9-appstore-sign.oceancloudapi.com/ocean-cloud-tos/VolcanoUserVoice/speech_7481299960424759350_a3772140-2e47-4620-907a-c29c95eebdeb.mp3?lk3s=da27ec82&x-expires=1775640960&x-signature=9h1ZoDG9bnfswsbnuCL6FYDLCO8%3D",
"https://lf3-appstore-sign.oceancloudapi.com/ocean-cloud-tos/VolcanoUserVoice/speech_7481299960424759350_e81b91bd-c95c-4024-939d-926a78d03c04.mp3?lk3s=da27ec82&x-expires=1775640960&x-signature=ghRF3Cl790jv%2BYIo6siC4aJwnHY%3D",
"https://lf6-appstore-sign.oceancloudapi.com/ocean-cloud-tos/VolcanoUserVoice/speech_7481299960424759350_6d804e9c-1f85-40a8-8a26-9b76dc396b62.mp3?lk3s=da27ec82&x-expires=1775640962&x-signature=Rupknj8zFcndYDvEjHybn%2F32rDs%3D"
],
"medias": [
{
"end": 5,
"index": 0,
"start": 0
},
{
"end": 11,
"index": 1,
"start": 6
},
{
"end": 12,
"index": 2,
"start": 12
},
{
"end": 16,
"index": 3,
"start": 13
}
]
}输出(output)
{
"all_timelines": [
{
"end": 17087000,
"start": 0
}
],
"media_timelines": [
{
"end": 4783000,
"start": 0
},
{
"end": 11051000,
"start": 4783000
},
{
"end": 13469000,
"start": 11051000
},
{
"end": 17087000,
"start": 13469000
}
],
"timelines": [
{
"end": 525000,
"start": 0
},
{
"end": 1303000,
"start": 525000
},
{
"end": 2388000,
"start": 1303000
},
{
"end": 3053000,
"start": 2388000
},
{
"end": 3918000,
"start": 3053000
},
{
"end": 4783000,
"start": 3918000
},
{
"end": 5468000,
"start": 4783000
},
{
"end": 6546000,
"start": 5468000
},
{
"end": 7284000,
"start": 6546000
},
{
"end": 8435000,
"start": 7284000
},
{
"end": 9420000,
"start": 8435000
},
{
"end": 11051000,
"start": 9420000
},
{
"end": 13469000,
"start": 11051000
},
{
"end": 14020000,
"start": 13469000
},
{
"end": 15385000,
"start": 14020000
},
{
"end": 16316000,
"start": 15385000
},
{
"end": 17087000,
"start": 16316000
}
]
}
最近更新
- 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 短视频分镜脚本之画面元素编写规则