@meframe/core 0.1.0 → 0.1.2
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.
- package/dist/cache/CacheManager.d.ts +2 -2
- package/dist/cache/CacheManager.d.ts.map +1 -1
- package/dist/cache/CacheManager.js +4 -4
- package/dist/cache/CacheManager.js.map +1 -1
- package/dist/cache/l1/AudioL1Cache.d.ts +5 -2
- package/dist/cache/l1/AudioL1Cache.d.ts.map +1 -1
- package/dist/cache/l1/AudioL1Cache.js +7 -3
- package/dist/cache/l1/AudioL1Cache.js.map +1 -1
- package/dist/controllers/PlaybackController.d.ts.map +1 -1
- package/dist/controllers/PlaybackController.js +1 -1
- package/dist/controllers/PlaybackController.js.map +1 -1
- package/dist/model/CompositionModel.d.ts.map +1 -1
- package/dist/model/CompositionModel.js +4 -5
- package/dist/model/CompositionModel.js.map +1 -1
- package/dist/model/types.d.ts +6 -0
- package/dist/model/types.d.ts.map +1 -1
- package/dist/model/types.js.map +1 -1
- package/dist/orchestrator/CompositionPlanner.d.ts +0 -1
- package/dist/orchestrator/CompositionPlanner.d.ts.map +1 -1
- package/dist/orchestrator/CompositionPlanner.js +4 -12
- package/dist/orchestrator/CompositionPlanner.js.map +1 -1
- package/dist/orchestrator/ExportScheduler.d.ts.map +1 -1
- package/dist/orchestrator/ExportScheduler.js +2 -0
- package/dist/orchestrator/ExportScheduler.js.map +1 -1
- package/dist/orchestrator/GlobalAudioSession.d.ts +2 -2
- package/dist/orchestrator/GlobalAudioSession.d.ts.map +1 -1
- package/dist/orchestrator/GlobalAudioSession.js +11 -6
- package/dist/orchestrator/GlobalAudioSession.js.map +1 -1
- package/dist/orchestrator/Orchestrator.d.ts.map +1 -1
- package/dist/orchestrator/Orchestrator.js +2 -7
- package/dist/orchestrator/Orchestrator.js.map +1 -1
- package/dist/stages/compose/LayerRenderer.d.ts +5 -0
- package/dist/stages/compose/LayerRenderer.d.ts.map +1 -1
- package/dist/stages/compose/LayerRenderer.js +91 -89
- package/dist/stages/compose/LayerRenderer.js.map +1 -1
- package/dist/stages/compose/instructions.d.ts +6 -6
- package/dist/stages/compose/instructions.d.ts.map +1 -1
- package/dist/stages/compose/types.d.ts +6 -0
- package/dist/stages/compose/types.d.ts.map +1 -1
- package/dist/workers/stages/compose/{video-compose.worker.B-_C-_y6.js → video-compose.worker.C8728Oi3.js} +97 -98
- package/dist/workers/stages/compose/video-compose.worker.C8728Oi3.js.map +1 -0
- package/dist/workers/worker-manifest.json +1 -1
- package/package.json +1 -1
- package/dist/workers/stages/compose/video-compose.worker.B-_C-_y6.js.map +0 -1
|
@@ -74,41 +74,46 @@ class LayerRenderer {
|
|
|
74
74
|
const parsed = parseFloat(strValue);
|
|
75
75
|
return isNaN(parsed) ? void 0 : parsed;
|
|
76
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Calculate dimensions from renderConfig
|
|
79
|
+
* Returns dimensions maintaining aspect ratio when only one dimension is specified
|
|
80
|
+
*/
|
|
81
|
+
calculateDimensionsFromConfig(sourceWidth, sourceHeight, renderConfig) {
|
|
82
|
+
if (!renderConfig) {
|
|
83
|
+
return { width: sourceWidth, height: sourceHeight };
|
|
84
|
+
}
|
|
85
|
+
const width = this.parseDimension(renderConfig.width, this.width);
|
|
86
|
+
const height = this.parseDimension(renderConfig.height, this.height);
|
|
87
|
+
if (width && height) {
|
|
88
|
+
return { width, height };
|
|
89
|
+
} else if (width) {
|
|
90
|
+
return {
|
|
91
|
+
width,
|
|
92
|
+
height: Math.round(sourceHeight / sourceWidth * width)
|
|
93
|
+
};
|
|
94
|
+
} else if (height) {
|
|
95
|
+
return {
|
|
96
|
+
width: Math.round(sourceWidth / sourceHeight * height),
|
|
97
|
+
height
|
|
98
|
+
};
|
|
99
|
+
} else {
|
|
100
|
+
return { width: sourceWidth, height: sourceHeight };
|
|
101
|
+
}
|
|
102
|
+
}
|
|
77
103
|
getLayerDimensions(layer) {
|
|
78
104
|
if (layer.type === "image") {
|
|
79
105
|
const imageLayer = layer;
|
|
80
106
|
if (imageLayer.source) {
|
|
81
107
|
const imgWidth = imageLayer.source.width;
|
|
82
108
|
const imgHeight = imageLayer.source.height;
|
|
83
|
-
|
|
84
|
-
if (isAttachment) {
|
|
85
|
-
const targetWidthRaw = imageLayer.targetWidth;
|
|
86
|
-
const targetHeightRaw = imageLayer.targetHeight;
|
|
87
|
-
const targetWidth = this.parseDimension(targetWidthRaw, this.width);
|
|
88
|
-
const targetHeight = this.parseDimension(targetHeightRaw, this.height);
|
|
89
|
-
if (targetWidth && targetHeight) {
|
|
90
|
-
return { width: targetWidth, height: targetHeight };
|
|
91
|
-
} else if (targetWidth) {
|
|
92
|
-
return {
|
|
93
|
-
width: targetWidth,
|
|
94
|
-
height: imgHeight / imgWidth * targetWidth
|
|
95
|
-
};
|
|
96
|
-
} else if (targetHeight) {
|
|
97
|
-
return {
|
|
98
|
-
width: imgWidth / imgHeight * targetHeight,
|
|
99
|
-
height: targetHeight
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
return { width: imgWidth, height: imgHeight };
|
|
109
|
+
return this.calculateDimensionsFromConfig(imgWidth, imgHeight, imageLayer.renderConfig);
|
|
104
110
|
}
|
|
105
111
|
} else if (layer.type === "video") {
|
|
106
112
|
const videoLayer = layer;
|
|
107
113
|
const videoFrame = videoLayer.videoFrame;
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
};
|
|
114
|
+
const videoWidth = videoFrame.displayWidth || videoFrame.codedWidth;
|
|
115
|
+
const videoHeight = videoFrame.displayHeight || videoFrame.codedHeight;
|
|
116
|
+
return this.calculateDimensionsFromConfig(videoWidth, videoHeight, videoLayer.renderConfig);
|
|
112
117
|
}
|
|
113
118
|
return { width: this.width, height: this.height };
|
|
114
119
|
}
|
|
@@ -153,11 +158,27 @@ class LayerRenderer {
|
|
|
153
158
|
this.ctx.translate(-centerX, -centerY);
|
|
154
159
|
}
|
|
155
160
|
renderVideoLayer(layer) {
|
|
156
|
-
const { videoFrame, crop } = layer;
|
|
161
|
+
const { videoFrame, crop, renderConfig } = layer;
|
|
157
162
|
const videoWidth = videoFrame.displayWidth || videoFrame.codedWidth;
|
|
158
163
|
const videoHeight = videoFrame.displayHeight || videoFrame.codedHeight;
|
|
159
|
-
|
|
160
|
-
|
|
164
|
+
let renderX;
|
|
165
|
+
let renderY;
|
|
166
|
+
let renderWidth;
|
|
167
|
+
let renderHeight;
|
|
168
|
+
if (renderConfig) {
|
|
169
|
+
const dimensions = this.calculateDimensionsFromConfig(videoWidth, videoHeight, renderConfig);
|
|
170
|
+
renderWidth = dimensions.width;
|
|
171
|
+
renderHeight = dimensions.height;
|
|
172
|
+
renderX = Math.round((this.width - renderWidth) / 2);
|
|
173
|
+
renderY = Math.round((this.height - renderHeight) / 2);
|
|
174
|
+
} else {
|
|
175
|
+
const naturalScale = this.height / videoHeight;
|
|
176
|
+
const dimensions = this.calculateRenderDimensions(videoWidth, videoHeight, naturalScale);
|
|
177
|
+
renderX = dimensions.x;
|
|
178
|
+
renderY = dimensions.y;
|
|
179
|
+
renderWidth = dimensions.width;
|
|
180
|
+
renderHeight = dimensions.height;
|
|
181
|
+
}
|
|
161
182
|
if (crop) {
|
|
162
183
|
this.ctx.drawImage(
|
|
163
184
|
videoFrame,
|
|
@@ -165,23 +186,17 @@ class LayerRenderer {
|
|
|
165
186
|
crop.y,
|
|
166
187
|
crop.width,
|
|
167
188
|
crop.height,
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
189
|
+
renderX,
|
|
190
|
+
renderY,
|
|
191
|
+
renderWidth,
|
|
192
|
+
renderHeight
|
|
172
193
|
);
|
|
173
194
|
} else {
|
|
174
|
-
this.ctx.drawImage(
|
|
175
|
-
videoFrame,
|
|
176
|
-
dimensions.x,
|
|
177
|
-
dimensions.y,
|
|
178
|
-
dimensions.width,
|
|
179
|
-
dimensions.height
|
|
180
|
-
);
|
|
195
|
+
this.ctx.drawImage(videoFrame, renderX, renderY, renderWidth, renderHeight);
|
|
181
196
|
}
|
|
182
197
|
}
|
|
183
198
|
renderImageLayer(layer) {
|
|
184
|
-
const { source, crop } = layer;
|
|
199
|
+
const { source, crop, renderConfig } = layer;
|
|
185
200
|
if (source instanceof ImageData) {
|
|
186
201
|
if (crop) {
|
|
187
202
|
const tempCanvas = new OffscreenCanvas(crop.width, crop.height);
|
|
@@ -191,56 +206,43 @@ class LayerRenderer {
|
|
|
191
206
|
} else {
|
|
192
207
|
this.ctx.putImageData(source, 0, 0);
|
|
193
208
|
}
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
if (!source) return;
|
|
212
|
+
const imgWidth = source.width;
|
|
213
|
+
const imgHeight = source.height;
|
|
214
|
+
let renderX;
|
|
215
|
+
let renderY;
|
|
216
|
+
let renderWidth;
|
|
217
|
+
let renderHeight;
|
|
218
|
+
if (renderConfig) {
|
|
219
|
+
const dimensions = this.calculateDimensionsFromConfig(imgWidth, imgHeight, renderConfig);
|
|
220
|
+
renderWidth = dimensions.width;
|
|
221
|
+
renderHeight = dimensions.height;
|
|
222
|
+
renderX = 0;
|
|
223
|
+
renderY = 0;
|
|
194
224
|
} else {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
renderWidth = imgWidth / imgHeight * targetHeight;
|
|
217
|
-
} else {
|
|
218
|
-
renderWidth = imgWidth;
|
|
219
|
-
renderHeight = imgHeight;
|
|
220
|
-
}
|
|
221
|
-
} else {
|
|
222
|
-
const naturalScale = this.width / imgWidth;
|
|
223
|
-
const dimensions = this.calculateRenderDimensions(imgWidth, imgHeight, naturalScale);
|
|
224
|
-
renderWidth = dimensions.width;
|
|
225
|
-
renderHeight = dimensions.height;
|
|
226
|
-
}
|
|
227
|
-
const renderX = isAttachment ? 0 : Math.round((this.width - renderWidth) / 2);
|
|
228
|
-
const renderY = isAttachment ? 0 : Math.round((this.height - renderHeight) / 2);
|
|
229
|
-
if (crop) {
|
|
230
|
-
this.ctx.drawImage(
|
|
231
|
-
source,
|
|
232
|
-
crop.x,
|
|
233
|
-
crop.y,
|
|
234
|
-
crop.width,
|
|
235
|
-
crop.height,
|
|
236
|
-
renderX,
|
|
237
|
-
renderY,
|
|
238
|
-
renderWidth,
|
|
239
|
-
renderHeight
|
|
240
|
-
);
|
|
241
|
-
} else {
|
|
242
|
-
this.ctx.drawImage(source, renderX, renderY, renderWidth, renderHeight);
|
|
243
|
-
}
|
|
225
|
+
const naturalScale = this.width / imgWidth;
|
|
226
|
+
const dimensions = this.calculateRenderDimensions(imgWidth, imgHeight, naturalScale);
|
|
227
|
+
renderWidth = dimensions.width;
|
|
228
|
+
renderHeight = dimensions.height;
|
|
229
|
+
renderX = Math.round((this.width - renderWidth) / 2);
|
|
230
|
+
renderY = Math.round((this.height - renderHeight) / 2);
|
|
231
|
+
}
|
|
232
|
+
if (crop) {
|
|
233
|
+
this.ctx.drawImage(
|
|
234
|
+
source,
|
|
235
|
+
crop.x,
|
|
236
|
+
crop.y,
|
|
237
|
+
crop.width,
|
|
238
|
+
crop.height,
|
|
239
|
+
renderX,
|
|
240
|
+
renderY,
|
|
241
|
+
renderWidth,
|
|
242
|
+
renderHeight
|
|
243
|
+
);
|
|
244
|
+
} else {
|
|
245
|
+
this.ctx.drawImage(source, renderX, renderY, renderWidth, renderHeight);
|
|
244
246
|
}
|
|
245
247
|
}
|
|
246
248
|
renderTextLayer(layer) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LayerRenderer.js","sources":["../../../src/stages/compose/LayerRenderer.ts"],"sourcesContent":["import type { Layer, VideoLayer, ImageLayer, TextLayer, Transform2D, MaskConfig } from './types';\nimport { renderBasicText, renderTextWithEntrance } from './text-renderers/basic-text-renderer';\nimport { renderWordByWord } from './text-renderers/word-by-word-renderer';\nimport { renderCharacterKTV } from './text-renderers/character-ktv-renderer';\nimport { renderWordByWordFancy } from './text-renderers/word-fancy-renderer';\n\n/**\n * LayerRenderer - Handles rendering of individual layers\n * Single responsibility: Draw a single layer to the canvas context\n */\nexport class LayerRenderer {\n private ctx: OffscreenCanvasRenderingContext2D | CanvasRenderingContext2D;\n private width: number;\n private height: number;\n private currentFrame: number = 0;\n private fps: number = 30;\n private readonly FILL_THRESHOLD = 0.9;\n\n constructor(\n ctx: OffscreenCanvasRenderingContext2D | CanvasRenderingContext2D,\n width: number,\n height: number,\n fps: number = 30\n ) {\n this.ctx = ctx;\n this.width = width;\n this.height = height;\n this.fps = fps;\n this.ensureHighQualityRendering();\n }\n\n setCurrentFrame(frame: number): void {\n this.currentFrame = frame;\n }\n\n private ensureHighQualityRendering(): void {\n this.ctx.imageSmoothingEnabled = true;\n this.ctx.imageSmoothingQuality = 'high';\n }\n\n /**\n * Render a single layer with all its properties\n */\n renderLayer(layer: Layer): void {\n if (!layer.visible || layer.opacity <= 0) return;\n\n // Only save/restore context if layer has properties that need it\n const needsStateManagement =\n layer.opacity !== 1 || layer.blendMode || layer.transform || layer.mask;\n\n if (needsStateManagement) {\n this.ctx.save();\n }\n\n try {\n // Apply layer properties only when needed\n if (layer.opacity !== 1) {\n this.ctx.globalAlpha = layer.opacity;\n }\n\n if (layer.blendMode) {\n this.ctx.globalCompositeOperation = layer.blendMode;\n }\n\n if (layer.transform) {\n // Get layer dimensions for transform anchor calculation\n const layerDimensions = this.getLayerDimensions(layer);\n this.applyTransform(layer.transform, layerDimensions);\n }\n // Render based on layer type\n switch (layer.type) {\n case 'video':\n this.renderVideoLayer(layer as VideoLayer);\n break;\n case 'image':\n this.renderImageLayer(layer as ImageLayer);\n break;\n case 'text':\n this.renderTextLayer(layer as TextLayer);\n break;\n }\n\n // Apply mask if present\n if (layer.mask) {\n this.applyMask(layer.mask);\n }\n } finally {\n if (needsStateManagement) {\n this.ctx.restore();\n }\n }\n }\n\n private parseDimension(\n value: number | string | undefined,\n canvasSize: number\n ): number | undefined {\n if (value === undefined) return undefined;\n if (typeof value === 'number') return value;\n\n // value is string at this point\n const strValue = value as string;\n\n // Parse percentage string like \"5%\"\n if (strValue.includes('%')) {\n const numValue = parseFloat(strValue);\n return isNaN(numValue) ? undefined : (numValue / 100) * canvasSize;\n }\n\n // Parse as pixel value\n const parsed = parseFloat(strValue);\n return isNaN(parsed) ? undefined : parsed;\n }\n\n private getLayerDimensions(layer: Layer): { width: number; height: number } {\n if (layer.type === 'image') {\n const imageLayer = layer as ImageLayer;\n if (imageLayer.source) {\n const imgWidth = imageLayer.source.width;\n const imgHeight = imageLayer.source.height;\n\n // For attachment layers with target dimensions, calculate rendered size\n const isAttachment = !!imageLayer.attachmentId;\n if (isAttachment) {\n const targetWidthRaw = (imageLayer as any).targetWidth;\n const targetHeightRaw = (imageLayer as any).targetHeight;\n\n // Parse dimensions (supports both pixels and percentages)\n const targetWidth = this.parseDimension(targetWidthRaw, this.width);\n const targetHeight = this.parseDimension(targetHeightRaw, this.height);\n\n if (targetWidth && targetHeight) {\n return { width: targetWidth, height: targetHeight };\n } else if (targetWidth) {\n return {\n width: targetWidth,\n height: (imgHeight / imgWidth) * targetWidth,\n };\n } else if (targetHeight) {\n return {\n width: (imgWidth / imgHeight) * targetHeight,\n height: targetHeight,\n };\n }\n }\n\n // No scaling, return original dimensions\n return { width: imgWidth, height: imgHeight };\n }\n } else if (layer.type === 'video') {\n const videoLayer = layer as VideoLayer;\n const videoFrame = videoLayer.videoFrame;\n return {\n width: videoFrame.displayWidth || videoFrame.codedWidth,\n height: videoFrame.displayHeight || videoFrame.codedHeight,\n };\n }\n // Default to canvas dimensions\n return { width: this.width, height: this.height };\n }\n\n /**\n * Calculate render dimensions with smart fill logic\n * @param sourceWidth Source width\n * @param sourceHeight Source height\n * @param naturalScale Natural scale factor (scaleY for video, scaleX for image)\n * @returns Render dimensions and position\n */\n private calculateRenderDimensions(\n sourceWidth: number,\n sourceHeight: number,\n naturalScale: number\n ): { width: number; height: number; x: number; y: number } {\n const scaledWidth = sourceWidth * naturalScale;\n const scaledHeight = sourceHeight * naturalScale;\n\n // Smart fill: when scaled size is close to container (>90%), use cover mode\n const shouldFill =\n scaledWidth / this.width > this.FILL_THRESHOLD &&\n scaledHeight / this.height > this.FILL_THRESHOLD;\n\n let renderWidth: number;\n let renderHeight: number;\n\n if (shouldFill) {\n // Cover mode: use Math.max to ensure entire canvas is covered while maintaining aspect ratio\n const coverScale = Math.max(this.width / sourceWidth, this.height / sourceHeight);\n renderWidth = Math.round(sourceWidth * coverScale);\n renderHeight = Math.round(sourceHeight * coverScale);\n } else {\n // Natural scale mode: use scaled dimensions\n renderWidth = Math.round(scaledWidth);\n renderHeight = Math.round(scaledHeight);\n }\n\n // Center the content\n const renderX = Math.round((this.width - renderWidth) / 2);\n const renderY = Math.round((this.height - renderHeight) / 2);\n\n return { width: renderWidth, height: renderHeight, x: renderX, y: renderY };\n }\n\n private applyTransform(\n transform: Transform2D,\n layerDimensions: { width: number; height: number }\n ): void {\n // Use layer dimensions (not canvas dimensions) for anchor calculation\n const anchorX = transform.anchorX ?? 0.5;\n const anchorY = transform.anchorY ?? 0.5;\n const centerX = layerDimensions.width * anchorX;\n const centerY = layerDimensions.height * anchorY;\n\n // Move to the layer position + anchor offset\n this.ctx.translate(transform.x + centerX, transform.y + centerY);\n\n if (transform.rotation) {\n this.ctx.rotate(transform.rotation);\n }\n\n this.ctx.scale(transform.scaleX, transform.scaleY);\n\n if (transform.skewX || transform.skewY) {\n this.ctx.transform(1, transform.skewY ?? 0, transform.skewX ?? 0, 1, 0, 0);\n }\n\n // Move back by anchor offset\n this.ctx.translate(-centerX, -centerY);\n }\n\n private renderVideoLayer(layer: VideoLayer): void {\n const { videoFrame, crop } = layer;\n\n // Get video dimensions\n const videoWidth = videoFrame.displayWidth || videoFrame.codedWidth;\n const videoHeight = videoFrame.displayHeight || videoFrame.codedHeight;\n\n // Video uses scaleY (height-based scaling) to match legacy behavior\n const naturalScale = this.height / videoHeight;\n const dimensions = this.calculateRenderDimensions(videoWidth, videoHeight, naturalScale);\n\n if (crop) {\n this.ctx.drawImage(\n videoFrame,\n crop.x,\n crop.y,\n crop.width,\n crop.height,\n dimensions.x,\n dimensions.y,\n dimensions.width,\n dimensions.height\n );\n } else {\n this.ctx.drawImage(\n videoFrame,\n dimensions.x,\n dimensions.y,\n dimensions.width,\n dimensions.height\n );\n }\n // NOTE: Do not close videoFrame - it's managed by RcFrame wrapper\n }\n\n private renderImageLayer(layer: ImageLayer): void {\n const { source, crop } = layer;\n\n // Handle ImageData by putting it on canvas first\n if (source instanceof ImageData) {\n if (crop) {\n // For ImageData with crop, we need to extract the cropped region\n const tempCanvas = new OffscreenCanvas(crop.width, crop.height);\n const tempCtx = tempCanvas.getContext('2d')!;\n tempCtx.putImageData(source, -crop.x, -crop.y);\n this.ctx.drawImage(tempCanvas, 0, 0, this.width, this.height);\n } else {\n // Put ImageData directly\n this.ctx.putImageData(source, 0, 0);\n }\n } else {\n // ImageBitmap can be drawn directly\n if (!source) {\n return;\n }\n\n // Determine if this is an attachment layer (has attachmentId)\n const isAttachment = !!layer.attachmentId;\n const imgWidth = source.width;\n const imgHeight = source.height;\n\n let renderWidth: number;\n let renderHeight: number;\n\n if (isAttachment) {\n // Attachment images use original size (or targetWidth/targetHeight if specified)\n const targetWidthRaw = (layer as any).targetWidth;\n const targetHeightRaw = (layer as any).targetHeight;\n\n // Parse dimensions (supports both pixels and percentages)\n const targetWidth = this.parseDimension(targetWidthRaw, this.width);\n const targetHeight = this.parseDimension(targetHeightRaw, this.height);\n\n if (targetWidth && targetHeight) {\n // Both specified, use as-is\n renderWidth = targetWidth;\n renderHeight = targetHeight;\n } else if (targetWidth) {\n // Only width specified, maintain aspect ratio\n renderWidth = targetWidth;\n renderHeight = (imgHeight / imgWidth) * targetWidth;\n } else if (targetHeight) {\n // Only height specified, maintain aspect ratio\n renderHeight = targetHeight;\n renderWidth = (imgWidth / imgHeight) * targetHeight;\n } else {\n // No target size, use original\n renderWidth = imgWidth;\n renderHeight = imgHeight;\n }\n } else {\n // Main track images use scaleX (width-based scaling) to match legacy behavior\n const naturalScale = this.width / imgWidth;\n const dimensions = this.calculateRenderDimensions(imgWidth, imgHeight, naturalScale);\n renderWidth = dimensions.width;\n renderHeight = dimensions.height;\n }\n\n // Calculate render position (center for main track images, origin for attachments)\n const renderX = isAttachment ? 0 : Math.round((this.width - renderWidth) / 2);\n const renderY = isAttachment ? 0 : Math.round((this.height - renderHeight) / 2);\n\n if (crop) {\n this.ctx.drawImage(\n source,\n crop.x,\n crop.y,\n crop.width,\n crop.height,\n renderX,\n renderY,\n renderWidth,\n renderHeight\n );\n } else {\n this.ctx.drawImage(source, renderX, renderY, renderWidth, renderHeight);\n }\n }\n }\n\n private renderTextLayer(layer: TextLayer): void {\n const animationType = layer.animation?.type;\n const hasWordTimings = layer.wordTimings && layer.wordTimings.length > 0;\n\n const needsWordTimings = ['wordByWord', 'characterKTV', 'wordByWordFancy'].includes(\n animationType || ''\n );\n\n if (needsWordTimings && !hasWordTimings) {\n renderBasicText(this.ctx, layer, this.width, this.height, this.currentFrame);\n return;\n }\n\n switch (animationType) {\n case 'wordByWord':\n renderWordByWord(this.ctx, layer, this.width, this.height, this.currentFrame, this.fps);\n break;\n case 'characterKTV':\n renderCharacterKTV(this.ctx, layer, this.width, this.height, this.currentFrame, this.fps);\n break;\n case 'wordByWordFancy':\n renderWordByWordFancy(\n this.ctx,\n layer,\n this.width,\n this.height,\n this.currentFrame,\n this.fps\n );\n break;\n case 'fade':\n renderTextWithEntrance(this.ctx, layer, this.width, this.height, this.currentFrame);\n break;\n default:\n renderBasicText(this.ctx, layer, this.width, this.height, this.currentFrame);\n break;\n }\n }\n\n private applyMask(mask: MaskConfig): void {\n this.ctx.globalCompositeOperation = mask.invert ? 'source-out' : 'destination-in';\n\n if (mask.source) {\n this.ctx.drawImage(mask.source, 0, 0, this.width, this.height);\n } else if (mask.shape === 'circle') {\n this.ctx.beginPath();\n this.ctx.arc(\n this.width / 2,\n this.height / 2,\n Math.min(this.width, this.height) / 2,\n 0,\n Math.PI * 2\n );\n this.ctx.fill();\n }\n }\n\n updateDimensions(width: number, height: number): void {\n this.width = width;\n this.height = height;\n this.ensureHighQualityRendering();\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"LayerRenderer.js","sources":["../../../src/stages/compose/LayerRenderer.ts"],"sourcesContent":["import type { Layer, VideoLayer, ImageLayer, TextLayer, Transform2D, MaskConfig } from './types';\nimport { renderBasicText, renderTextWithEntrance } from './text-renderers/basic-text-renderer';\nimport { renderWordByWord } from './text-renderers/word-by-word-renderer';\nimport { renderCharacterKTV } from './text-renderers/character-ktv-renderer';\nimport { renderWordByWordFancy } from './text-renderers/word-fancy-renderer';\n\n/**\n * LayerRenderer - Handles rendering of individual layers\n * Single responsibility: Draw a single layer to the canvas context\n */\nexport class LayerRenderer {\n private ctx: OffscreenCanvasRenderingContext2D | CanvasRenderingContext2D;\n private width: number;\n private height: number;\n private currentFrame: number = 0;\n private fps: number = 30;\n private readonly FILL_THRESHOLD = 0.9;\n\n constructor(\n ctx: OffscreenCanvasRenderingContext2D | CanvasRenderingContext2D,\n width: number,\n height: number,\n fps: number = 30\n ) {\n this.ctx = ctx;\n this.width = width;\n this.height = height;\n this.fps = fps;\n this.ensureHighQualityRendering();\n }\n\n setCurrentFrame(frame: number): void {\n this.currentFrame = frame;\n }\n\n private ensureHighQualityRendering(): void {\n this.ctx.imageSmoothingEnabled = true;\n this.ctx.imageSmoothingQuality = 'high';\n }\n\n /**\n * Render a single layer with all its properties\n */\n renderLayer(layer: Layer): void {\n if (!layer.visible || layer.opacity <= 0) return;\n\n // Only save/restore context if layer has properties that need it\n const needsStateManagement =\n layer.opacity !== 1 || layer.blendMode || layer.transform || layer.mask;\n\n if (needsStateManagement) {\n this.ctx.save();\n }\n\n try {\n // Apply layer properties only when needed\n if (layer.opacity !== 1) {\n this.ctx.globalAlpha = layer.opacity;\n }\n\n if (layer.blendMode) {\n this.ctx.globalCompositeOperation = layer.blendMode;\n }\n\n if (layer.transform) {\n // Get layer dimensions for transform anchor calculation\n const layerDimensions = this.getLayerDimensions(layer);\n this.applyTransform(layer.transform, layerDimensions);\n }\n // Render based on layer type\n switch (layer.type) {\n case 'video':\n this.renderVideoLayer(layer as VideoLayer);\n break;\n case 'image':\n this.renderImageLayer(layer as ImageLayer);\n break;\n case 'text':\n this.renderTextLayer(layer as TextLayer);\n break;\n }\n\n // Apply mask if present\n if (layer.mask) {\n this.applyMask(layer.mask);\n }\n } finally {\n if (needsStateManagement) {\n this.ctx.restore();\n }\n }\n }\n\n private parseDimension(\n value: number | string | undefined,\n canvasSize: number\n ): number | undefined {\n if (value === undefined) return undefined;\n if (typeof value === 'number') return value;\n\n // value is string at this point\n const strValue = value as string;\n\n // Parse percentage string like \"5%\"\n if (strValue.includes('%')) {\n const numValue = parseFloat(strValue);\n return isNaN(numValue) ? undefined : (numValue / 100) * canvasSize;\n }\n\n // Parse as pixel value\n const parsed = parseFloat(strValue);\n return isNaN(parsed) ? undefined : parsed;\n }\n\n /**\n * Calculate dimensions from renderConfig\n * Returns dimensions maintaining aspect ratio when only one dimension is specified\n */\n private calculateDimensionsFromConfig(\n sourceWidth: number,\n sourceHeight: number,\n renderConfig: { width?: number | string; height?: number | string } | undefined\n ): { width: number; height: number } {\n if (!renderConfig) {\n return { width: sourceWidth, height: sourceHeight };\n }\n\n const width = this.parseDimension(renderConfig.width, this.width);\n const height = this.parseDimension(renderConfig.height, this.height);\n\n if (width && height) {\n return { width, height };\n } else if (width) {\n return {\n width,\n height: Math.round((sourceHeight / sourceWidth) * width),\n };\n } else if (height) {\n return {\n width: Math.round((sourceWidth / sourceHeight) * height),\n height,\n };\n } else {\n // renderConfig exists but empty, use original size\n return { width: sourceWidth, height: sourceHeight };\n }\n }\n\n private getLayerDimensions(layer: Layer): { width: number; height: number } {\n if (layer.type === 'image') {\n const imageLayer = layer as ImageLayer;\n if (imageLayer.source) {\n const imgWidth = imageLayer.source.width;\n const imgHeight = imageLayer.source.height;\n return this.calculateDimensionsFromConfig(imgWidth, imgHeight, imageLayer.renderConfig);\n }\n } else if (layer.type === 'video') {\n const videoLayer = layer as VideoLayer;\n const videoFrame = videoLayer.videoFrame;\n const videoWidth = videoFrame.displayWidth || videoFrame.codedWidth;\n const videoHeight = videoFrame.displayHeight || videoFrame.codedHeight;\n return this.calculateDimensionsFromConfig(videoWidth, videoHeight, videoLayer.renderConfig);\n }\n // Default to canvas dimensions\n return { width: this.width, height: this.height };\n }\n\n /**\n * Calculate render dimensions with smart fill logic\n * @param sourceWidth Source width\n * @param sourceHeight Source height\n * @param naturalScale Natural scale factor (scaleY for video, scaleX for image)\n * @returns Render dimensions and position\n */\n private calculateRenderDimensions(\n sourceWidth: number,\n sourceHeight: number,\n naturalScale: number\n ): { width: number; height: number; x: number; y: number } {\n const scaledWidth = sourceWidth * naturalScale;\n const scaledHeight = sourceHeight * naturalScale;\n\n // Smart fill: when scaled size is close to container (>90%), use cover mode\n const shouldFill =\n scaledWidth / this.width > this.FILL_THRESHOLD &&\n scaledHeight / this.height > this.FILL_THRESHOLD;\n\n let renderWidth: number;\n let renderHeight: number;\n\n if (shouldFill) {\n // Cover mode: use Math.max to ensure entire canvas is covered while maintaining aspect ratio\n const coverScale = Math.max(this.width / sourceWidth, this.height / sourceHeight);\n renderWidth = Math.round(sourceWidth * coverScale);\n renderHeight = Math.round(sourceHeight * coverScale);\n } else {\n // Natural scale mode: use scaled dimensions\n renderWidth = Math.round(scaledWidth);\n renderHeight = Math.round(scaledHeight);\n }\n\n // Center the content\n const renderX = Math.round((this.width - renderWidth) / 2);\n const renderY = Math.round((this.height - renderHeight) / 2);\n\n return { width: renderWidth, height: renderHeight, x: renderX, y: renderY };\n }\n\n private applyTransform(\n transform: Transform2D,\n layerDimensions: { width: number; height: number }\n ): void {\n // Use layer dimensions (not canvas dimensions) for anchor calculation\n const anchorX = transform.anchorX ?? 0.5;\n const anchorY = transform.anchorY ?? 0.5;\n const centerX = layerDimensions.width * anchorX;\n const centerY = layerDimensions.height * anchorY;\n\n // Move to the layer position + anchor offset\n this.ctx.translate(transform.x + centerX, transform.y + centerY);\n\n if (transform.rotation) {\n this.ctx.rotate(transform.rotation);\n }\n\n this.ctx.scale(transform.scaleX, transform.scaleY);\n\n if (transform.skewX || transform.skewY) {\n this.ctx.transform(1, transform.skewY ?? 0, transform.skewX ?? 0, 1, 0, 0);\n }\n\n // Move back by anchor offset\n this.ctx.translate(-centerX, -centerY);\n }\n\n private renderVideoLayer(layer: VideoLayer): void {\n const { videoFrame, crop, renderConfig } = layer;\n\n const videoWidth = videoFrame.displayWidth || videoFrame.codedWidth;\n const videoHeight = videoFrame.displayHeight || videoFrame.codedHeight;\n\n let renderX: number;\n let renderY: number;\n let renderWidth: number;\n let renderHeight: number;\n\n if (renderConfig) {\n // Has renderConfig: explicit dimensions\n const dimensions = this.calculateDimensionsFromConfig(videoWidth, videoHeight, renderConfig);\n renderWidth = dimensions.width;\n renderHeight = dimensions.height;\n // Center the video\n renderX = Math.round((this.width - renderWidth) / 2);\n renderY = Math.round((this.height - renderHeight) / 2);\n } else {\n // No renderConfig: legacy smart fill (height-based)\n const naturalScale = this.height / videoHeight;\n const dimensions = this.calculateRenderDimensions(videoWidth, videoHeight, naturalScale);\n renderX = dimensions.x;\n renderY = dimensions.y;\n renderWidth = dimensions.width;\n renderHeight = dimensions.height;\n }\n\n if (crop) {\n this.ctx.drawImage(\n videoFrame,\n crop.x,\n crop.y,\n crop.width,\n crop.height,\n renderX,\n renderY,\n renderWidth,\n renderHeight\n );\n } else {\n this.ctx.drawImage(videoFrame, renderX, renderY, renderWidth, renderHeight);\n }\n // NOTE: Do not close videoFrame - it's managed by RcFrame wrapper\n }\n\n private renderImageLayer(layer: ImageLayer): void {\n const { source, crop, renderConfig } = layer;\n\n // Handle ImageData by putting it on canvas first\n if (source instanceof ImageData) {\n if (crop) {\n // For ImageData with crop, we need to extract the cropped region\n const tempCanvas = new OffscreenCanvas(crop.width, crop.height);\n const tempCtx = tempCanvas.getContext('2d')!;\n tempCtx.putImageData(source, -crop.x, -crop.y);\n this.ctx.drawImage(tempCanvas, 0, 0, this.width, this.height);\n } else {\n // Put ImageData directly\n this.ctx.putImageData(source, 0, 0);\n }\n return;\n }\n\n if (!source) return;\n\n const imgWidth = source.width;\n const imgHeight = source.height;\n\n let renderX: number;\n let renderY: number;\n let renderWidth: number;\n let renderHeight: number;\n\n if (renderConfig) {\n // Has renderConfig: explicit dimensions\n const dimensions = this.calculateDimensionsFromConfig(imgWidth, imgHeight, renderConfig);\n renderWidth = dimensions.width;\n renderHeight = dimensions.height;\n // Images with renderConfig start at origin (for overlay positioning)\n renderX = 0;\n renderY = 0;\n } else {\n // No renderConfig: legacy smart fill (width-based, main track)\n const naturalScale = this.width / imgWidth;\n const dimensions = this.calculateRenderDimensions(imgWidth, imgHeight, naturalScale);\n renderWidth = dimensions.width;\n renderHeight = dimensions.height;\n // Center the image\n renderX = Math.round((this.width - renderWidth) / 2);\n renderY = Math.round((this.height - renderHeight) / 2);\n }\n\n if (crop) {\n this.ctx.drawImage(\n source,\n crop.x,\n crop.y,\n crop.width,\n crop.height,\n renderX,\n renderY,\n renderWidth,\n renderHeight\n );\n } else {\n this.ctx.drawImage(source, renderX, renderY, renderWidth, renderHeight);\n }\n }\n\n private renderTextLayer(layer: TextLayer): void {\n const animationType = layer.animation?.type;\n const hasWordTimings = layer.wordTimings && layer.wordTimings.length > 0;\n\n const needsWordTimings = ['wordByWord', 'characterKTV', 'wordByWordFancy'].includes(\n animationType || ''\n );\n\n if (needsWordTimings && !hasWordTimings) {\n renderBasicText(this.ctx, layer, this.width, this.height, this.currentFrame);\n return;\n }\n\n switch (animationType) {\n case 'wordByWord':\n renderWordByWord(this.ctx, layer, this.width, this.height, this.currentFrame, this.fps);\n break;\n case 'characterKTV':\n renderCharacterKTV(this.ctx, layer, this.width, this.height, this.currentFrame, this.fps);\n break;\n case 'wordByWordFancy':\n renderWordByWordFancy(\n this.ctx,\n layer,\n this.width,\n this.height,\n this.currentFrame,\n this.fps\n );\n break;\n case 'fade':\n renderTextWithEntrance(this.ctx, layer, this.width, this.height, this.currentFrame);\n break;\n default:\n renderBasicText(this.ctx, layer, this.width, this.height, this.currentFrame);\n break;\n }\n }\n\n private applyMask(mask: MaskConfig): void {\n this.ctx.globalCompositeOperation = mask.invert ? 'source-out' : 'destination-in';\n\n if (mask.source) {\n this.ctx.drawImage(mask.source, 0, 0, this.width, this.height);\n } else if (mask.shape === 'circle') {\n this.ctx.beginPath();\n this.ctx.arc(\n this.width / 2,\n this.height / 2,\n Math.min(this.width, this.height) / 2,\n 0,\n Math.PI * 2\n );\n this.ctx.fill();\n }\n }\n\n updateDimensions(width: number, height: number): void {\n this.width = width;\n this.height = height;\n this.ensureHighQualityRendering();\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,10 @@ import { TimeUs } from '../../model';
|
|
|
2
2
|
import { VideoComposeConfig } from './types';
|
|
3
3
|
|
|
4
4
|
export type ClipInstructionStatus = 'ready' | 'pending' | 'invalid';
|
|
5
|
+
export interface ClipRenderConfig {
|
|
6
|
+
width?: number | string;
|
|
7
|
+
height?: number | string;
|
|
8
|
+
}
|
|
5
9
|
export interface SerializedTimeRange {
|
|
6
10
|
startUs: TimeUs;
|
|
7
11
|
endUs: TimeUs;
|
|
@@ -23,17 +27,13 @@ export interface SerializedVideoLayerPayload extends LayerPayloadBase {
|
|
|
23
27
|
durationUs: TimeUs;
|
|
24
28
|
playbackRate?: number;
|
|
25
29
|
rotationDeg?: number;
|
|
26
|
-
|
|
30
|
+
renderConfig?: ClipRenderConfig;
|
|
27
31
|
}
|
|
28
32
|
export interface SerializedImageLayerPayload extends LayerPayloadBase {
|
|
29
33
|
resourceId: string;
|
|
30
34
|
oldResourceId?: string;
|
|
31
|
-
|
|
32
|
-
height?: number;
|
|
33
|
-
fit?: 'cover' | 'contain' | 'fill';
|
|
35
|
+
renderConfig?: ClipRenderConfig;
|
|
34
36
|
bitmapHandle?: ImageBitmap;
|
|
35
|
-
targetWidth?: number | string;
|
|
36
|
-
targetHeight?: number | string;
|
|
37
37
|
animation?: {
|
|
38
38
|
position: {
|
|
39
39
|
x: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instructions.d.ts","sourceRoot":"","sources":["../../../src/stages/compose/instructions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElD,MAAM,MAAM,qBAAqB,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"instructions.d.ts","sourceRoot":"","sources":["../../../src/stages/compose/instructions.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,10 @@ export interface AudioComposeConfig {
|
|
|
6
6
|
format?: 'f32-planar' | 'f32' | 's16' | 's32';
|
|
7
7
|
}
|
|
8
8
|
type TimeUs = number;
|
|
9
|
+
export interface ClipRenderConfig {
|
|
10
|
+
width?: number | string;
|
|
11
|
+
height?: number | string;
|
|
12
|
+
}
|
|
9
13
|
export interface AudioTrackConfig {
|
|
10
14
|
startTimeUs: number;
|
|
11
15
|
durationUs?: number;
|
|
@@ -234,6 +238,7 @@ export interface VideoLayer extends Layer {
|
|
|
234
238
|
type: 'video';
|
|
235
239
|
videoFrame: VideoFrame;
|
|
236
240
|
rcFrame?: any;
|
|
241
|
+
renderConfig?: ClipRenderConfig;
|
|
237
242
|
crop?: {
|
|
238
243
|
x: number;
|
|
239
244
|
y: number;
|
|
@@ -245,6 +250,7 @@ export interface ImageLayer extends Layer {
|
|
|
245
250
|
type: 'image';
|
|
246
251
|
source: ImageBitmap | ImageData | null;
|
|
247
252
|
attachmentId?: string;
|
|
253
|
+
renderConfig?: ClipRenderConfig;
|
|
248
254
|
crop?: {
|
|
249
255
|
x: number;
|
|
250
256
|
y: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/stages/compose/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC;IACnB,MAAM,CAAC,EAAE,YAAY,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;CAC/C;AAED,KAAK,MAAM,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/stages/compose/types.ts"],"names":[],"mappings":"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"}
|