devrel-toolkit 0.1.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 (115) hide show
  1. package/README.md +63 -0
  2. package/dist/__tests__/cli.test.d.ts +2 -0
  3. package/dist/__tests__/cli.test.d.ts.map +1 -0
  4. package/dist/__tests__/cli.test.js +47 -0
  5. package/dist/__tests__/cli.test.js.map +1 -0
  6. package/dist/__tests__/components.test.d.ts +2 -0
  7. package/dist/__tests__/components.test.d.ts.map +1 -0
  8. package/dist/__tests__/components.test.js +73 -0
  9. package/dist/__tests__/components.test.js.map +1 -0
  10. package/dist/__tests__/d-id-client.test.d.ts +2 -0
  11. package/dist/__tests__/d-id-client.test.d.ts.map +1 -0
  12. package/dist/__tests__/d-id-client.test.js +116 -0
  13. package/dist/__tests__/d-id-client.test.js.map +1 -0
  14. package/dist/__tests__/render-integration.test.d.ts +2 -0
  15. package/dist/__tests__/render-integration.test.d.ts.map +1 -0
  16. package/dist/__tests__/render-integration.test.js +26 -0
  17. package/dist/__tests__/render-integration.test.js.map +1 -0
  18. package/dist/__tests__/schema.test.d.ts +2 -0
  19. package/dist/__tests__/schema.test.d.ts.map +1 -0
  20. package/dist/__tests__/schema.test.js +173 -0
  21. package/dist/__tests__/schema.test.js.map +1 -0
  22. package/dist/__tests__/timing.test.d.ts +2 -0
  23. package/dist/__tests__/timing.test.d.ts.map +1 -0
  24. package/dist/__tests__/timing.test.js +69 -0
  25. package/dist/__tests__/timing.test.js.map +1 -0
  26. package/dist/cli/d-id.d.ts +3 -0
  27. package/dist/cli/d-id.d.ts.map +1 -0
  28. package/dist/cli/d-id.js +53 -0
  29. package/dist/cli/d-id.js.map +1 -0
  30. package/dist/cli/doctor.d.ts +3 -0
  31. package/dist/cli/doctor.d.ts.map +1 -0
  32. package/dist/cli/doctor.js +134 -0
  33. package/dist/cli/doctor.js.map +1 -0
  34. package/dist/cli/index.d.ts +3 -0
  35. package/dist/cli/index.d.ts.map +1 -0
  36. package/dist/cli/index.js +21 -0
  37. package/dist/cli/index.js.map +1 -0
  38. package/dist/cli/install-skill.d.ts +3 -0
  39. package/dist/cli/install-skill.d.ts.map +1 -0
  40. package/dist/cli/install-skill.js +50 -0
  41. package/dist/cli/install-skill.js.map +1 -0
  42. package/dist/cli/render.d.ts +4 -0
  43. package/dist/cli/render.d.ts.map +1 -0
  44. package/dist/cli/render.js +134 -0
  45. package/dist/cli/render.js.map +1 -0
  46. package/dist/cli/setup.d.ts +3 -0
  47. package/dist/cli/setup.d.ts.map +1 -0
  48. package/dist/cli/setup.js +60 -0
  49. package/dist/cli/setup.js.map +1 -0
  50. package/dist/compositor/DemoVideo.d.ts +4 -0
  51. package/dist/compositor/DemoVideo.d.ts.map +1 -0
  52. package/dist/compositor/DemoVideo.js +64 -0
  53. package/dist/compositor/DemoVideo.js.map +1 -0
  54. package/dist/compositor/Root.d.ts +3 -0
  55. package/dist/compositor/Root.d.ts.map +1 -0
  56. package/dist/compositor/Root.js +30 -0
  57. package/dist/compositor/Root.js.map +1 -0
  58. package/dist/compositor/components/AvatarPiP.d.ts +10 -0
  59. package/dist/compositor/components/AvatarPiP.d.ts.map +1 -0
  60. package/dist/compositor/components/AvatarPiP.js +52 -0
  61. package/dist/compositor/components/AvatarPiP.js.map +1 -0
  62. package/dist/compositor/components/BrowserFrame.d.ts +18 -0
  63. package/dist/compositor/components/BrowserFrame.d.ts.map +1 -0
  64. package/dist/compositor/components/BrowserFrame.js +97 -0
  65. package/dist/compositor/components/BrowserFrame.js.map +1 -0
  66. package/dist/compositor/components/Cursor.d.ts +13 -0
  67. package/dist/compositor/components/Cursor.d.ts.map +1 -0
  68. package/dist/compositor/components/Cursor.js +65 -0
  69. package/dist/compositor/components/Cursor.js.map +1 -0
  70. package/dist/compositor/components/Highlight.d.ts +9 -0
  71. package/dist/compositor/components/Highlight.d.ts.map +1 -0
  72. package/dist/compositor/components/Highlight.js +83 -0
  73. package/dist/compositor/components/Highlight.js.map +1 -0
  74. package/dist/compositor/components/IntroOutro.d.ts +10 -0
  75. package/dist/compositor/components/IntroOutro.d.ts.map +1 -0
  76. package/dist/compositor/components/IntroOutro.js +48 -0
  77. package/dist/compositor/components/IntroOutro.js.map +1 -0
  78. package/dist/compositor/components/SceneTransition.d.ts +9 -0
  79. package/dist/compositor/components/SceneTransition.d.ts.map +1 -0
  80. package/dist/compositor/components/SceneTransition.js +35 -0
  81. package/dist/compositor/components/SceneTransition.js.map +1 -0
  82. package/dist/compositor/components/Subtitles.d.ts +9 -0
  83. package/dist/compositor/components/Subtitles.d.ts.map +1 -0
  84. package/dist/compositor/components/Subtitles.js +45 -0
  85. package/dist/compositor/components/Subtitles.js.map +1 -0
  86. package/dist/compositor/index.d.ts +2 -0
  87. package/dist/compositor/index.d.ts.map +1 -0
  88. package/dist/compositor/index.js +4 -0
  89. package/dist/compositor/index.js.map +1 -0
  90. package/dist/compositor/timing.d.ts +16 -0
  91. package/dist/compositor/timing.d.ts.map +1 -0
  92. package/dist/compositor/timing.js +39 -0
  93. package/dist/compositor/timing.js.map +1 -0
  94. package/dist/d-id/client.d.ts +50 -0
  95. package/dist/d-id/client.d.ts.map +1 -0
  96. package/dist/d-id/client.js +114 -0
  97. package/dist/d-id/client.js.map +1 -0
  98. package/dist/d-id/generate.d.ts +9 -0
  99. package/dist/d-id/generate.d.ts.map +1 -0
  100. package/dist/d-id/generate.js +81 -0
  101. package/dist/d-id/generate.js.map +1 -0
  102. package/dist/utils/config.d.ts +14 -0
  103. package/dist/utils/config.d.ts.map +1 -0
  104. package/dist/utils/config.js +34 -0
  105. package/dist/utils/config.js.map +1 -0
  106. package/dist/utils/schema.d.ts +273 -0
  107. package/dist/utils/schema.d.ts.map +1 -0
  108. package/dist/utils/schema.js +98 -0
  109. package/dist/utils/schema.js.map +1 -0
  110. package/package.json +54 -0
  111. package/remotion.config.ts +4 -0
  112. package/skills/make-demo/SKILL.md +282 -0
  113. package/skills/make-demo/references/demo-script-schema.md +47 -0
  114. package/skills/make-demo/references/render-props-schema.md +49 -0
  115. package/skills/make-demo/references/toolkit-commands.md +23 -0
@@ -0,0 +1,35 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { AbsoluteFill, interpolate, useCurrentFrame, useVideoConfig, } from "remotion";
3
+ export const SceneTransition = ({ type, durationFrames, direction, }) => {
4
+ const frame = useCurrentFrame();
5
+ const { width } = useVideoConfig();
6
+ if (type === "cut" || durationFrames <= 0)
7
+ return null;
8
+ // Progress: 0 = fully transitioned, 1 = fully visible (for "in" direction)
9
+ const progress = interpolate(frame, [0, durationFrames], [0, 1], {
10
+ extrapolateLeft: "clamp",
11
+ extrapolateRight: "clamp",
12
+ });
13
+ const effectiveProgress = direction === "in" ? progress : 1 - progress;
14
+ switch (type) {
15
+ case "fade": {
16
+ // Overlay a black fill that fades out (for entrance)
17
+ const opacity = 1 - effectiveProgress;
18
+ return (_jsx(AbsoluteFill, { style: {
19
+ backgroundColor: "#000",
20
+ opacity,
21
+ } }));
22
+ }
23
+ case "slide": {
24
+ // Scene slides in from the right (for entrance)
25
+ const translateX = interpolate(effectiveProgress, [0, 1], [width, 0]);
26
+ return (_jsx(AbsoluteFill, { style: {
27
+ backgroundColor: "#000",
28
+ transform: `translateX(${-translateX}px)`,
29
+ } }));
30
+ }
31
+ default:
32
+ return null;
33
+ }
34
+ };
35
+ //# sourceMappingURL=SceneTransition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SceneTransition.js","sourceRoot":"","sources":["../../../src/compositor/components/SceneTransition.tsx"],"names":[],"mappings":";AACA,OAAO,EACL,YAAY,EACZ,WAAW,EACX,eAAe,EACf,cAAc,GACf,MAAM,UAAU,CAAC;AAQlB,MAAM,CAAC,MAAM,eAAe,GAAmC,CAAC,EAC9D,IAAI,EACJ,cAAc,EACd,SAAS,GACV,EAAE,EAAE;IACH,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,MAAM,EAAE,KAAK,EAAE,GAAG,cAAc,EAAE,CAAC;IAEnC,IAAI,IAAI,KAAK,KAAK,IAAI,cAAc,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAEvD,2EAA2E;IAC3E,MAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,cAAc,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;QAC/D,eAAe,EAAE,OAAO;QACxB,gBAAgB,EAAE,OAAO;KAC1B,CAAC,CAAC;IAEH,MAAM,iBAAiB,GAAG,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC;IAEvE,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,qDAAqD;YACrD,MAAM,OAAO,GAAG,CAAC,GAAG,iBAAiB,CAAC;YACtC,OAAO,CACL,KAAC,YAAY,IACX,KAAK,EAAE;oBACL,eAAe,EAAE,MAAM;oBACvB,OAAO;iBACR,GACD,CACH,CAAC;QACJ,CAAC;QAED,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,gDAAgD;YAChD,MAAM,UAAU,GAAG,WAAW,CAAC,iBAAiB,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;YACtE,OAAO,CACL,KAAC,YAAY,IACX,KAAK,EAAE;oBACL,eAAe,EAAE,MAAM;oBACvB,SAAS,EAAE,cAAc,CAAC,UAAU,KAAK;iBAC1C,GACD,CACH,CAAC;QACJ,CAAC;QAED;YACE,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ import React from "react";
2
+ interface SubtitlesProps {
3
+ text: string;
4
+ durationFrames: number;
5
+ visible: boolean;
6
+ }
7
+ export declare const Subtitles: React.FC<SubtitlesProps>;
8
+ export {};
9
+ //# sourceMappingURL=Subtitles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Subtitles.d.ts","sourceRoot":"","sources":["../../../src/compositor/components/Subtitles.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CAuE9C,CAAC"}
@@ -0,0 +1,45 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { interpolate, useCurrentFrame } from "remotion";
3
+ export const Subtitles = ({ text, durationFrames, visible, }) => {
4
+ const frame = useCurrentFrame();
5
+ if (!visible || !text)
6
+ return null;
7
+ const words = text.split(/\s+/);
8
+ const totalWords = words.length;
9
+ // Calculate how many words should be visible at the current frame
10
+ // Leave a small buffer at start and end
11
+ const startFrame = 10;
12
+ const endFrame = durationFrames - 5;
13
+ const visibleWordCount = Math.ceil(interpolate(frame, [startFrame, endFrame], [0, totalWords], {
14
+ extrapolateLeft: "clamp",
15
+ extrapolateRight: "clamp",
16
+ }));
17
+ // Fade in
18
+ const opacity = interpolate(frame, [0, 10], [0, 1], {
19
+ extrapolateLeft: "clamp",
20
+ extrapolateRight: "clamp",
21
+ });
22
+ // Fade out at end
23
+ const fadeOut = interpolate(frame, [durationFrames - 10, durationFrames], [1, 0], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });
24
+ return (_jsx("div", { style: {
25
+ position: "absolute",
26
+ bottom: 48,
27
+ left: "50%",
28
+ transform: "translateX(-50%)",
29
+ maxWidth: "80%",
30
+ opacity: opacity * fadeOut,
31
+ }, children: _jsx("div", { style: {
32
+ backgroundColor: "rgba(0, 0, 0, 0.7)",
33
+ borderRadius: 12,
34
+ padding: "12px 24px",
35
+ backdropFilter: "blur(8px)",
36
+ }, children: _jsx("span", { style: {
37
+ color: "#fff",
38
+ fontSize: 24,
39
+ fontFamily: "system-ui, -apple-system, sans-serif",
40
+ fontWeight: 500,
41
+ lineHeight: 1.4,
42
+ letterSpacing: 0.3,
43
+ }, children: words.slice(0, visibleWordCount).join(" ") }) }) }));
44
+ };
45
+ //# sourceMappingURL=Subtitles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Subtitles.js","sourceRoot":"","sources":["../../../src/compositor/components/Subtitles.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAQxD,MAAM,CAAC,MAAM,SAAS,GAA6B,CAAC,EAClD,IAAI,EACJ,cAAc,EACd,OAAO,GACR,EAAE,EAAE;IACH,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAEhC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAEnC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAChC,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC;IAEhC,kEAAkE;IAClE,wCAAwC;IACxC,MAAM,UAAU,GAAG,EAAE,CAAC;IACtB,MAAM,QAAQ,GAAG,cAAc,GAAG,CAAC,CAAC;IACpC,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAChC,WAAW,CAAC,KAAK,EAAE,CAAC,UAAU,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE;QAC1D,eAAe,EAAE,OAAO;QACxB,gBAAgB,EAAE,OAAO;KAC1B,CAAC,CACH,CAAC;IAEF,UAAU;IACV,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;QAClD,eAAe,EAAE,OAAO;QACxB,gBAAgB,EAAE,OAAO;KAC1B,CAAC,CAAC;IAEH,kBAAkB;IAClB,MAAM,OAAO,GAAG,WAAW,CACzB,KAAK,EACL,CAAC,cAAc,GAAG,EAAE,EAAE,cAAc,CAAC,EACrC,CAAC,CAAC,EAAE,CAAC,CAAC,EACN,EAAE,eAAe,EAAE,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,CACxD,CAAC;IAEF,OAAO,CACL,cACE,KAAK,EAAE;YACL,QAAQ,EAAE,UAAU;YACpB,MAAM,EAAE,EAAE;YACV,IAAI,EAAE,KAAK;YACX,SAAS,EAAE,kBAAkB;YAC7B,QAAQ,EAAE,KAAK;YACf,OAAO,EAAE,OAAO,GAAG,OAAO;SAC3B,YAED,cACE,KAAK,EAAE;gBACL,eAAe,EAAE,oBAAoB;gBACrC,YAAY,EAAE,EAAE;gBAChB,OAAO,EAAE,WAAW;gBACpB,cAAc,EAAE,WAAW;aAC5B,YAED,eACE,KAAK,EAAE;oBACL,KAAK,EAAE,MAAM;oBACb,QAAQ,EAAE,EAAE;oBACZ,UAAU,EAAE,sCAAsC;oBAClD,UAAU,EAAE,GAAG;oBACf,UAAU,EAAE,GAAG;oBACf,aAAa,EAAE,GAAG;iBACnB,YAEA,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GACtC,GACH,GACF,CACP,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/compositor/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ import { registerRoot } from "remotion";
2
+ import { RemotionRoot } from "./Root.js";
3
+ registerRoot(RemotionRoot);
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/compositor/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC,YAAY,CAAC,YAAY,CAAC,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { RenderProps, RenderScene } from "../utils/schema.js";
2
+ /**
3
+ * Calculate total duration in frames for the entire composition.
4
+ * Accounts for transition overlaps between scenes.
5
+ * Used by calculateMetadata in Root.tsx.
6
+ */
7
+ export declare function calculateTotalFrames(props: RenderProps): number;
8
+ /**
9
+ * Estimate duration from narration text (~150 words per minute = 2.5 wps).
10
+ */
11
+ export declare function estimateDuration(narration: string): number;
12
+ /**
13
+ * Get the scene duration in seconds.
14
+ */
15
+ export declare function getSceneDuration(scene: RenderScene): number;
16
+ //# sourceMappingURL=timing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timing.d.ts","sourceRoot":"","sources":["../../src/compositor/timing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAInE;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAqB/D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAG1D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAE3D"}
@@ -0,0 +1,39 @@
1
+ const TRANSITION_DURATION_SECONDS = 0.5;
2
+ /**
3
+ * Calculate total duration in frames for the entire composition.
4
+ * Accounts for transition overlaps between scenes.
5
+ * Used by calculateMetadata in Root.tsx.
6
+ */
7
+ export function calculateTotalFrames(props) {
8
+ const { fps, scenes } = props;
9
+ if (scenes.length === 0)
10
+ return 0;
11
+ const transitionFrames = Math.ceil(TRANSITION_DURATION_SECONDS * fps);
12
+ // Sum all scene durations
13
+ let total = 0;
14
+ for (const scene of scenes) {
15
+ total += Math.ceil(scene.avatarDuration * fps);
16
+ }
17
+ // Subtract transition overlaps between consecutive non-cut scenes
18
+ for (let i = 0; i < scenes.length - 1; i++) {
19
+ const nextScene = scenes[i + 1];
20
+ if (nextScene && nextScene.transition !== "cut") {
21
+ total -= transitionFrames;
22
+ }
23
+ }
24
+ return total;
25
+ }
26
+ /**
27
+ * Estimate duration from narration text (~150 words per minute = 2.5 wps).
28
+ */
29
+ export function estimateDuration(narration) {
30
+ const words = narration.trim().split(/\s+/).length;
31
+ return Math.max(2, words / 2.5);
32
+ }
33
+ /**
34
+ * Get the scene duration in seconds.
35
+ */
36
+ export function getSceneDuration(scene) {
37
+ return scene.avatarDuration;
38
+ }
39
+ //# sourceMappingURL=timing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timing.js","sourceRoot":"","sources":["../../src/compositor/timing.ts"],"names":[],"mappings":"AAEA,MAAM,2BAA2B,GAAG,GAAG,CAAC;AAExC;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAkB;IACrD,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IAC9B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAElC,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,2BAA2B,GAAG,GAAG,CAAC,CAAC;IAEtE,0BAA0B;IAC1B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,GAAG,GAAG,CAAC,CAAC;IACjD,CAAC;IAED,kEAAkE;IAClE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAChC,IAAI,SAAS,IAAI,SAAS,CAAC,UAAU,KAAK,KAAK,EAAE,CAAC;YAChD,KAAK,IAAI,gBAAgB,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,SAAiB;IAChD,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;IACnD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,GAAG,CAAC,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAkB;IACjD,OAAO,KAAK,CAAC,cAAc,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,50 @@
1
+ export interface DIDAvatar {
2
+ id: string;
3
+ name: string;
4
+ sentiments: {
5
+ id: string;
6
+ name: string;
7
+ }[];
8
+ }
9
+ export interface CreateVideoOptions {
10
+ avatarId: string;
11
+ sentimentId?: string;
12
+ script: string;
13
+ config?: {
14
+ result_format?: "mp4" | "mov" | "webm";
15
+ output_resolution?: 480 | 720 | 1080;
16
+ };
17
+ background?: {
18
+ type: "color";
19
+ value: string;
20
+ };
21
+ }
22
+ export interface VideoStatus {
23
+ id: string;
24
+ status: "created" | "started" | "done" | "error" | "rejected";
25
+ result_url?: string;
26
+ duration?: number;
27
+ error?: {
28
+ kind: string;
29
+ description: string;
30
+ };
31
+ }
32
+ export interface PollOptions {
33
+ interval?: number;
34
+ timeout?: number;
35
+ }
36
+ export declare class DIDClient {
37
+ private apiKey;
38
+ constructor(apiKey: string);
39
+ private get headers();
40
+ private request;
41
+ listAvatars(): Promise<DIDAvatar[]>;
42
+ createVideo(options: CreateVideoOptions): Promise<{
43
+ id: string;
44
+ status: string;
45
+ }>;
46
+ getVideo(id: string): Promise<VideoStatus>;
47
+ pollUntilDone(id: string, options?: PollOptions): Promise<VideoStatus>;
48
+ downloadVideo(resultUrl: string, outputPath: string): Promise<void>;
49
+ }
50
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/d-id/client.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC5C;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE;QACP,aAAa,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;QACvC,iBAAiB,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,IAAI,CAAC;KACtC,CAAC;IACF,UAAU,CAAC,EAAE;QACX,IAAI,EAAE,OAAO,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,CAAC;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/C;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,MAAM;IAI1B,OAAO,KAAK,OAAO,GAKlB;YAEa,OAAO;IAiEf,WAAW,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAQnC,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAsBjF,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAI1C,aAAa,CACjB,EAAE,EAAE,MAAM,EACV,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,WAAW,CAAC;IA4BjB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAY1E"}
@@ -0,0 +1,114 @@
1
+ import { createWriteStream } from "node:fs";
2
+ import { pipeline } from "node:stream/promises";
3
+ import { Readable } from "node:stream";
4
+ const BASE_URL = "https://api.d-id.com";
5
+ export class DIDClient {
6
+ apiKey;
7
+ constructor(apiKey) {
8
+ this.apiKey = apiKey;
9
+ }
10
+ get headers() {
11
+ return {
12
+ Authorization: `Basic ${this.apiKey}`,
13
+ "Content-Type": "application/json",
14
+ };
15
+ }
16
+ async request(method, path, body, retries = 3) {
17
+ let lastError = null;
18
+ for (let attempt = 0; attempt < retries; attempt++) {
19
+ try {
20
+ const response = await fetch(`${BASE_URL}${path}`, {
21
+ method,
22
+ headers: this.headers,
23
+ body: body ? JSON.stringify(body) : undefined,
24
+ });
25
+ if (response.ok) {
26
+ return (await response.json());
27
+ }
28
+ const errorBody = await response.json().catch(() => ({}));
29
+ if (response.status === 401) {
30
+ throw new Error("D-ID authentication failed (401). Check your DID_API_KEY.");
31
+ }
32
+ if (response.status === 402) {
33
+ throw new Error("D-ID insufficient credits (402). Top up your D-ID account to continue.");
34
+ }
35
+ // Don't retry client errors (4xx) other than rate limits
36
+ if (response.status >= 400 && response.status < 500 && response.status !== 429) {
37
+ throw new Error(`D-ID API error ${response.status}: ${errorBody.description || JSON.stringify(errorBody)}`);
38
+ }
39
+ lastError = new Error(`D-ID API error ${response.status}: ${errorBody.description || "unknown error"}`);
40
+ }
41
+ catch (err) {
42
+ if (err instanceof Error &&
43
+ (err.message.includes("401") ||
44
+ err.message.includes("402") ||
45
+ err.message.includes("D-ID API error 4"))) {
46
+ throw err;
47
+ }
48
+ lastError = err;
49
+ }
50
+ // Exponential backoff before retry
51
+ if (attempt < retries - 1) {
52
+ const delay = Math.pow(2, attempt) * 1000;
53
+ await new Promise((resolve) => setTimeout(resolve, delay));
54
+ }
55
+ }
56
+ throw lastError ?? new Error("D-ID API request failed after retries");
57
+ }
58
+ async listAvatars() {
59
+ const data = await this.request("GET", "/expressives/avatars");
60
+ return data.avatars ?? data;
61
+ }
62
+ async createVideo(options) {
63
+ const body = {
64
+ avatar_id: options.avatarId,
65
+ script: {
66
+ type: "text",
67
+ input: options.script,
68
+ },
69
+ };
70
+ if (options.sentimentId) {
71
+ body.sentiment_id = options.sentimentId;
72
+ }
73
+ if (options.config) {
74
+ body.config = options.config;
75
+ }
76
+ if (options.background) {
77
+ body.background = options.background;
78
+ }
79
+ return this.request("POST", "/expressives", body);
80
+ }
81
+ async getVideo(id) {
82
+ return this.request("GET", `/expressives/${id}`, undefined, 1);
83
+ }
84
+ async pollUntilDone(id, options = {}) {
85
+ const interval = options.interval ?? 5000;
86
+ const timeout = options.timeout ?? 600000; // 10 minutes
87
+ const startTime = Date.now();
88
+ while (true) {
89
+ const video = await this.getVideo(id);
90
+ if (video.status === "done") {
91
+ return video;
92
+ }
93
+ if (video.status === "error" || video.status === "rejected") {
94
+ throw new Error(`D-ID video generation failed: ${video.error?.description ?? video.status}`);
95
+ }
96
+ if (Date.now() - startTime > timeout) {
97
+ throw new Error(`D-ID video generation timed out after ${timeout / 1000}s (status: ${video.status})`);
98
+ }
99
+ await new Promise((resolve) => setTimeout(resolve, interval));
100
+ }
101
+ }
102
+ async downloadVideo(resultUrl, outputPath) {
103
+ const response = await fetch(resultUrl);
104
+ if (!response.ok) {
105
+ throw new Error(`Failed to download video: HTTP ${response.status}`);
106
+ }
107
+ if (!response.body) {
108
+ throw new Error("Response body is empty");
109
+ }
110
+ const fileStream = createWriteStream(outputPath);
111
+ await pipeline(Readable.fromWeb(response.body), fileStream);
112
+ }
113
+ }
114
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/d-id/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export interface GenerateOptions {
2
+ scriptPath: string;
3
+ outputDir: string;
4
+ defaultAvatarId?: string;
5
+ defaultSentimentId?: string;
6
+ concurrency: number;
7
+ }
8
+ export declare function generateAvatarClips(options: GenerateOptions): Promise<void>;
9
+ //# sourceMappingURL=generate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/d-id/generate.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;CACrB;AAeD,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAqGjF"}
@@ -0,0 +1,81 @@
1
+ import { readFileSync, mkdirSync, writeFileSync } from "node:fs";
2
+ import { resolve, join } from "node:path";
3
+ import { DIDClient } from "./client.js";
4
+ import { requireDidApiKey } from "../utils/config.js";
5
+ export async function generateAvatarClips(options) {
6
+ const apiKey = requireDidApiKey();
7
+ const client = new DIDClient(apiKey);
8
+ // Read and parse script
9
+ const scriptPath = resolve(options.scriptPath);
10
+ const raw = readFileSync(scriptPath, "utf-8");
11
+ const scenes = JSON.parse(raw);
12
+ if (!Array.isArray(scenes) || scenes.length === 0) {
13
+ throw new Error("Script must be a non-empty array of scenes with { id, narration }");
14
+ }
15
+ // Ensure output directory exists
16
+ const outputDir = resolve(options.outputDir);
17
+ mkdirSync(outputDir, { recursive: true });
18
+ const total = scenes.length;
19
+ const manifest = [];
20
+ let completed = 0;
21
+ console.log(`\nGenerating ${total} avatar clip(s)...\n`);
22
+ // Process scenes with concurrency limit
23
+ const queue = [...scenes];
24
+ const inFlight = [];
25
+ async function processScene(scene) {
26
+ const avatarId = scene.avatarId ?? options.defaultAvatarId;
27
+ if (!avatarId) {
28
+ throw new Error(`No avatar ID for scene "${scene.id}". Provide --avatar or set avatarId per scene.`);
29
+ }
30
+ const sentimentId = scene.sentimentId ?? options.defaultSentimentId;
31
+ console.log(` [${completed + 1}/${total}] Generating avatar for "${scene.id}"...`);
32
+ // Rate limit: minimum 500ms between API calls
33
+ await new Promise((resolve) => setTimeout(resolve, 500));
34
+ // Create the video
35
+ const created = await client.createVideo({
36
+ avatarId,
37
+ sentimentId,
38
+ script: scene.narration,
39
+ config: { result_format: "mp4", output_resolution: 1080 },
40
+ background: { type: "color", value: "#1a1a1a" },
41
+ });
42
+ // Poll until done
43
+ const result = await client.pollUntilDone(created.id, {
44
+ interval: 5000,
45
+ timeout: 600000,
46
+ });
47
+ if (!result.result_url) {
48
+ throw new Error(`No result URL for scene "${scene.id}" (id: ${created.id})`);
49
+ }
50
+ // Download the clip
51
+ const clipPath = join(outputDir, `${scene.id}.mp4`);
52
+ await client.downloadVideo(result.result_url, clipPath);
53
+ completed++;
54
+ console.log(` [${completed}/${total}] Done: ${scene.id} (${result.duration ?? "?"}s)`);
55
+ manifest.push({
56
+ id: scene.id,
57
+ clipPath,
58
+ duration: result.duration ?? 0,
59
+ });
60
+ }
61
+ // Run with concurrency limit
62
+ for (const scene of queue) {
63
+ const promise = processScene(scene).then(() => {
64
+ const idx = inFlight.indexOf(promise);
65
+ if (idx !== -1)
66
+ inFlight.splice(idx, 1);
67
+ });
68
+ inFlight.push(promise);
69
+ if (inFlight.length >= options.concurrency) {
70
+ await Promise.race(inFlight);
71
+ }
72
+ }
73
+ // Wait for remaining
74
+ await Promise.all(inFlight);
75
+ // Write manifest
76
+ const manifestPath = join(outputDir, "manifest.json");
77
+ writeFileSync(manifestPath, JSON.stringify({ scenes: manifest }, null, 2), "utf-8");
78
+ console.log(`\nAll ${total} clip(s) generated.`);
79
+ console.log(`Manifest: ${manifestPath}\n`);
80
+ }
81
+ //# sourceMappingURL=generate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../src/d-id/generate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export interface ToolkitConfig {
2
+ didApiKey: string | undefined;
3
+ browserUseApiKey: string | undefined;
4
+ }
5
+ /**
6
+ * Loads configuration from environment variables, falling back to .env.local
7
+ * in the current working directory.
8
+ */
9
+ export declare function loadConfig(): ToolkitConfig;
10
+ /**
11
+ * Returns the D-ID API key or throws with a helpful error message.
12
+ */
13
+ export declare function requireDidApiKey(): string;
14
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;CACtC;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,aAAa,CAiB1C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAQzC"}
@@ -0,0 +1,34 @@
1
+ import * as dotenv from "dotenv";
2
+ import { existsSync } from "node:fs";
3
+ import { resolve } from "node:path";
4
+ /**
5
+ * Loads configuration from environment variables, falling back to .env.local
6
+ * in the current working directory.
7
+ */
8
+ export function loadConfig() {
9
+ // Try loading .env.local from the user's project directory
10
+ const envLocalPath = resolve(process.cwd(), ".env.local");
11
+ if (existsSync(envLocalPath)) {
12
+ dotenv.config({ path: envLocalPath });
13
+ }
14
+ // Also try .env as a fallback
15
+ const envPath = resolve(process.cwd(), ".env");
16
+ if (existsSync(envPath)) {
17
+ dotenv.config({ path: envPath });
18
+ }
19
+ return {
20
+ didApiKey: process.env.DID_API_KEY,
21
+ browserUseApiKey: process.env.BROWSER_USE_API_KEY,
22
+ };
23
+ }
24
+ /**
25
+ * Returns the D-ID API key or throws with a helpful error message.
26
+ */
27
+ export function requireDidApiKey() {
28
+ const config = loadConfig();
29
+ if (!config.didApiKey) {
30
+ throw new Error("DID_API_KEY not found. Set it as an environment variable or in your project's .env.local file.");
31
+ }
32
+ return config.didApiKey;
33
+ }
34
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC;;;GAGG;AACH,MAAM,UAAU,UAAU;IACxB,2DAA2D;IAC3D,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,YAAY,CAAC,CAAC;IAC1D,IAAI,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC7B,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;IACxC,CAAC;IAED,8BAA8B;IAC9B,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC;IAC/C,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACxB,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IACnC,CAAC;IAED,OAAO;QACL,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW;QAClC,gBAAgB,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB;KAClD,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CACb,gGAAgG,CACjG,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC,SAAS,CAAC;AAC1B,CAAC"}