byteplan-cli 1.0.2 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/package.json +7 -3
  2. package/skills/byteplan-analysis/SKILL.md +1078 -0
  3. package/skills/byteplan-api/API_REFERENCE.md +249 -0
  4. package/skills/byteplan-api/SKILL.md +96 -0
  5. package/skills/byteplan-api/package.json +16 -0
  6. package/skills/byteplan-api/scripts/api.js +973 -0
  7. package/skills/byteplan-excel/SKILL.md +212 -0
  8. package/skills/byteplan-excel/examples/margin-analysis.json +40 -0
  9. package/skills/byteplan-excel/package.json +12 -0
  10. package/skills/byteplan-excel/pnpm-lock.yaml +68 -0
  11. package/skills/byteplan-excel/scripts/generate_excel.js +156 -0
  12. package/skills/byteplan-html/SKILL.md +490 -0
  13. package/skills/byteplan-html/examples/example-output.html +184 -0
  14. package/skills/byteplan-html/examples/generate-ppt-style-html.js +611 -0
  15. package/skills/byteplan-html/examples/margin-contribution-analysis.json +152 -0
  16. package/skills/byteplan-html/package.json +18 -0
  17. package/skills/byteplan-html/scripts/generate_html.js +517 -0
  18. package/skills/byteplan-ppt/SKILL.md +394 -0
  19. package/skills/byteplan-ppt/examples/margin-contribution-analysis.json +152 -0
  20. package/skills/byteplan-ppt/package.json +16 -0
  21. package/skills/byteplan-ppt/pnpm-lock.yaml +138 -0
  22. package/skills/byteplan-ppt/scripts/check_ppt_overlap.js +318 -0
  23. package/skills/byteplan-ppt/scripts/generate_ppt.js +680 -0
  24. package/skills/byteplan-video/SKILL.md +606 -0
  25. package/skills/byteplan-video/examples/sample-video-data.json +82 -0
  26. package/skills/byteplan-video/remotion-project/package.json +22 -0
  27. package/skills/byteplan-video/remotion-project/pnpm-lock.yaml +1646 -0
  28. package/skills/byteplan-video/remotion-project/remotion.config.ts +6 -0
  29. package/skills/byteplan-video/remotion-project/scene_durations.json +32 -0
  30. package/skills/byteplan-video/remotion-project/scripts/generate_audio.js +279 -0
  31. package/skills/byteplan-video/remotion-project/src/DynamicReport.tsx +172 -0
  32. package/skills/byteplan-video/remotion-project/src/Root.tsx +51 -0
  33. package/skills/byteplan-video/remotion-project/src/SalesReport.tsx +107 -0
  34. package/skills/byteplan-video/remotion-project/src/index.tsx +4 -0
  35. package/skills/byteplan-video/remotion-project/src/scenes/ChartSlide.tsx +201 -0
  36. package/skills/byteplan-video/remotion-project/src/scenes/CoverSlide.tsx +61 -0
  37. package/skills/byteplan-video/remotion-project/src/scenes/EndSlide.tsx +60 -0
  38. package/skills/byteplan-video/remotion-project/src/scenes/InsightSlide.tsx +101 -0
  39. package/skills/byteplan-video/remotion-project/src/scenes/KpiSlide.tsx +84 -0
  40. package/skills/byteplan-video/remotion-project/src/scenes/RecommendationSlide.tsx +100 -0
  41. package/skills/byteplan-video/remotion-project/tsconfig.json +13 -0
  42. package/skills/byteplan-video/remotion-project/video_data.json +76 -0
  43. package/skills/byteplan-video/scripts/generate_video.js +270 -0
  44. package/skills/byteplan-video/templates/package.json +31 -0
  45. package/skills/byteplan-video/templates/pnpm-lock.yaml +2200 -0
  46. package/skills/byteplan-video/templates/remotion.config.ts +9 -0
  47. package/skills/byteplan-video/templates/scripts/generate-audio.ts +55 -0
  48. package/skills/byteplan-video/templates/src/components/BarChartScene.tsx +153 -0
  49. package/skills/byteplan-video/templates/src/components/InsightScene.tsx +135 -0
  50. package/skills/byteplan-video/templates/src/components/LineChartScene.tsx +214 -0
  51. package/skills/byteplan-video/templates/src/components/SceneFactory.tsx +34 -0
  52. package/skills/byteplan-video/templates/src/components/SummaryScene.tsx +155 -0
  53. package/skills/byteplan-video/templates/src/components/TitleScene.tsx +130 -0
  54. package/skills/byteplan-video/templates/src/compositions/AnalysisVideo.tsx +39 -0
  55. package/skills/byteplan-video/templates/src/index.tsx +28 -0
  56. package/skills/byteplan-video/templates/src/register-root.tsx +4 -0
  57. package/skills/byteplan-video/templates/src/storyboard/types.ts +46 -0
  58. package/skills/byteplan-video/templates/tsconfig.json +17 -0
  59. package/skills/byteplan-video/templates/tsconfig.scripts.json +13 -0
  60. package/skills/byteplan-word/SKILL.md +233 -0
  61. package/skills/byteplan-word/package.json +12 -0
  62. package/skills/byteplan-word/pnpm-lock.yaml +120 -0
  63. package/skills/byteplan-word/scripts/generate_word.js +548 -0
  64. package/src/cli.js +4 -0
  65. package/src/commands/skills.js +279 -0
@@ -0,0 +1,606 @@
1
+ ---
2
+ name: byteplan-video
3
+ description: 根据已有的分析数据生成数据可视化视频。支持自动分镜、语音合成、音画同步。使用 Remotion 渲染引擎。需要先使用 byteplan-analysis skill 完成数据分析。
4
+ ---
5
+
6
+ # BytePlan 视频报告 Skill
7
+
8
+ ## 概述
9
+
10
+ 此 Skill 根据已有的分析数据生成数据可视化视频:
11
+
12
+ 1. **检查数据** - 确认 analysisPlan.json 和 analysis_report.md 存在
13
+ 2. **解析数据** - 从分析结果提取关键数据
14
+ 3. **生成分镜** - 根据数据自动生成场景配置
15
+ 4. **合成语音** - 使用 edge-tts 生成解说语音
16
+ 5. **渲染视频** - 使用 Remotion 渲染 MP4 视频
17
+
18
+ **设计原则**:视频风格与 byteplan-html/byteplan-ppt 统一,深色渐变背景、卡片式设计。
19
+
20
+ **前置条件**:必须先使用 [byteplan-analysis](../byteplan-analysis/SKILL.md) skill 完成数据分析。
21
+
22
+ ---
23
+
24
+ ## 设计规范(与 HTML/PPT 一致)
25
+
26
+ ### 1. 视频结构(标准模板)
27
+
28
+ | 场景 | 内容 | 时长 |
29
+ |------|------|------|
30
+ | 1 | 封面(标题 + 主题) | 5s |
31
+ | 2-N | 数据场景(图表 + 解说) | 每个 8-15s |
32
+ | N+1 | 洞察场景(关键发现) | 8s |
33
+ | N+2 | 总结场景(行动建议) | 8s |
34
+ | N+3 | 结尾页 | 3s |
35
+
36
+ ### 2. 颜色规范
37
+
38
+ ```
39
+ 主题色:
40
+ - purple: #667eea(主强调色)
41
+ - dark-purple: #764ba2(渐变终点色)
42
+
43
+ 背景色:
44
+ - dark-bg: #1a1a2e(主背景)
45
+ - dark-bg-2: #16213e(次背景)
46
+
47
+ 文字色:
48
+ - text-white: #FFFFFF(标题文字)
49
+ - text-gray: #CBD5E1(正文文字)
50
+
51
+ 数据色:
52
+ - green: #4ade80(正向数据)
53
+ - red: #f87171(负向数据)
54
+ - blue: #60a5fa(链接)
55
+ - pink: #f472b6(图表色)
56
+ - cyan: #06B6D4(图表色)
57
+ ```
58
+
59
+ ### 3. 字体规范
60
+
61
+ ```
62
+ 字体:微软雅黑(Microsoft YaHei)
63
+
64
+ 标题:44px, Bold
65
+ 场景标题:32px, Bold
66
+ 解说文字:24px
67
+ 数据数值:36px, Bold, Green
68
+ ```
69
+
70
+ ### 4. 动画规范
71
+
72
+ ```
73
+ 入场动画:fadeIn (0.5s)
74
+ 图表动画:growFromLeft (1s)
75
+ 文字动画:typewriter (按字数计算)
76
+ 转场动画:slide (0.3s)
77
+ ```
78
+
79
+ ---
80
+
81
+ ## 使用方法
82
+
83
+ ### 方式一:命令行
84
+
85
+ ```bash
86
+ # 使用默认数据文件 (video_data.json)
87
+ cd skills/byteplan-video
88
+ pnpm run generate -o report.mp4
89
+
90
+ # 指定数据文件
91
+ pnpm run generate -o report.mp4 -d /path/to/data.json
92
+
93
+ # 指定分辨率和帧率
94
+ pnpm run generate -o report.mp4 --width 1920 --height 1080 --fps 30
95
+ ```
96
+
97
+ ### 方式二:Node.js 调用
98
+
99
+ ```javascript
100
+ import { generateVideo } from './scripts/generate_video.js';
101
+
102
+ await generateVideo('report.mp4', 'video_data.json');
103
+ ```
104
+
105
+ ---
106
+
107
+ ## 数据格式
108
+
109
+ ⚠️ **所有必需字段必须显式提供,无默认值**
110
+
111
+ ```json
112
+ {
113
+ "title": "报告标题",
114
+ "subtitle": "副标题",
115
+ "period": "2026年3月",
116
+ "scenes": [
117
+ {
118
+ "id": "scene_1",
119
+ "type": "title",
120
+ "title": "跨境电商边际贡献分析",
121
+ "subtitle": "数据驱动决策",
122
+ "narration": "本视频将为您分析跨境电商边际贡献情况。",
123
+ "visualConfig": {
124
+ "title": "跨境电商边际贡献分析",
125
+ "subtitle": "数据驱动决策"
126
+ },
127
+ "duration": 5
128
+ },
129
+ {
130
+ "id": "scene_2",
131
+ "type": "bar_chart",
132
+ "title": "渠道边际贡献对比",
133
+ "dataKey": "channelContribution",
134
+ "narration": "渠道A边际贡献最高,达到1627万元。",
135
+ "visualConfig": {
136
+ "title": "渠道边际贡献对比",
137
+ "dataKey": "channelContribution"
138
+ },
139
+ "duration": 10
140
+ },
141
+ {
142
+ "id": "scene_3",
143
+ "type": "line_chart",
144
+ "title": "营收趋势",
145
+ "dataKey": "revenueTrend",
146
+ "narration": "营收呈上升趋势,Q2环比增长50%。",
147
+ "visualConfig": {
148
+ "title": "营收趋势",
149
+ "dataKey": "revenueTrend"
150
+ },
151
+ "duration": 10
152
+ },
153
+ {
154
+ "id": "scene_4",
155
+ "type": "insight",
156
+ "title": "关键洞察",
157
+ "narration": "关键洞察:渠道A表现卓越,但存在产品亏损风险。",
158
+ "visualConfig": {
159
+ "title": "关键洞察",
160
+ "highlights": [
161
+ "渠道A表现卓越,贡献率达68%",
162
+ "风险提示:部分产品亏损"
163
+ ]
164
+ },
165
+ "duration": 8
166
+ },
167
+ {
168
+ "id": "scene_5",
169
+ "type": "summary",
170
+ "title": "行动建议",
171
+ "narration": "建议加大渠道A投入,优化亏损产品线。",
172
+ "visualConfig": {
173
+ "title": "行动建议",
174
+ "points": [
175
+ "加大渠道A投入",
176
+ "优化亏损产品线"
177
+ ],
178
+ "source": "BytePlan 数据平台"
179
+ },
180
+ "duration": 8
181
+ }
182
+ ]
183
+ }
184
+ ```
185
+
186
+ **注意**:
187
+ - `visualConfig` 包含组件渲染所需的配置
188
+ - `dataKey` 用于从 `chartData.json` 获取图表数据
189
+ - `highlights` 是洞察场景的要点数组
190
+ - `points` 是总结场景的要点数组
191
+ - `source` 显示在总结场景底部(可选)
192
+
193
+ ### 场景字段说明
194
+
195
+ | 字段 | 类型 | 必需 | 说明 |
196
+ |------|------|------|------|
197
+ | `type` | string | ✅ | 场景类型(见下表) |
198
+ | `title` | string | ✅ | **场景标题(必须提供,无默认值)** |
199
+ | `subtitle` | string | ❌ | 副标题(封面场景) |
200
+ | `dataKey` | string | ⭐ | **图表数据键(图表场景必需)** |
201
+ | `highlights` | string[] | ⭐ | **洞察要点(insight 场景必需)** |
202
+ | `points` | string[] | ⭐ | **总结要点(summary 场景必需)** |
203
+ | `source` | string | ❌ | 数据来源(显示在总结场景底部) |
204
+ | `narration` | string | ⭐ | **解说文本(用于语音合成)** |
205
+ | `duration` | number | ❌ | 场景时长(秒),有语音时自动计算 |
206
+
207
+ ⚠️ **重要约束**:所有必需字段必须显式提供,组件不会使用任何默认值。缺少必需字段将导致渲染错误。
208
+
209
+ ### 场景类型
210
+
211
+ | 类型 | 说明 | 必需字段 | 支持解说 |
212
+ |------|------|----------|----------|
213
+ | `title` | 封面场景 | title(subtitle 可选) | ✅ |
214
+ | `bar_chart` | 柱状图场景 | title, dataKey | ✅ |
215
+ | `line_chart` | 折线图场景 | title, dataKey | ✅ |
216
+ | `insight` | 洞察场景 | title, highlights[] | ✅ |
217
+ | `summary` | 总结场景 | title, points[], source(可选) | ✅ |
218
+
219
+ ⭐ **重要**:`narration` 字段用于语音合成,如果提供则自动生成语音解说,场景时长由语音时长决定。
220
+
221
+ ---
222
+
223
+ ## 完整示例
224
+
225
+ ### 1. 准备数据文件
226
+
227
+ 确保 `video_data.json` 包含所有必要字段,特别是 `narration` 字段用于语音合成:
228
+
229
+ ```bash
230
+ # 从分析结果生成数据文件
231
+ # 或使用示例数据
232
+ cp examples/sample-video-data.json video_data.json
233
+ ```
234
+
235
+ ### 2. 安装依赖和工具
236
+
237
+ ```bash
238
+ cd skills/byteplan-video/remotion-project
239
+
240
+ # 安装项目依赖(包含 node-edge-tts)
241
+ pnpm install
242
+ ```
243
+
244
+ **TTS 语音合成工具**(二选一):
245
+
246
+ | 方式 | 安装命令 | 说明 |
247
+ |------|----------|------|
248
+ | **npm 包(推荐)** | `pnpm add node-edge-tts` | 纯 Node.js,无需 Python |
249
+ | Python edge-tts | `pip install edge-tts` | 备用方案 |
250
+
251
+ 脚本会自动检测并优先使用 npm 包,失败时回退到 Python edge-tts。
252
+
253
+ ### 3. 生成视频
254
+
255
+ ```bash
256
+ # 自动生成语音并渲染视频
257
+ pnpm run generate -o analysis_report.mp4
258
+
259
+ # 或分步执行:
260
+ # 1. 生成语音
261
+ pnpm run generate:audio
262
+
263
+ # 2. 渲染视频
264
+ pnpm run render
265
+ ```
266
+
267
+ ### 4. 预期输出
268
+
269
+ 生成的视频包含:
270
+ - 封面场景:标题动画 + 渐变背景
271
+ - 数据场景:图表动画 + **语音解说**
272
+ - 洞察场景:卡片动画 + 关键发现
273
+ - 总结场景:建议动画 + 行动指引
274
+ - 结尾场景:感谢动画
275
+
276
+ ### 5. 查看视频
277
+
278
+ ```bash
279
+ open analysis_report.mp4
280
+ ```
281
+
282
+ ---
283
+
284
+ ## 语音合成配置
285
+
286
+ 支持两种 TTS 方式,脚本自动检测并选择可用方式:
287
+
288
+ ### 方式 1: npm 包(推荐)
289
+
290
+ ```bash
291
+ # 安装 node-edge-tts
292
+ pnpm add node-edge-tts
293
+ # 或
294
+ npm install node-edge-tts
295
+ ```
296
+
297
+ 纯 Node.js 实现,无需 Python 依赖,跨平台兼容性更好。
298
+
299
+ ### 方式 2: Python edge-tts(备用)
300
+
301
+ ```bash
302
+ # 安装 Python edge-tts
303
+ pip install edge-tts
304
+ # 或
305
+ pip3 install edge-tts
306
+ ```
307
+
308
+ **注意**:Python edge-tts 需要 ffprobe 获取音频时长:
309
+ - Windows: `choco install ffmpeg`
310
+ - macOS: `brew install ffmpeg`
311
+ - Linux: `sudo apt install ffmpeg`
312
+
313
+ ### 可用语音
314
+
315
+ | 语音ID | 名称 | 特点 |
316
+ |--------|------|------|
317
+ | `zh-CN-XiaoxiaoNeural` | 晓晓(女声) | 自然流畅,推荐使用 |
318
+ | `zh-CN-YunxiNeural` | 云希(男声) | 温和稳重 |
319
+ | `zh-CN-YunyangNeural` | 云扬(男声) | 新闻播报风格 |
320
+ | `zh-CN-XiaoyiNeural` | 晓伊(女声) | 活泼年轻 |
321
+
322
+ ### 语音配置
323
+
324
+ ```javascript
325
+ // 默认配置
326
+ const voiceConfig = {
327
+ voice: 'zh-CN-XiaoxiaoNeural', // 语音ID
328
+ rate: '+0%', // 语速:-50% 到 +100%
329
+ pitch: '+0Hz' // 音调:-50Hz 到 +50Hz
330
+ };
331
+ ```
332
+
333
+ ### 解说文本规范
334
+
335
+ - **长度**:每个场景 20-80 字为宜
336
+ - **风格**:口语化,避免专业术语
337
+ - **节奏**:突出关键数字和变化
338
+ - **停顿**:重要信息后适当加句号,让语音自然停顿
339
+
340
+ ```javascript
341
+ // 好的解说文本
342
+ "渠道A边际贡献最高,达到1627万元,占比68%。"
343
+
344
+ // 不好的解说文本(太长、太书面)
345
+ "经过数据分析,我们发现渠道A的边际贡献在整个渠道体系中排名第一,具体金额为一千六百二十七万元。"
346
+ ```
347
+
348
+ ### 生成语音
349
+
350
+ ```bash
351
+ # 进入项目目录
352
+ cd skills/byteplan-video/remotion-project
353
+
354
+ # 安装依赖(包含 node-edge-tts)
355
+ pnpm install
356
+
357
+ # 运行语音生成脚本
358
+ pnpm run generate:audio
359
+ # 或
360
+ node scripts/generate_audio.js
361
+ ```
362
+
363
+ 脚本会自动:
364
+ 1. 检测 node-edge-tts npm 包(优先)
365
+ 2. 回退到 Python edge-tts(备用)
366
+ 3. 生成所有场景的 MP3 音频
367
+ 4. 保存场景时长配置
368
+
369
+ ### 自动时长计算
370
+
371
+ 语音生成后,系统会自动:
372
+ 1. 获取音频时长
373
+ 2. 更新场景配置中的 `audioDuration`
374
+ 3. Remotion 根据时长自动调整视频帧数
375
+
376
+ ---
377
+
378
+ ## 渲染配置
379
+
380
+ ```javascript
381
+ // remotion.config.ts
382
+ export const config = {
383
+ width: 1920,
384
+ height: 1080,
385
+ fps: 30,
386
+ durationInFrames: 'auto', // 根据场景自动计算
387
+ codec: 'h264',
388
+ outputFormat: 'mp4'
389
+ };
390
+ ```
391
+
392
+ ---
393
+
394
+ ## 注意事项
395
+
396
+ - **前置条件**:必须先运行 byteplan-analysis 完成数据分析
397
+ - **无默认值**:所有必需字段必须显式提供,组件不会使用任何硬编码默认值
398
+ - **字段验证**:缺少必需字段将抛出错误,渲染失败
399
+ - **依赖安装**:首次使用需要 `pnpm install` 安装 Remotion 依赖
400
+ - **语音合成**:推荐使用 `node-edge-tts` npm 包(无需额外依赖)
401
+ - **音频时长**:npm 包从字幕文件自动获取,无需 ffprobe
402
+ - **渲染时间**:视频渲染需要一定时间,耐心等待
403
+ - **字体要求**:使用微软雅黑,确保中英文显示效果
404
+ - **与 HTML/PPT 一致**:设计风格完全统一
405
+
406
+ ---
407
+
408
+ ## 常见问题与解决方案
409
+
410
+ ### 1. 动画值持续增长/溢出
411
+
412
+ **问题**:`interpolate` 函数的动画值在超出输入范围后会继续线性增长,导致柱状图高度一直变大。
413
+
414
+ **原因**:Remotion 的 `interpolate` 默认会进行线性外推(extrapolation)。
415
+
416
+ **解决方案**:所有 `interpolate` 调用必须添加 `extrapolateRight: "clamp"` 参数:
417
+
418
+ ```javascript
419
+ // ❌ 错误:动画值会持续增长
420
+ const opacity = interpolate(frame, [0, 20], [0, 1]);
421
+
422
+ // ✅ 正确:动画值在达到目标后保持不变
423
+ const opacity = interpolate(frame, [0, 20], [0, 1], { extrapolateRight: "clamp" });
424
+
425
+ // 柱状图高度动画
426
+ const animatedHeight = interpolate(
427
+ frame,
428
+ [delay, delay + 30],
429
+ [0, barHeight],
430
+ { extrapolateRight: "clamp" } // 必须添加
431
+ );
432
+ ```
433
+
434
+ ### 2. SVG 饼图位置错误
435
+
436
+ **问题**:饼图显示在画布外或位置偏移。
437
+
438
+ **原因**:SVG 圆心坐标使用了绝对值(如 `cx: 960, cy: 540`),但 SVG 尺寸较小。
439
+
440
+ **解决方案**:圆心坐标应相对于 SVG 尺寸计算:
441
+
442
+ ```javascript
443
+ // ❌ 错误:圆心超出 SVG 范围
444
+ const cx = 960; // 画面中心
445
+ const cy = 540;
446
+ <svg width={450} height={450}>...</svg>
447
+
448
+ // ✅ 正确:圆心在 SVG 中心
449
+ const svgSize = 400;
450
+ const cx = svgSize / 2; // 200
451
+ const cy = svgSize / 2; // 200
452
+ <svg width={svgSize} height={svgSize}>...</svg>
453
+ ```
454
+
455
+ ### 3. 柱状图布局错乱
456
+
457
+ **问题**:柱状图位置不居中或高度计算错误。
458
+
459
+ **原因**:
460
+ 1. 容器同时设置了 `height` 和 `justifyContent: "center"`
461
+ 2. `paddingLeft` 与 flexbox 居中冲突
462
+
463
+ **解决方案**:
464
+
465
+ ```javascript
466
+ // ❌ 错误:多种定位方式冲突
467
+ <div style={{
468
+ display: "flex",
469
+ alignItems: "flex-end",
470
+ height: chartHeight, // 固定高度
471
+ paddingLeft: startX, // 手动偏移
472
+ }}>
473
+ ...
474
+ </div>
475
+
476
+ // ✅ 正确:使用 flexbox 自动居中
477
+ <div style={{
478
+ display: "flex",
479
+ flexDirection: "row",
480
+ alignItems: "flex-end", // 底部对齐
481
+ gap: barGap,
482
+ justifyContent: "center", // 自动居中
483
+ }}>
484
+ {data.map((d, i) => (
485
+ <div key={i} style={{
486
+ display: "flex",
487
+ flexDirection: "column",
488
+ alignItems: "center",
489
+ }}>
490
+ {/* 数值在柱状条上方 */}
491
+ <div style={{ ... }}>{d.value}</div>
492
+ {/* 柱状条 */}
493
+ <div style={{ height: animatedHeight, ... }} />
494
+ {/* 标签在柱状条下方 */}
495
+ <div style={{ ... }}>{d.name}</div>
496
+ </div>
497
+ ))}
498
+ </div>
499
+ ```
500
+
501
+ ### 4. Chrome Headless Shell 下载慢
502
+
503
+ **问题**:首次渲染时下载 Chrome Headless Shell 非常慢(90MB)。
504
+
505
+ **解决方案**:使用 `--browser-executable` 参数指定本地 Chrome:
506
+
507
+ ```bash
508
+ # 下载 Chrome Headless Shell 到本地
509
+ # macOS: https://storage.googleapis.com/chrome-for-testing-public/144.0.7559.20/mac-arm64/chrome-headless-shell-mac-arm64.zip
510
+
511
+ # 赋予执行权限
512
+ chmod +x /path/to/chrome-headless-shell
513
+
514
+ # 渲染时指定路径
515
+ npx remotion render SalesReport output.mp4 \
516
+ --browser-executable=/path/to/chrome-headless-shell
517
+ ```
518
+
519
+ ### 5. 帧数范围错误
520
+
521
+ **问题**:`frame range 0-719 is not inbetween 0-299`
522
+
523
+ **原因**:`Composition` 的 `durationInFrames` 设置过小,与实际场景总帧数不匹配。
524
+
525
+ **解决方案**:根据场景数量和时长动态计算总帧数:
526
+
527
+ ```javascript
528
+ // 计算总帧数
529
+ const sceneDurations = [9, 13, 14, 15, 15, 15, 12, 8]; // 每个场景秒数
530
+ const fps = 30;
531
+ const totalFrames = sceneDurations.reduce((sum, d) => sum + d * fps, 0);
532
+
533
+ <Composition
534
+ id="SalesReport"
535
+ component={SalesReport}
536
+ durationInFrames={totalFrames} // 动态计算
537
+ fps={fps}
538
+ ...
539
+ />
540
+ ```
541
+
542
+ ### 6. Sequence 帧数计算错误
543
+
544
+ **问题**:场景切换时机不对或内容闪烁。
545
+
546
+ **原因**:`Sequence` 的 `from` 和 `durationInFrames` 计算有误。
547
+
548
+ **解决方案**:提前计算每个场景的起始帧和结束帧:
549
+
550
+ ```javascript
551
+ // 预计算场景帧范围
552
+ let currentFrame = 0;
553
+ const slideData = sceneDurations.map((s, i) => {
554
+ const startFrame = currentFrame;
555
+ currentFrame += s.duration * fps;
556
+ return {
557
+ ...s,
558
+ startFrame,
559
+ endFrame: currentFrame
560
+ };
561
+ });
562
+
563
+ // Sequence 使用计算好的值
564
+ <Sequence
565
+ from={slideData[0].endFrame}
566
+ durationInFrames={slideData[1].duration * fps}
567
+ >
568
+ <KpiSlide ... />
569
+ <Audio src={...} />
570
+ </Sequence>
571
+ ```
572
+
573
+ ### 7. 语音时长不同步
574
+
575
+ **问题**:画面结束但语音还在播放,或语音已结束画面还在等待。
576
+
577
+ **解决方案**:使用 ffprobe 获取准确的语音时长,并添加缓冲时间:
578
+
579
+ ```javascript
580
+ // 获取音频时长
581
+ const durationStr = execSync(
582
+ `ffprobe -i "${audioPath}" -show_entries format=duration -v quiet -of csv="p=0"`
583
+ ).toString().trim();
584
+ const audioDuration = parseFloat(durationStr);
585
+
586
+ // 添加 0.5 秒缓冲,确保语音播放完毕
587
+ const sceneDuration = Math.ceil(audioDuration + 0.5);
588
+ ```
589
+
590
+ ---
591
+
592
+ ## 渲染命令示例
593
+
594
+ ```bash
595
+ # 完整渲染流程
596
+
597
+ # 1. 生成语音
598
+ node scripts/generate_audio.js
599
+
600
+ # 2. 渲染视频(指定 Chrome)
601
+ npx remotion render SalesReport output.mp4 \
602
+ --browser-executable=/Users/fudebao/Downloads/chrome-headless-shell-mac-arm64/chrome-headless-shell
603
+
604
+ # 或使用 npm script
605
+ npm run render
606
+ ```
@@ -0,0 +1,82 @@
1
+ {
2
+ "title": "跨境电商边际贡献分析报告",
3
+ "subtitle": "找出贡献最大的要素",
4
+ "period": "2026年3月31日",
5
+ "source": "BytePlan 数据平台",
6
+ "scenes": [
7
+ {
8
+ "type": "title",
9
+ "title": "跨境电商边际贡献分析",
10
+ "subtitle": "数据驱动决策",
11
+ "duration": 5
12
+ },
13
+ {
14
+ "type": "bar_chart",
15
+ "title": "渠道边际贡献对比",
16
+ "data": [
17
+ { "name": "渠道A", "value": 16273934 },
18
+ { "name": "渠道B", "value": 5234567 },
19
+ { "name": "渠道C", "value": 3456789 },
20
+ { "name": "渠道D", "value": 2345678 },
21
+ { "name": "渠道E", "value": 1234567 }
22
+ ],
23
+ "narration": "渠道A边际贡献最高,达到1627万元,占比68%。",
24
+ "duration": 12
25
+ },
26
+ {
27
+ "type": "bar_chart",
28
+ "title": "产品边际贡献排行",
29
+ "data": [
30
+ { "name": "CD120P", "value": 8234567 },
31
+ { "name": "CD110P", "value": 5678901 },
32
+ { "name": "CD130P", "value": 3456789 },
33
+ { "name": "CD140P", "value": -234567 }
34
+ ],
35
+ "narration": "CD120P产品贡献最大,而CD140P出现亏损。",
36
+ "duration": 10
37
+ },
38
+ {
39
+ "type": "ranking",
40
+ "title": "边际贡献 TOP5 市场",
41
+ "data": [
42
+ { "name": "美国", "value": 8234567 },
43
+ { "name": "德国", "value": 5678901 },
44
+ { "name": "日本", "value": 3456789 },
45
+ { "name": "英国", "value": 2345678 },
46
+ { "name": "法国", "value": 1234567 }
47
+ ],
48
+ "narration": "美国市场贡献最大,占总贡献的40%。",
49
+ "duration": 10
50
+ },
51
+ {
52
+ "type": "insight",
53
+ "title": "关键洞察",
54
+ "items": [
55
+ { "title": "渠道A表现卓越", "content": "以68%贡献率成为最大贡献来源" },
56
+ { "title": "美国市场领先", "content": "贡献率达40%,是核心市场" },
57
+ { "title": "CD120P热销", "content": "单品贡献超过800万元" },
58
+ { "title": "⚠️ 亏损风险", "content": "CD140P边际贡献为负,需优化", "warning": true }
59
+ ],
60
+ "narration": "关键洞察:渠道A表现卓越,但存在产品亏损风险。",
61
+ "duration": 10
62
+ },
63
+ {
64
+ "type": "summary",
65
+ "title": "行动建议",
66
+ "items": [
67
+ "加大渠道A营销投入",
68
+ "扩展美国市场份额",
69
+ "优化或淘汰亏损产品",
70
+ "建立数据监控机制"
71
+ ],
72
+ "narration": "建议加大渠道A投入,优化亏损产品线。",
73
+ "duration": 10
74
+ },
75
+ {
76
+ "type": "end",
77
+ "title": "谢谢观看",
78
+ "subtitle": "BytePlan 数据平台",
79
+ "duration": 3
80
+ }
81
+ ]
82
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "byteplan-video-render",
3
+ "version": "1.0.0",
4
+ "scripts": {
5
+ "start": "remotion studio",
6
+ "build": "remotion render SalesReport out.mp4",
7
+ "render": "remotion render SalesReport out.mp4",
8
+ "generate:audio": "node scripts/generate_audio.js"
9
+ },
10
+ "dependencies": {
11
+ "@remotion/cli": "^4.0.0",
12
+ "@remotion/player": "^4.0.0",
13
+ "node-edge-tts": "^1.2.10",
14
+ "react": "^18.2.0",
15
+ "react-dom": "^18.2.0",
16
+ "remotion": "^4.0.0"
17
+ },
18
+ "devDependencies": {
19
+ "@types/react": "^18.2.0",
20
+ "typescript": "^5.0.0"
21
+ }
22
+ }