distark-render 1.0.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.
- package/README.md +75 -0
- package/dist/modules/eyeSystem.d.ts +104 -0
- package/dist/modules/eyeSystem.d.ts.map +1 -0
- package/dist/modules/eyeSystem.js +326 -0
- package/dist/modules/eyeSystem.js.map +1 -0
- package/dist/modules/imageLoad.d.ts +86 -0
- package/dist/modules/imageLoad.d.ts.map +1 -0
- package/dist/modules/imageLoad.js +259 -0
- package/dist/modules/imageLoad.js.map +1 -0
- package/dist/modules/mouthSystem.d.ts +147 -0
- package/dist/modules/mouthSystem.d.ts.map +1 -0
- package/dist/modules/mouthSystem.js +277 -0
- package/dist/modules/mouthSystem.js.map +1 -0
- package/dist/modules/renderRig.d.ts +53 -0
- package/dist/modules/renderRig.d.ts.map +1 -0
- package/dist/modules/renderRig.js +1248 -0
- package/dist/modules/renderRig.js.map +1 -0
- package/dist/test-skia.d.ts +15 -0
- package/dist/test-skia.d.ts.map +1 -0
- package/dist/test-skia.js +179 -0
- package/dist/test-skia.js.map +1 -0
- package/dist/types.d.ts +204 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image Loading Module
|
|
3
|
+
* Handles loading images from MD5 hashes or URLs with caching support
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* ImageLoader class - Handles loading and caching images for character rigs
|
|
7
|
+
*/
|
|
8
|
+
export class ImageLoader {
|
|
9
|
+
/**
|
|
10
|
+
* Creates a new ImageLoader instance
|
|
11
|
+
* @param baseHost - The base URL for the API (default: 'https://orchestrator.distark.com')
|
|
12
|
+
*/
|
|
13
|
+
constructor(baseHost = 'https://orchestrator.distark.com') {
|
|
14
|
+
this.baseHost = baseHost;
|
|
15
|
+
this.imageCache = new Map();
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Set the base host for image loading
|
|
19
|
+
* @param host - The base URL for the API
|
|
20
|
+
*/
|
|
21
|
+
setBaseHost(host) {
|
|
22
|
+
this.baseHost = host;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Get the current base host
|
|
26
|
+
* @returns The current base host URL
|
|
27
|
+
*/
|
|
28
|
+
getBaseHost() {
|
|
29
|
+
return this.baseHost;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Resolve an image source (hash or URL) to a full URL
|
|
33
|
+
* @param imageData - Image hash, URL, or data URL
|
|
34
|
+
* @returns Full URL or null if invalid
|
|
35
|
+
*/
|
|
36
|
+
resolveImageSource(imageData) {
|
|
37
|
+
if (!imageData || typeof imageData !== 'string') {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
// Check if it's an MD5 hash (32-character hex string)
|
|
41
|
+
const md5Regex = /^[a-f0-9]{32}$/i;
|
|
42
|
+
if (md5Regex.test(imageData)) {
|
|
43
|
+
return `${this.baseHost}/api/v1/artifacts/${imageData}`;
|
|
44
|
+
}
|
|
45
|
+
// Check if it's a truncated hash (ends with ...)
|
|
46
|
+
const truncatedHashRegex = /^[a-f0-9]{20,31}\.{3}$/i;
|
|
47
|
+
if (truncatedHashRegex.test(imageData)) {
|
|
48
|
+
const hash = imageData.replace(/\.{3}$/, '');
|
|
49
|
+
console.warn(`Truncated hash detected for ${imageData}, attempting to load with partial hash`);
|
|
50
|
+
return `${this.baseHost}/api/v1/artifacts/${hash}`;
|
|
51
|
+
}
|
|
52
|
+
// Return as-is for URLs and data URLs
|
|
53
|
+
if (imageData.startsWith('http://') ||
|
|
54
|
+
imageData.startsWith('https://') ||
|
|
55
|
+
imageData.startsWith('data:')) {
|
|
56
|
+
return imageData;
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Load an image from a URL/hash and invoke callbacks
|
|
62
|
+
* @param key - Unique key for the image
|
|
63
|
+
* @param imageData - Image hash or URL
|
|
64
|
+
* @param onLoad - Callback when image loads successfully
|
|
65
|
+
* @param onError - Callback when image fails to load (optional)
|
|
66
|
+
*/
|
|
67
|
+
loadImage(key, imageData, onLoad, onError) {
|
|
68
|
+
const imageUrl = this.resolveImageSource(imageData);
|
|
69
|
+
if (!imageUrl) {
|
|
70
|
+
console.warn(`Could not resolve image source for ${key}: ${imageData}`);
|
|
71
|
+
if (onError) {
|
|
72
|
+
onError(key, 'Invalid image source');
|
|
73
|
+
}
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
console.log(`📥 Loading image for ${key} from: ${imageUrl.substring(0, 100)}...`);
|
|
77
|
+
const img = new Image();
|
|
78
|
+
img.crossOrigin = 'anonymous'; // Enable CORS
|
|
79
|
+
img.onload = () => {
|
|
80
|
+
console.log(`✓ Successfully loaded image for ${key} (${img.width}x${img.height})`);
|
|
81
|
+
if (onLoad) {
|
|
82
|
+
onLoad(key, img);
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
img.onerror = (err) => {
|
|
86
|
+
console.error(`✗ Failed to load image for ${key}`);
|
|
87
|
+
console.error(` URL: ${imageUrl}`);
|
|
88
|
+
console.error(` Error:`, err);
|
|
89
|
+
if (onError) {
|
|
90
|
+
onError(key, err);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
img.src = imageUrl;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Load multiple images in parallel
|
|
97
|
+
* @param imagesToLoad - Array of {key, hash} objects
|
|
98
|
+
* @param onProgress - Optional callback for progress updates
|
|
99
|
+
* @returns Promise that resolves with loaded images map
|
|
100
|
+
*/
|
|
101
|
+
async loadImages(imagesToLoad, onProgress) {
|
|
102
|
+
const loadedImages = {};
|
|
103
|
+
let loaded = 0;
|
|
104
|
+
let failed = 0;
|
|
105
|
+
const total = imagesToLoad.length;
|
|
106
|
+
const loadPromises = imagesToLoad.map(({ key, hash }) => {
|
|
107
|
+
return new Promise((resolve) => {
|
|
108
|
+
this.loadImage(key, hash, (loadedKey, img) => {
|
|
109
|
+
loadedImages[loadedKey] = img;
|
|
110
|
+
loaded++;
|
|
111
|
+
if (onProgress) {
|
|
112
|
+
onProgress(loaded, total, failed);
|
|
113
|
+
}
|
|
114
|
+
resolve();
|
|
115
|
+
}, () => {
|
|
116
|
+
failed++;
|
|
117
|
+
if (onProgress) {
|
|
118
|
+
onProgress(loaded, total, failed);
|
|
119
|
+
}
|
|
120
|
+
resolve();
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
await Promise.all(loadPromises);
|
|
125
|
+
return loadedImages;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Get the image cache
|
|
129
|
+
* @returns The image cache Map
|
|
130
|
+
*/
|
|
131
|
+
getImageCache() {
|
|
132
|
+
return this.imageCache;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Clear the image cache
|
|
136
|
+
*/
|
|
137
|
+
clearImageCache() {
|
|
138
|
+
this.imageCache.clear();
|
|
139
|
+
console.log('🗑️ Image cache cleared');
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Get image from cache or return undefined
|
|
143
|
+
* @param key - Image key
|
|
144
|
+
*/
|
|
145
|
+
getCachedImage(key) {
|
|
146
|
+
return this.imageCache.get(key);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Manually add image to cache
|
|
150
|
+
* @param key - Image key
|
|
151
|
+
* @param image - Image element
|
|
152
|
+
*/
|
|
153
|
+
cacheImage(key, image) {
|
|
154
|
+
this.imageCache.set(key, image);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Load image with caching support
|
|
158
|
+
* Checks cache first, only loads if not cached
|
|
159
|
+
*/
|
|
160
|
+
loadImageWithCache(key, imageData, onLoad, onError) {
|
|
161
|
+
// Check cache first
|
|
162
|
+
const cached = this.imageCache.get(key);
|
|
163
|
+
if (cached) {
|
|
164
|
+
console.log(`✓ Using cached image for ${key}`);
|
|
165
|
+
if (onLoad) {
|
|
166
|
+
onLoad(key, cached);
|
|
167
|
+
}
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
// Not in cache, load it
|
|
171
|
+
this.loadImage(key, imageData, (loadedKey, img) => {
|
|
172
|
+
// Add to cache
|
|
173
|
+
this.imageCache.set(loadedKey, img);
|
|
174
|
+
console.log(`💾 Cached image for ${loadedKey}`);
|
|
175
|
+
if (onLoad) {
|
|
176
|
+
onLoad(loadedKey, img);
|
|
177
|
+
}
|
|
178
|
+
}, onError);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Load all images for a character rig and populate the cache
|
|
182
|
+
* @param rigData - Character rig data
|
|
183
|
+
* @param useCache - Whether to use existing cache (default: true)
|
|
184
|
+
* @param onProgress - Progress callback
|
|
185
|
+
* @returns Promise that resolves with the image cache as a plain object
|
|
186
|
+
*/
|
|
187
|
+
async loadAllRigImages(rigData, useCache = true, onProgress) {
|
|
188
|
+
const imagesToLoad = [];
|
|
189
|
+
// Collect all image paths from imagePaths
|
|
190
|
+
if (rigData.imagePaths) {
|
|
191
|
+
for (const [key, hash] of Object.entries(rigData.imagePaths)) {
|
|
192
|
+
if (hash && typeof hash === 'string' && !hash.includes('[MEDIA_REMOVED]')) {
|
|
193
|
+
const imageKey = `imagePaths.${key}`;
|
|
194
|
+
// Skip if already in cache and useCache is true
|
|
195
|
+
if (!useCache || !this.imageCache.has(imageKey)) {
|
|
196
|
+
imagesToLoad.push({ key: imageKey, hash });
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// Collect all eye images
|
|
202
|
+
if (rigData.eyes) {
|
|
203
|
+
for (const [key, value] of Object.entries(rigData.eyes)) {
|
|
204
|
+
if (typeof value === 'string' && !value.includes('[MEDIA_REMOVED]') &&
|
|
205
|
+
(key.includes('Image') || key.includes('Iris') || key.includes('Lid'))) {
|
|
206
|
+
const imageKey = `eyes.${key}`;
|
|
207
|
+
// Skip if already in cache and useCache is true
|
|
208
|
+
if (!useCache || !this.imageCache.has(imageKey)) {
|
|
209
|
+
imagesToLoad.push({ key: imageKey, hash: value });
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
console.log(`📦 Loading ${imagesToLoad.length} images for character rig...`);
|
|
215
|
+
let loaded = 0;
|
|
216
|
+
let failed = 0;
|
|
217
|
+
const total = imagesToLoad.length;
|
|
218
|
+
// If nothing to load, return cache immediately
|
|
219
|
+
if (total === 0) {
|
|
220
|
+
console.log('✓ All images already cached!');
|
|
221
|
+
const result = {};
|
|
222
|
+
this.imageCache.forEach((img, key) => {
|
|
223
|
+
result[key] = img;
|
|
224
|
+
});
|
|
225
|
+
console.log('📦 Image Cache:', result);
|
|
226
|
+
return result;
|
|
227
|
+
}
|
|
228
|
+
const loadPromises = imagesToLoad.map(({ key, hash }) => {
|
|
229
|
+
return new Promise((resolve) => {
|
|
230
|
+
this.loadImage(key, hash, (loadedKey, img) => {
|
|
231
|
+
this.imageCache.set(loadedKey, img);
|
|
232
|
+
loaded++;
|
|
233
|
+
if (onProgress) {
|
|
234
|
+
onProgress(loaded, total, failed);
|
|
235
|
+
}
|
|
236
|
+
resolve();
|
|
237
|
+
}, () => {
|
|
238
|
+
failed++;
|
|
239
|
+
if (onProgress) {
|
|
240
|
+
onProgress(loaded, total, failed);
|
|
241
|
+
}
|
|
242
|
+
resolve();
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
await Promise.all(loadPromises);
|
|
247
|
+
console.log(`✓ Loaded ${loaded}/${total} images (${failed} failed)`);
|
|
248
|
+
// Return cache as plain object
|
|
249
|
+
const result = {};
|
|
250
|
+
this.imageCache.forEach((img, key) => {
|
|
251
|
+
result[key] = img;
|
|
252
|
+
});
|
|
253
|
+
console.log('📦 Image Cache:', result);
|
|
254
|
+
return result;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
// Export a default instance for backwards compatibility
|
|
258
|
+
export const defaultImageLoader = new ImageLoader();
|
|
259
|
+
//# sourceMappingURL=imageLoad.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"imageLoad.js","sourceRoot":"","sources":["../../modules/imageLoad.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mouth System Module
|
|
3
|
+
* Handles mouth animation based on audio volume, visemes, or manual control
|
|
4
|
+
*
|
|
5
|
+
* Note: This module does NOT handle rendering - it only manages state.
|
|
6
|
+
* The renderRig module handles actual rendering of mouth images.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Mouth shape types (viseme-based and general shapes)
|
|
10
|
+
*/
|
|
11
|
+
export type MouthShape = 'closed' | 'slightly-open' | 'half-open' | 'ds' | 'open' | 'ee' | 'wide-open' | 'ah' | 'woo' | 'neutral';
|
|
12
|
+
/**
|
|
13
|
+
* Audio analysis data structure
|
|
14
|
+
*/
|
|
15
|
+
export interface AudioAnalysisData {
|
|
16
|
+
analyser: AnalyserNode;
|
|
17
|
+
dataArray: Uint8Array<ArrayBuffer>;
|
|
18
|
+
audioElement: HTMLAudioElement;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Viseme mapping data (phoneme to mouth shape)
|
|
22
|
+
*/
|
|
23
|
+
export interface VisemeData {
|
|
24
|
+
viseme: string;
|
|
25
|
+
timestamp: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Mouth animation mode
|
|
29
|
+
*/
|
|
30
|
+
export type MouthAnimationMode = 'manual' | 'audio' | 'viseme';
|
|
31
|
+
/**
|
|
32
|
+
* Mouth data configuration
|
|
33
|
+
*/
|
|
34
|
+
export interface MouthData {
|
|
35
|
+
mouthWidth?: number;
|
|
36
|
+
mouthHeight?: number;
|
|
37
|
+
mouthSize?: number;
|
|
38
|
+
mouthXCoor?: number;
|
|
39
|
+
mouthYCoor?: number;
|
|
40
|
+
[key: string]: number | undefined;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Mouth state
|
|
44
|
+
*/
|
|
45
|
+
export interface MouthState {
|
|
46
|
+
currentMouthKey: MouthShape;
|
|
47
|
+
lastMouthChangeTime: number;
|
|
48
|
+
currentVolume: number;
|
|
49
|
+
mode: MouthAnimationMode;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Mouth configuration
|
|
53
|
+
*/
|
|
54
|
+
export interface MouthConfig {
|
|
55
|
+
volumeThreshold?: number;
|
|
56
|
+
mouthChangeInterval?: number;
|
|
57
|
+
talkingMouths?: MouthShape[];
|
|
58
|
+
visemeMapping?: Record<string, MouthShape>;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* MouthSystem class - Manages mouth animation state
|
|
62
|
+
*/
|
|
63
|
+
export declare class MouthSystem {
|
|
64
|
+
private state;
|
|
65
|
+
private config;
|
|
66
|
+
private characterId;
|
|
67
|
+
private availableMouths;
|
|
68
|
+
/**
|
|
69
|
+
* Default viseme to mouth shape mapping
|
|
70
|
+
*/
|
|
71
|
+
private static readonly DEFAULT_VISEME_MAPPING;
|
|
72
|
+
/**
|
|
73
|
+
* Default talking mouths (used for random audio-based animation)
|
|
74
|
+
*/
|
|
75
|
+
private static readonly DEFAULT_TALKING_MOUTHS;
|
|
76
|
+
/**
|
|
77
|
+
* Creates a new MouthSystem instance
|
|
78
|
+
* @param characterId - Unique identifier for the character
|
|
79
|
+
* @param availableMouths - Set of available mouth shapes for this character
|
|
80
|
+
* @param config - Optional mouth configuration
|
|
81
|
+
*/
|
|
82
|
+
constructor(characterId: string, availableMouths?: Set<MouthShape>, config?: MouthConfig);
|
|
83
|
+
/**
|
|
84
|
+
* Get current mouth state
|
|
85
|
+
*/
|
|
86
|
+
getState(): MouthState;
|
|
87
|
+
/**
|
|
88
|
+
* Get current mouth shape
|
|
89
|
+
*/
|
|
90
|
+
getCurrentMouth(): MouthShape;
|
|
91
|
+
/**
|
|
92
|
+
* Manually set mouth shape
|
|
93
|
+
*/
|
|
94
|
+
setMouthShape(shape: MouthShape): void;
|
|
95
|
+
/**
|
|
96
|
+
* Set available mouth shapes
|
|
97
|
+
*/
|
|
98
|
+
setAvailableMouths(mouths: MouthShape[]): void;
|
|
99
|
+
/**
|
|
100
|
+
* Update mouth animation based on audio volume
|
|
101
|
+
* @param currentTime - Current time in milliseconds
|
|
102
|
+
* @param audioData - Audio analysis data
|
|
103
|
+
*/
|
|
104
|
+
updateFromAudio(currentTime: number, audioData: AudioAnalysisData): void;
|
|
105
|
+
/**
|
|
106
|
+
* Update mouth animation based on viseme data
|
|
107
|
+
* @param viseme - Viseme identifier (e.g., 'A', 'E', 'O')
|
|
108
|
+
*/
|
|
109
|
+
updateFromViseme(viseme: string): void;
|
|
110
|
+
/**
|
|
111
|
+
* Reset mouth to neutral/closed state
|
|
112
|
+
*/
|
|
113
|
+
reset(): void;
|
|
114
|
+
/**
|
|
115
|
+
* Get the image key for the current mouth shape
|
|
116
|
+
* This is used by renderRig to determine which image to render
|
|
117
|
+
*
|
|
118
|
+
* @returns The image key for the current mouth (e.g., 'imagePaths.mouth_open')
|
|
119
|
+
*/
|
|
120
|
+
getCurrentMouthImageKey(): string;
|
|
121
|
+
/**
|
|
122
|
+
* Get all possible image key candidates for current mouth
|
|
123
|
+
* Used by renderRig to try multiple image name variations
|
|
124
|
+
*/
|
|
125
|
+
getMouthImageKeyCandidates(): string[];
|
|
126
|
+
/**
|
|
127
|
+
* Get configuration
|
|
128
|
+
*/
|
|
129
|
+
getConfig(): MouthConfig;
|
|
130
|
+
/**
|
|
131
|
+
* Update configuration
|
|
132
|
+
*/
|
|
133
|
+
updateConfig(config: Partial<MouthConfig>): void;
|
|
134
|
+
/**
|
|
135
|
+
* Get debug information
|
|
136
|
+
*/
|
|
137
|
+
getDebugInfo(): string;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Factory function to create mouth system
|
|
141
|
+
*/
|
|
142
|
+
export declare function createMouthSystem(characterId: string, availableMouths?: MouthShape[], config?: MouthConfig): MouthSystem;
|
|
143
|
+
/**
|
|
144
|
+
* Helper: Extract available mouth shapes from rig data
|
|
145
|
+
*/
|
|
146
|
+
export declare function extractMouthShapesFromRigData(rigData: any): MouthShape[];
|
|
147
|
+
//# sourceMappingURL=mouthSystem.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mouthSystem.d.ts","sourceRoot":"","sources":["../../modules/mouthSystem.ts"],"names":[],"mappings":"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"}
|