transcript_to_video.workflow.json 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. {
  2. "name": "transcript_to_video",
  3. "displayName": "逐字稿AI视频生成",
  4. "description": "端到端编排:从输入逐字稿文本,到AI拆分镜脚本、批量生成视频素材、汇总输出视频URL列表+SRT字幕文件。覆盖分镜生成、文生视频/图生视频、任务轮询、结果汇总的完整链路。",
  5. "version": "1.0.0",
  6. "input": {
  7. "type": "object",
  8. "required": ["transcript"],
  9. "properties": {
  10. "transcript": {
  11. "type": "string",
  12. "description": "逐字稿全文(中文),将被AI拆分为分镜段",
  13. "example": "回到开头那个数字,500美元。这个数字之所以让人震撼不是因为它小,而是因为它背后站着的是一个人用了几年的时间在没有任何文档没有任何团队支援的黑暗中..."
  14. },
  15. "segmentDuration": {
  16. "type": "number",
  17. "description": "每段目标时长(秒),影响分镜拆分粒度",
  18. "default": 15
  19. },
  20. "videoModel": {
  21. "type": "string",
  22. "enum": ["720p", "1080p", "pro"],
  23. "description": "视频生成模型:720p(默认,性价比最高) / 1080p(高清) / pro(最高质量)",
  24. "default": "720p"
  25. },
  26. "videoMethod": {
  27. "type": "string",
  28. "enum": ["text2video", "img2video"],
  29. "description": "text2video=纯文生视频(快速省钱),img2video=先生图再图生视频(效果更可控)",
  30. "default": "text2video"
  31. },
  32. "aspectRatio": {
  33. "type": "string",
  34. "enum": ["16:9", "9:16", "1:1", "4:3"],
  35. "description": "视频画面比例,16:9横屏(默认) / 9:16竖屏(抖音) / 1:1方形",
  36. "default": "16:9"
  37. },
  38. "frames": {
  39. "type": "integer",
  40. "enum": [121, 241],
  41. "description": "视频帧数:121=5秒(默认) / 241=10秒",
  42. "default": 121
  43. }
  44. }
  45. },
  46. "stages": [
  47. {
  48. "id": "stage_1",
  49. "name": "AI分镜脚本生成",
  50. "description": "Agent将逐字稿拆分为分镜JSON数组 + SRT字幕文件",
  51. "parallel": false,
  52. "steps": [
  53. {
  54. "id": "1.1",
  55. "name": "逐字稿拆分为分镜脚本",
  56. "type": "ai",
  57. "aiConfig": {
  58. "systemPrompt": "你是专业的视频分镜脚本编写专家。将逐字稿拆分为分镜段,每段约40-45个中文字(约15秒语速)。为每段生成英文视频生成提示词(prompt),描述画面内容、镜头类型、氛围和画质。prompt必须是英文,要具体、富有画面感、适合AI视频生成。",
  59. "userPromptTemplate": "请将以下逐字稿拆分为分镜脚本,每段约{{input.segmentDuration}}秒(约40-45个中文字)。\n\n逐字稿:\n{{input.transcript}}\n\n请输出两部分:\n\n**Part 1: 分镜JSON**\n```json\n[\n {\n \"id\": \"S-01\",\n \"act\": \"段落名称\",\n \"narration\": \"中文旁白原文(从逐字稿截取)\",\n \"type\": \"ai-gen\",\n \"prompt\": \"Detailed English prompt for AI video generation. Include: camera movement, scene description, lighting, mood, style. End with quality keywords like 'Cinematic 4K, dramatic lighting'\",\n \"duration\": \"15s\"\n }\n]\n```\n\n**Part 2: SRT字幕**\n```srt\n1\n00:00:00,000 --> 00:00:15,000\n中文旁白原文\n\n2\n00:00:15,000 --> 00:00:30,000\n...\n```",
  60. "temperature": 0.3,
  61. "maxTokens": 8000
  62. },
  63. "output": {
  64. "storyboard": "分镜JSON数组",
  65. "srt": "SRT字幕文件内容"
  66. },
  67. "description": "Agent解析逐字稿,生成带英文prompt的分镜脚本和SRT字幕"
  68. }
  69. ],
  70. "aggregation": {
  71. "output": "storyboardData",
  72. "fields": ["storyboard", "srt"]
  73. }
  74. },
  75. {
  76. "id": "stage_2",
  77. "name": "批量生成视频素材",
  78. "description": "对每个分镜段调用即梦API生成视频素材,支持text2video和img2video两种模式",
  79. "dependsOn": ["stage_1"],
  80. "parallel": true,
  81. "steps": [
  82. {
  83. "id": "2.1",
  84. "name": "文生图(img2video模式首帧)",
  85. "condition": "input.videoMethod === 'img2video'",
  86. "skill": "jimeng-img-v4",
  87. "iterate": "storyboardData.storyboard",
  88. "iterateAs": "segment",
  89. "input": {
  90. "prompt": "{{segment.prompt}}",
  91. "sizeDate": {
  92. "width": "{{input.aspectRatio === '16:9' ? 2560 : input.aspectRatio === '9:16' ? 1440 : 2048}}",
  93. "height": "{{input.aspectRatio === '16:9' ? 1440 : input.aspectRatio === '9:16' ? 2560 : 2048}}"
  94. }
  95. },
  96. "output": "imageWorkIds[{{segment.id}}]",
  97. "rateLimit": { "maxConcurrent": 5, "delayMs": 1000 },
  98. "description": "为每个分镜段生成首帧图片(仅img2video模式)"
  99. },
  100. {
  101. "id": "2.2",
  102. "name": "轮询图片生成结果",
  103. "condition": "input.videoMethod === 'img2video'",
  104. "skill": "jimeng-task-query",
  105. "dependsOn": ["2.1"],
  106. "iterate": "imageWorkIds",
  107. "iterateAs": "workId",
  108. "input": {
  109. "workId": "{{workId}}",
  110. "routerName": "getImgV4"
  111. },
  112. "pollingConfig": {
  113. "intervalMs": 3000,
  114. "maxAttempts": 30,
  115. "completionCondition": "data.isFinish === true"
  116. },
  117. "description": "每3秒轮询一次图片生成状态"
  118. },
  119. {
  120. "id": "2.3",
  121. "name": "获取图片URL",
  122. "condition": "input.videoMethod === 'img2video'",
  123. "skill": "jimeng-work-result",
  124. "dependsOn": ["2.2"],
  125. "iterate": "imageWorkIds",
  126. "iterateAs": "workId",
  127. "input": {
  128. "workId": "{{workId}}"
  129. },
  130. "output": "imageUrls[{{segmentId}}]",
  131. "responseExtract": "images[0]",
  132. "description": "获取生成的图片永久URL作为视频首帧"
  133. },
  134. {
  135. "id": "2.4",
  136. "name": "生成视频(text2video或img2video)",
  137. "skill": "jimeng-video-v3-720p",
  138. "skillSelector": {
  139. "720p": "jimeng-video-v3-720p",
  140. "1080p": "jimeng-video-v3-1080p",
  141. "pro": "jimeng-video-v3-pro"
  142. },
  143. "skillSelectorKey": "input.videoModel",
  144. "dependsOn": ["2.3"],
  145. "iterate": "storyboardData.storyboard",
  146. "iterateAs": "segment",
  147. "input": {
  148. "prompt": "{{segment.prompt}}",
  149. "method": "{{input.videoMethod === 'img2video' ? '2' : '1'}}",
  150. "frames": "{{input.frames}}",
  151. "config": {
  152. "aspect_ratio": "{{input.aspectRatio}}",
  153. "image_urls": "{{input.videoMethod === 'img2video' ? [imageUrls[segment.id]] : undefined}}"
  154. }
  155. },
  156. "output": "videoWorkIds[{{segment.id}}]",
  157. "rateLimit": { "maxConcurrent": 5, "delayMs": 1000 },
  158. "description": "为每个分镜段生成视频。text2video用method=1,img2video用method=2+首帧图"
  159. }
  160. ],
  161. "aggregation": {
  162. "output": "generationResults",
  163. "fields": ["videoWorkIds", "imageUrls"]
  164. }
  165. },
  166. {
  167. "id": "stage_3",
  168. "name": "轮询视频生成结果",
  169. "description": "轮询所有视频生成任务,获取最终视频URL",
  170. "dependsOn": ["stage_2"],
  171. "parallel": true,
  172. "steps": [
  173. {
  174. "id": "3.1",
  175. "name": "轮询视频任务状态",
  176. "skill": "jimeng-task-query",
  177. "iterate": "generationResults.videoWorkIds",
  178. "iterateAs": "entry",
  179. "input": {
  180. "workId": "{{entry.workId}}",
  181. "routerName": "{{input.videoModel === '720p' ? 'getVideoV3_720p' : input.videoModel === '1080p' ? 'getVideoV3_1080p' : 'getVideoV3_Pro'}}"
  182. },
  183. "pollingConfig": {
  184. "intervalMs": 5000,
  185. "maxAttempts": 60,
  186. "completionCondition": "data.isFinish === true",
  187. "timeoutMs": 300000
  188. },
  189. "rateLimit": { "maxConcurrent": 10, "delayMs": 500 },
  190. "description": "每5秒轮询一次视频生成状态,最多5分钟"
  191. },
  192. {
  193. "id": "3.2",
  194. "name": "获取视频URL",
  195. "skill": "jimeng-work-result",
  196. "dependsOn": ["3.1"],
  197. "iterate": "generationResults.videoWorkIds",
  198. "iterateAs": "entry",
  199. "input": {
  200. "workId": "{{entry.workId}}"
  201. },
  202. "output": "videoResults[{{entry.segmentId}}]",
  203. "responseExtract": {
  204. "videoUrl": "videos[0]",
  205. "images": "images"
  206. },
  207. "description": "获取生成的视频永久URL"
  208. }
  209. ],
  210. "aggregation": {
  211. "output": "allVideoResults",
  212. "logic": "合并所有视频结果,按分镜段ID排序"
  213. }
  214. },
  215. {
  216. "id": "stage_4",
  217. "name": "结果汇总与输出",
  218. "description": "汇总所有生成结果,合并分镜脚本与视频URL,统计成功/失败",
  219. "dependsOn": ["stage_3"],
  220. "parallel": false,
  221. "steps": [
  222. {
  223. "id": "4.1",
  224. "name": "合并分镜与视频结果",
  225. "type": "compute",
  226. "logic": "mergeStoryboardWithVideos(storyboardData, allVideoResults, imageUrls)",
  227. "algorithm": {
  228. "merge": "将每个分镜段的videoUrl和imageUrl写入对应的storyboard item",
  229. "stats": "统计 totalSegments, successCount, failedCount, failedIds",
  230. "sort": "按分镜ID排序确保顺序正确",
  231. "srtUpdate": "如果视频实际时长与SRT不同,标注差异供用户参考"
  232. },
  233. "output": "finalOutput",
  234. "description": "生成最终输出:带videoUrl的分镜JSON + SRT字幕 + 统计信息"
  235. }
  236. ]
  237. },
  238. {
  239. "id": "stage_5",
  240. "name": "可选:一键成片",
  241. "description": "将生成的视频素材通过Quickly AI合成短视频(最长30秒)",
  242. "dependsOn": ["stage_4"],
  243. "optional": true,
  244. "condition": "用户明确要求一键成片 && finalOutput.successCount <= 50",
  245. "steps": [
  246. {
  247. "id": "5.1",
  248. "name": "提交一键成片任务",
  249. "skill": "quickly-video-create",
  250. "input": {
  251. "material_list": "{{finalOutput.segments.filter(s => s.videoUrl).map(s => ({ type: 'video', value: s.videoUrl }))}}",
  252. "tags": "{{extractKeywordsFromTranscript(input.transcript)}}",
  253. "proportion": "{{input.aspectRatio === '16:9' ? '9:16' : input.aspectRatio}}",
  254. "video_duration": { "min": 15, "max": 30 },
  255. "pre_id": "{{Date.now().toString()}}",
  256. "ai_voice": 1,
  257. "ai_bgm": 1,
  258. "ai_subtitle": 1
  259. },
  260. "output": "quicklyTaskId",
  261. "description": "将视频素材提交Quickly AI合成短视频(注意:最长30秒限制)"
  262. },
  263. {
  264. "id": "5.2",
  265. "name": "轮询成片结果",
  266. "skill": "quickly-video-query",
  267. "dependsOn": ["5.1"],
  268. "input": {
  269. "taskId": "{{quicklyTaskId}}"
  270. },
  271. "pollingConfig": {
  272. "intervalMs": 15000,
  273. "maxAttempts": 40,
  274. "completionCondition": "data.length > 0"
  275. },
  276. "output": "quicklyResult",
  277. "description": "每15秒轮询,最多10分钟"
  278. }
  279. ]
  280. }
  281. ],
  282. "output": {
  283. "type": "object",
  284. "description": "工作流最终输出",
  285. "properties": {
  286. "storyboard": "带videoUrl的完整分镜JSON",
  287. "srt": "SRT字幕文件内容",
  288. "segments": "视频片段URL列表(按顺序)",
  289. "totalSegments": "总分镜段数",
  290. "successCount": "成功生成的视频数",
  291. "failedCount": "失败的视频数",
  292. "failedIds": "失败的分镜段ID列表(可重试)",
  293. "quicklyResult": "(可选)一键成片结果"
  294. }
  295. },
  296. "estimatedTime": {
  297. "stage_1": "10-30秒(AI生成分镜)",
  298. "stage_2_text2video": "1-3分钟/5段并行(视频生成)",
  299. "stage_2_img2video": "2-5分钟/5段并行(图片+视频)",
  300. "stage_3": "与stage_2重叠(轮询)",
  301. "stage_4": "< 1秒(汇总)",
  302. "total_20segments": "约3-8分钟",
  303. "total_71segments": "约10-25分钟"
  304. },
  305. "userDelivery": {
  306. "immediate": "视频片段URL列表 + SRT字幕文件 + 分镜脚本JSON",
  307. "userAction": "导入剪映/CapCut → 按SRT时间轴排列视频 → 配音 → 成片",
  308. "optional": "一键成片(≤30秒短视频预览)"
  309. }
  310. }