@mevdragon/vidfarm-devcli 0.5.2 → 0.6.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 (113) hide show
  1. package/README.md +3 -3
  2. package/demo/README.md +28 -0
  3. package/demo/dist/app.css +1 -0
  4. package/demo/dist/app.js +1184 -0
  5. package/demo/dist/chunks/chunk-DXB73IDG.js +1 -0
  6. package/demo/dist/chunks/chunk-S7OWAJDS.js +36 -0
  7. package/demo/dist/chunks/chunk-VTIBZ6AN.js +1 -0
  8. package/demo/dist/chunks/dist-ADSJKBVE.js +332 -0
  9. package/demo/dist/chunks/domEditingLayers-VZMLL4AP-SGHWPND4.js +1 -0
  10. package/demo/dist/chunks/hyperframes-player-XB65TCD6.js +425 -0
  11. package/demo/dist/chunks/lib-XAQ37YOE.js +1 -0
  12. package/demo/dist/chunks/src-TJ2QYA4U.js +207 -0
  13. package/demo/dist/favicon.ico +0 -0
  14. package/demo/dist/icons/timeline/audio.svg +7 -0
  15. package/demo/dist/icons/timeline/captions.svg +5 -0
  16. package/demo/dist/icons/timeline/composition.svg +12 -0
  17. package/demo/dist/icons/timeline/image.svg +18 -0
  18. package/demo/dist/icons/timeline/music.svg +10 -0
  19. package/demo/dist/icons/timeline/text.svg +3 -0
  20. package/demo/dist/index.html +15 -0
  21. package/dist/src/account-pages-legacy.js +9396 -0
  22. package/dist/src/account-pages.js +61 -0
  23. package/dist/src/app.js +14378 -0
  24. package/dist/src/cli.js +1 -1
  25. package/dist/src/composition-runtime.js +613 -0
  26. package/dist/src/config.js +166 -0
  27. package/dist/src/context.js +447 -0
  28. package/dist/src/dev-app-legacy.js +739 -0
  29. package/dist/src/dev-app.js +6 -0
  30. package/dist/src/domain.js +2 -0
  31. package/dist/src/editor-chat-history.js +82 -0
  32. package/dist/src/editor-chat.js +449 -0
  33. package/dist/src/editor-dark-theme.js +1128 -0
  34. package/dist/src/frontend/debug.js +71 -0
  35. package/dist/src/frontend/flockposter-cache-store.js +124 -0
  36. package/dist/src/frontend/homepage-client.js +182 -0
  37. package/dist/src/frontend/homepage-shared.js +4 -0
  38. package/dist/src/frontend/homepage-store.js +28 -0
  39. package/dist/src/frontend/homepage-view.js +547 -0
  40. package/dist/src/frontend/page-runtime-client.js +132 -0
  41. package/dist/src/frontend/page-runtime-store.js +9 -0
  42. package/dist/src/frontend/sentry.js +42 -0
  43. package/dist/src/frontend/template-editor-chat.js +3960 -0
  44. package/dist/src/help-page.js +346 -0
  45. package/dist/src/homepage.js +1235 -0
  46. package/dist/src/hyperframes/composition.js +180 -0
  47. package/dist/src/index.js +16 -0
  48. package/dist/src/instrument.js +30 -0
  49. package/dist/src/lib/crypto.js +45 -0
  50. package/dist/src/lib/dev-log.js +54 -0
  51. package/dist/src/lib/display-name.js +11 -0
  52. package/dist/src/lib/ids.js +24 -0
  53. package/dist/src/lib/images.js +19 -0
  54. package/dist/src/lib/json.js +15 -0
  55. package/dist/src/lib/package-root.js +47 -0
  56. package/dist/src/lib/template-paths.js +28 -0
  57. package/dist/src/lib/time.js +7 -0
  58. package/dist/src/lib/url-clean.js +85 -0
  59. package/dist/src/page-runtime.js +2 -0
  60. package/dist/src/page-shell.js +1381 -0
  61. package/dist/src/primitive-context.js +357 -0
  62. package/dist/src/primitive-registry.js +2436 -0
  63. package/dist/src/primitive-sdk.js +4 -0
  64. package/dist/src/primitives/hyperframes-media.js +108 -0
  65. package/dist/src/react-page-shell.js +35 -0
  66. package/dist/src/ready-post-schedule-component.js +1540 -0
  67. package/dist/src/registry.js +296 -0
  68. package/dist/src/runtime.js +35 -0
  69. package/dist/src/services/api-call-history.js +249 -0
  70. package/dist/src/services/auth.js +152 -0
  71. package/dist/src/services/billing-pricing.js +39 -0
  72. package/dist/src/services/billing.js +228 -0
  73. package/dist/src/services/cast.js +127 -0
  74. package/dist/src/services/chat-threads.js +92 -0
  75. package/dist/src/services/composition-sanitize.js +124 -0
  76. package/dist/src/services/composition-watch.js +79 -0
  77. package/dist/src/services/fork-access.js +93 -0
  78. package/dist/src/services/fork-manifest.js +42 -0
  79. package/dist/src/services/ghostcut.js +179 -0
  80. package/dist/src/services/hyperframes.js +2307 -0
  81. package/dist/src/services/job-capacity.js +14 -0
  82. package/dist/src/services/job-logs.js +197 -0
  83. package/dist/src/services/jobs.js +136 -0
  84. package/dist/src/services/local-dynamo.js +0 -0
  85. package/dist/src/services/media-processing.js +766 -0
  86. package/dist/src/services/primitive-media-lambda.js +280 -0
  87. package/dist/src/services/providers.js +2926 -0
  88. package/dist/src/services/rate-limits.js +262 -0
  89. package/dist/src/services/serverless-auth.js +382 -0
  90. package/dist/src/services/serverless-jobs.js +1082 -0
  91. package/dist/src/services/serverless-provider-keys.js +409 -0
  92. package/dist/src/services/serverless-records.js +1385 -0
  93. package/dist/src/services/serverless-template-configs.js +75 -0
  94. package/dist/src/services/storage.js +383 -0
  95. package/dist/src/services/template-certification.js +413 -0
  96. package/dist/src/services/template-loader.js +99 -0
  97. package/dist/src/services/template-runtime-bundles.js +217 -0
  98. package/dist/src/services/template-sources.js +1017 -0
  99. package/dist/src/services/video-normalization.js +2 -0
  100. package/dist/src/services/webhooks.js +62 -0
  101. package/dist/src/template-editor-pages.js +2576 -0
  102. package/dist/src/template-editor-shell.js +2840 -0
  103. package/dist/src/template-sdk.js +4 -0
  104. package/dist/src/worker.js +17 -0
  105. package/package.json +6 -4
  106. package/public/assets/homepage-app.js +54 -0
  107. package/public/assets/homepage-client-app.js +80 -0
  108. package/public/assets/page-runtime-client-app.js +94 -0
  109. package/src/assets/SELLING_AWARENESS_STAGES.md +579 -0
  110. package/src/assets/SELLING_WITH_HOOKS.md +377 -0
  111. package/src/assets/SELLING_WITH_VSLS.md +606 -0
  112. package/src/assets/favicon.ico +0 -0
  113. package/src/assets/logo-vidfarm.png +0 -0
@@ -0,0 +1,280 @@
1
+ import { concatAudioAssets, concatVideoAssets, estimateNormalizationCostUsd, extractAudioFromVideoAsset, extractVideoFrameAsset, muteVideoAsset, normalizeAudioAsset, normalizeVideoAsset, probeMediaAsset, renderSlidesVideoAsset, replaceVideoAudioAsset, trimAudioAsset, trimVideoAsset } from "./media-processing.js";
2
+ import { config } from "../config.js";
3
+ export class PrimitiveMediaLambdaService {
4
+ async execute(input) {
5
+ if (config.VIDFARM_PRIMITIVE_MEDIA_LAMBDA_URL && config.VIDFARM_PRIMITIVE_MEDIA_LAMBDA_SECRET) {
6
+ return this.executeRemote(input);
7
+ }
8
+ return this.executeLocal(input);
9
+ }
10
+ async executeRemote(input) {
11
+ const response = await fetch(config.VIDFARM_PRIMITIVE_MEDIA_LAMBDA_URL, {
12
+ method: "POST",
13
+ headers: {
14
+ "content-type": "application/json",
15
+ "x-vidfarm-media-secret": config.VIDFARM_PRIMITIVE_MEDIA_LAMBDA_SECRET
16
+ },
17
+ body: JSON.stringify({
18
+ output_key: input.outputKey,
19
+ operation: input.operation,
20
+ payload: input.payload
21
+ })
22
+ });
23
+ const payload = await response.json().catch(() => null);
24
+ if (!response.ok || !payload?.storage_key || !payload.content_type) {
25
+ throw new Error(payload?.error || `Primitive media Lambda failed with HTTP ${response.status}.`);
26
+ }
27
+ const billingCostCenterSlug = input.operation === "video_normalize"
28
+ ? "video_normalization"
29
+ : "primitive_media_lambda";
30
+ return {
31
+ storageKey: payload.storage_key,
32
+ publicUrl: payload.public_url ?? null,
33
+ contentType: payload.content_type,
34
+ bytes: Number(payload.bytes ?? 0),
35
+ metadata: payload.metadata ?? {},
36
+ billingCostUsd: Number(payload.billing?.cost_usd ?? 0),
37
+ billingCostCenterSlug,
38
+ billingMetadata: {
39
+ operation: input.operation,
40
+ mode: "lambda",
41
+ duration_ms: Number(payload.billing?.duration_ms ?? 0)
42
+ }
43
+ };
44
+ }
45
+ async executeLocal(input) {
46
+ const startedAt = Date.now();
47
+ const result = await runLocalPrimitiveMediaOperation(input.operation, input.payload);
48
+ const stored = await input.storeLocal(input.localOutputKey, result.bytes, result.contentType);
49
+ return {
50
+ storageKey: stored.key,
51
+ publicUrl: stored.url,
52
+ contentType: result.contentType,
53
+ bytes: result.bytes.byteLength,
54
+ metadata: result.metadata,
55
+ billingCostUsd: result.billingCostUsd ?? estimateLocalLambdaEquivalentUsd(Date.now() - startedAt),
56
+ billingCostCenterSlug: input.operation === "video_normalize" ? "video_normalization" : "primitive_media_lambda",
57
+ billingMetadata: {
58
+ operation: input.operation,
59
+ mode: "local_fallback",
60
+ duration_ms: Date.now() - startedAt
61
+ }
62
+ };
63
+ }
64
+ }
65
+ async function runLocalPrimitiveMediaOperation(operation, payload) {
66
+ switch (operation) {
67
+ case "video_normalize": {
68
+ const result = await normalizeVideoAsset({
69
+ sourceUrl: readRequiredUrl(payload.source_video_url ?? payload.sourceUrl),
70
+ maxWidth: readOptionalInt(payload.max_width ?? payload.maxWidth),
71
+ maxHeight: readOptionalInt(payload.max_height ?? payload.maxHeight),
72
+ crf: readOptionalInt(payload.crf),
73
+ preset: readOptionalPreset(payload.preset),
74
+ maxVideoBitrateKbps: readOptionalInt(payload.max_video_bitrate_kbps ?? payload.maxVideoBitrateKbps),
75
+ audioBitrateKbps: readOptionalInt(payload.audio_bitrate_kbps ?? payload.audioBitrateKbps)
76
+ });
77
+ return {
78
+ bytes: result.bytes,
79
+ contentType: result.contentType,
80
+ metadata: result.metadata,
81
+ billingCostUsd: estimateNormalizationCostUsd(result.metadata)
82
+ };
83
+ }
84
+ case "video_render_slides": {
85
+ const result = await renderSlidesVideoAsset({
86
+ slides: readSlides(payload.slides),
87
+ width: Math.max(16, readOptionalInt(payload.width) ?? 1080),
88
+ height: Math.max(16, readOptionalInt(payload.height) ?? 1920),
89
+ backgroundColor: readString(payload.background_color ?? payload.backgroundColor) || "#000000",
90
+ defaultFit: readOptionalFit(payload.default_fit ?? payload.defaultFit) ?? "cover"
91
+ });
92
+ return {
93
+ bytes: result.bytes,
94
+ contentType: result.contentType,
95
+ metadata: result.metadata
96
+ };
97
+ }
98
+ case "video_trim": {
99
+ const result = await trimVideoAsset({
100
+ sourceUrl: readRequiredUrl(payload.source_video_url ?? payload.sourceUrl),
101
+ startMs: readOptionalInt(payload.start_ms ?? payload.startMs),
102
+ endMs: readOptionalInt(payload.end_ms ?? payload.endMs),
103
+ durationMs: readOptionalInt(payload.duration_ms ?? payload.durationMs),
104
+ maxWidth: readOptionalInt(payload.max_width ?? payload.maxWidth),
105
+ maxHeight: readOptionalInt(payload.max_height ?? payload.maxHeight),
106
+ crf: readOptionalInt(payload.crf),
107
+ preset: readOptionalPreset(payload.preset),
108
+ audioBitrateKbps: readOptionalInt(payload.audio_bitrate_kbps ?? payload.audioBitrateKbps)
109
+ });
110
+ return { bytes: result.bytes, contentType: result.contentType, metadata: result.metadata };
111
+ }
112
+ case "video_extract_audio": {
113
+ const result = await extractAudioFromVideoAsset({
114
+ sourceUrl: readRequiredUrl(payload.source_video_url ?? payload.sourceUrl),
115
+ format: readOptionalAudioFormat(payload.output_format ?? payload.outputFormat),
116
+ bitrateKbps: readOptionalInt(payload.audio_bitrate_kbps ?? payload.audioBitrateKbps)
117
+ });
118
+ return { bytes: result.bytes, contentType: result.contentType, metadata: result.metadata };
119
+ }
120
+ case "audio_trim": {
121
+ const result = await trimAudioAsset({
122
+ sourceUrl: readRequiredUrl(payload.source_audio_url ?? payload.sourceUrl),
123
+ startMs: readOptionalInt(payload.start_ms ?? payload.startMs),
124
+ endMs: readOptionalInt(payload.end_ms ?? payload.endMs),
125
+ durationMs: readOptionalInt(payload.duration_ms ?? payload.durationMs),
126
+ format: readOptionalAudioFormat(payload.output_format ?? payload.outputFormat),
127
+ bitrateKbps: readOptionalInt(payload.audio_bitrate_kbps ?? payload.audioBitrateKbps)
128
+ });
129
+ return { bytes: result.bytes, contentType: result.contentType, metadata: result.metadata };
130
+ }
131
+ case "video_probe":
132
+ case "audio_probe": {
133
+ const result = await probeMediaAsset({
134
+ sourceUrl: readRequiredUrl(payload.source_video_url
135
+ ?? payload.source_audio_url
136
+ ?? payload.source_url
137
+ ?? payload.sourceUrl)
138
+ });
139
+ return {
140
+ bytes: Buffer.from(JSON.stringify(result.metadata, null, 2), "utf8"),
141
+ contentType: "application/json",
142
+ metadata: result.metadata
143
+ };
144
+ }
145
+ case "video_extract_frame": {
146
+ const result = await extractVideoFrameAsset({
147
+ sourceUrl: readRequiredUrl(payload.source_video_url ?? payload.sourceUrl),
148
+ atMs: readOptionalInt(payload.at_ms ?? payload.atMs),
149
+ format: readOptionalImageFormat(payload.output_format ?? payload.outputFormat)
150
+ });
151
+ return { bytes: result.bytes, contentType: result.contentType, metadata: result.metadata };
152
+ }
153
+ case "video_mute": {
154
+ const result = await muteVideoAsset({ sourceUrl: readRequiredUrl(payload.source_video_url ?? payload.sourceUrl) });
155
+ return { bytes: result.bytes, contentType: result.contentType, metadata: result.metadata };
156
+ }
157
+ case "video_replace_audio": {
158
+ const result = await replaceVideoAudioAsset({
159
+ sourceVideoUrl: readRequiredUrl(payload.source_video_url ?? payload.sourceVideoUrl),
160
+ audioUrl: readRequiredUrl(payload.source_audio_url ?? payload.audio_url ?? payload.audioUrl),
161
+ audioBitrateKbps: readOptionalInt(payload.audio_bitrate_kbps ?? payload.audioBitrateKbps)
162
+ });
163
+ return { bytes: result.bytes, contentType: result.contentType, metadata: result.metadata };
164
+ }
165
+ case "video_concat": {
166
+ const result = await concatVideoAssets({
167
+ sourceUrls: readRequiredUrlArray(payload.source_video_urls ?? payload.sourceUrls),
168
+ width: readOptionalInt(payload.width),
169
+ height: readOptionalInt(payload.height),
170
+ fit: readOptionalFit(payload.fit),
171
+ backgroundColor: readString(payload.background_color ?? payload.backgroundColor) || undefined
172
+ });
173
+ return { bytes: result.bytes, contentType: result.contentType, metadata: result.metadata };
174
+ }
175
+ case "audio_concat": {
176
+ const result = await concatAudioAssets({
177
+ sourceUrls: readRequiredUrlArray(payload.source_audio_urls ?? payload.sourceUrls),
178
+ format: readOptionalAudioFormat(payload.output_format ?? payload.outputFormat),
179
+ bitrateKbps: readOptionalInt(payload.audio_bitrate_kbps ?? payload.audioBitrateKbps)
180
+ });
181
+ return { bytes: result.bytes, contentType: result.contentType, metadata: result.metadata };
182
+ }
183
+ case "audio_normalize": {
184
+ const result = await normalizeAudioAsset({
185
+ sourceUrl: readRequiredUrl(payload.source_audio_url ?? payload.sourceUrl),
186
+ format: readOptionalAudioFormat(payload.output_format ?? payload.outputFormat),
187
+ bitrateKbps: readOptionalInt(payload.audio_bitrate_kbps ?? payload.audioBitrateKbps),
188
+ sampleRateHz: readOptionalInt(payload.sample_rate_hz ?? payload.sampleRateHz)
189
+ });
190
+ return { bytes: result.bytes, contentType: result.contentType, metadata: result.metadata };
191
+ }
192
+ }
193
+ }
194
+ function estimateLocalLambdaEquivalentUsd(durationMs) {
195
+ const gbSeconds = 2 * (Math.max(1, durationMs) / 1000);
196
+ const computeCost = gbSeconds * 0.0000166667;
197
+ const requestCost = 0.20 / 1_000_000;
198
+ return Number((computeCost + requestCost).toFixed(6));
199
+ }
200
+ function readRequiredUrl(value) {
201
+ const text = readString(value);
202
+ if (!text) {
203
+ throw new Error("A source URL is required.");
204
+ }
205
+ new URL(text);
206
+ return text;
207
+ }
208
+ function readRequiredUrlArray(value) {
209
+ if (!Array.isArray(value) || !value.length) {
210
+ throw new Error("At least one source URL is required.");
211
+ }
212
+ return value.map((entry) => readRequiredUrl(entry));
213
+ }
214
+ function readOptionalInt(value) {
215
+ if (value == null || value === "")
216
+ return undefined;
217
+ const parsed = Number.parseInt(String(value), 10);
218
+ if (!Number.isFinite(parsed)) {
219
+ throw new Error(`Invalid integer value "${String(value)}".`);
220
+ }
221
+ return parsed;
222
+ }
223
+ function readOptionalPreset(value) {
224
+ const text = readString(value);
225
+ if (!text)
226
+ return undefined;
227
+ if (text === "veryfast" || text === "faster" || text === "fast" || text === "medium") {
228
+ return text;
229
+ }
230
+ throw new Error(`Unsupported preset "${text}".`);
231
+ }
232
+ function readOptionalFit(value) {
233
+ const text = readString(value);
234
+ if (!text)
235
+ return undefined;
236
+ if (text === "cover" || text === "contain" || text === "fill") {
237
+ return text;
238
+ }
239
+ throw new Error(`Unsupported fit "${text}".`);
240
+ }
241
+ function readOptionalAudioFormat(value) {
242
+ const text = readString(value);
243
+ if (!text)
244
+ return undefined;
245
+ if (text === "mp3" || text === "wav" || text === "m4a") {
246
+ return text;
247
+ }
248
+ throw new Error(`Unsupported audio format "${text}".`);
249
+ }
250
+ function readOptionalImageFormat(value) {
251
+ const text = readString(value);
252
+ if (!text)
253
+ return undefined;
254
+ if (text === "png" || text === "jpeg") {
255
+ return text;
256
+ }
257
+ throw new Error(`Unsupported image format "${text}".`);
258
+ }
259
+ function readSlides(value) {
260
+ if (!Array.isArray(value) || !value.length) {
261
+ throw new Error("At least one slide is required.");
262
+ }
263
+ return value.map((slide, index) => {
264
+ if (!slide || typeof slide !== "object" || Array.isArray(slide)) {
265
+ throw new Error(`Invalid slide at index ${index}.`);
266
+ }
267
+ const entry = slide;
268
+ return {
269
+ mediaUrl: readRequiredUrl(entry.media_url ?? entry.mediaUrl ?? entry.image_url ?? entry.imageUrl ?? entry.video_url ?? entry.videoUrl),
270
+ mediaType: readString(entry.media_type ?? entry.mediaType) === "video" ? "video" : "image",
271
+ durationMs: Math.max(100, readOptionalInt(entry.duration_ms ?? entry.durationMs) ?? 1000),
272
+ fit: readOptionalFit(entry.fit) ?? "cover",
273
+ backgroundColor: readString(entry.background_color ?? entry.backgroundColor) || "#000000"
274
+ };
275
+ });
276
+ }
277
+ function readString(value) {
278
+ return typeof value === "string" ? value.trim() : "";
279
+ }
280
+ //# sourceMappingURL=primitive-media-lambda.js.map