@hmcs/sdk 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 +30 -0
- package/dist/app.cjs +63 -0
- package/dist/app.js +63 -0
- package/dist/assets.cjs +52 -0
- package/dist/assets.js +52 -0
- package/dist/audio.cjs +159 -0
- package/dist/audio.js +159 -0
- package/dist/commands.cjs +298 -0
- package/dist/commands.d.ts +852 -0
- package/dist/commands.js +296 -0
- package/dist/coordinates.cjs +69 -0
- package/dist/coordinates.js +69 -0
- package/dist/displays.cjs +38 -0
- package/dist/displays.js +38 -0
- package/dist/effects.cjs +50 -0
- package/dist/effects.js +50 -0
- package/dist/entities.cjs +249 -0
- package/dist/entities.js +249 -0
- package/dist/host.cjs +297 -0
- package/dist/host.js +294 -0
- package/dist/index.cjs +98 -0
- package/dist/index.d.ts +2612 -0
- package/dist/index.js +17 -0
- package/dist/mods.cjs +207 -0
- package/dist/mods.js +207 -0
- package/dist/preferences.cjs +90 -0
- package/dist/preferences.js +90 -0
- package/dist/settings.cjs +46 -0
- package/dist/settings.js +46 -0
- package/dist/shadowPanel.cjs +46 -0
- package/dist/shadowPanel.js +46 -0
- package/dist/signals.cjs +158 -0
- package/dist/signals.js +158 -0
- package/dist/speech.cjs +48 -0
- package/dist/speech.js +48 -0
- package/dist/utils.cjs +13 -0
- package/dist/utils.js +11 -0
- package/dist/vrm.cjs +469 -0
- package/dist/vrm.js +466 -0
- package/dist/webviews.cjs +310 -0
- package/dist/webviews.js +302 -0
- package/package.json +61 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var host = require('./host.cjs');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Shadow Panel API namespace for controlling the application's shadow overlay.
|
|
7
|
+
*
|
|
8
|
+
* The shadow panel is a visual overlay that can be used to create atmospheric
|
|
9
|
+
* effects, focus attention, or provide visual feedback.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* await shadowPanel.setAlpha(0.7);
|
|
14
|
+
* const currentAlpha = await shadowPanel.alpha();
|
|
15
|
+
* await shadowPanel.setAlpha(0);
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
exports.shadowPanel = void 0;
|
|
19
|
+
(function (shadowPanel) {
|
|
20
|
+
/**
|
|
21
|
+
* Gets the current transparency level of the shadow panel.
|
|
22
|
+
*
|
|
23
|
+
* @returns A promise that resolves to the current alpha value (0-1)
|
|
24
|
+
*/
|
|
25
|
+
async function alpha() {
|
|
26
|
+
const response = await host.host.get(host.host.createUrl("shadow-panel/alpha"));
|
|
27
|
+
return Number(await response.json());
|
|
28
|
+
}
|
|
29
|
+
shadowPanel.alpha = alpha;
|
|
30
|
+
/**
|
|
31
|
+
* Sets the transparency level of the shadow panel.
|
|
32
|
+
*
|
|
33
|
+
* @param alpha - The transparency value between 0 (invisible) and 1 (opaque)
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* await shadowPanel.setAlpha(0.7);
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
async function setAlpha(alpha) {
|
|
41
|
+
await host.host.put(host.host.createUrl("shadow-panel/alpha"), {
|
|
42
|
+
alpha,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
shadowPanel.setAlpha = setAlpha;
|
|
46
|
+
})(exports.shadowPanel || (exports.shadowPanel = {}));
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { host } from './host.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shadow Panel API namespace for controlling the application's shadow overlay.
|
|
5
|
+
*
|
|
6
|
+
* The shadow panel is a visual overlay that can be used to create atmospheric
|
|
7
|
+
* effects, focus attention, or provide visual feedback.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* await shadowPanel.setAlpha(0.7);
|
|
12
|
+
* const currentAlpha = await shadowPanel.alpha();
|
|
13
|
+
* await shadowPanel.setAlpha(0);
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
var shadowPanel;
|
|
17
|
+
(function (shadowPanel) {
|
|
18
|
+
/**
|
|
19
|
+
* Gets the current transparency level of the shadow panel.
|
|
20
|
+
*
|
|
21
|
+
* @returns A promise that resolves to the current alpha value (0-1)
|
|
22
|
+
*/
|
|
23
|
+
async function alpha() {
|
|
24
|
+
const response = await host.get(host.createUrl("shadow-panel/alpha"));
|
|
25
|
+
return Number(await response.json());
|
|
26
|
+
}
|
|
27
|
+
shadowPanel.alpha = alpha;
|
|
28
|
+
/**
|
|
29
|
+
* Sets the transparency level of the shadow panel.
|
|
30
|
+
*
|
|
31
|
+
* @param alpha - The transparency value between 0 (invisible) and 1 (opaque)
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```typescript
|
|
35
|
+
* await shadowPanel.setAlpha(0.7);
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
async function setAlpha(alpha) {
|
|
39
|
+
await host.put(host.createUrl("shadow-panel/alpha"), {
|
|
40
|
+
alpha,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
shadowPanel.setAlpha = setAlpha;
|
|
44
|
+
})(shadowPanel || (shadowPanel = {}));
|
|
45
|
+
|
|
46
|
+
export { shadowPanel };
|
package/dist/signals.cjs
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var host = require('./host.cjs');
|
|
4
|
+
var eventsource = require('eventsource');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Signals API namespace for cross-process communication.
|
|
8
|
+
*
|
|
9
|
+
* Provides a pub/sub mechanism that allows external processes to communicate
|
|
10
|
+
* with the Desktop Homunculus application and its mods through event streaming.
|
|
11
|
+
*
|
|
12
|
+
* Key features:
|
|
13
|
+
* - Real-time event streaming via Server-Sent Events (SSE)
|
|
14
|
+
* - Signal broadcasting to multiple subscribers
|
|
15
|
+
* - Type-safe payload handling
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* // Listen for custom events from external processes
|
|
20
|
+
* const eventSource = signals.stream<{action: string, data: any}>(
|
|
21
|
+
* "my-custom-signal",
|
|
22
|
+
* (payload) => {
|
|
23
|
+
* console.log("Received signal:", payload.action, payload.data);
|
|
24
|
+
* }
|
|
25
|
+
* );
|
|
26
|
+
*
|
|
27
|
+
* // Send signals to all listeners
|
|
28
|
+
* await signals.send("my-custom-signal", {
|
|
29
|
+
* action: "update",
|
|
30
|
+
* data: { message: "Hello from external app!" }
|
|
31
|
+
* });
|
|
32
|
+
*
|
|
33
|
+
* // Clean up when done
|
|
34
|
+
* eventSource.close();
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
exports.signals = void 0;
|
|
38
|
+
(function (signals) {
|
|
39
|
+
/**
|
|
40
|
+
* Lists all active signal channels and their subscriber counts.
|
|
41
|
+
*
|
|
42
|
+
* Returns information about every signal channel that has been created.
|
|
43
|
+
* Useful for debugging, monitoring, and discovering available channels.
|
|
44
|
+
*
|
|
45
|
+
* @returns Array of active signal channel information
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* // List all active signal channels
|
|
50
|
+
* const channels = await signals.list();
|
|
51
|
+
* for (const ch of channels) {
|
|
52
|
+
* console.log(`${ch.signal}: ${ch.subscribers} subscribers`);
|
|
53
|
+
* }
|
|
54
|
+
*
|
|
55
|
+
* // Check if a specific signal has listeners before sending
|
|
56
|
+
* const channels = await signals.list();
|
|
57
|
+
* const target = channels.find(ch => ch.signal === "my-signal");
|
|
58
|
+
* if (target && target.subscribers > 0) {
|
|
59
|
+
* await signals.send("my-signal", { data: "hello" });
|
|
60
|
+
* }
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
async function list() {
|
|
64
|
+
const response = await host.host.get(host.host.createUrl("signals"));
|
|
65
|
+
return await response.json();
|
|
66
|
+
}
|
|
67
|
+
signals.list = list;
|
|
68
|
+
/**
|
|
69
|
+
* Creates a persistent connection to stream signal events of a specific type.
|
|
70
|
+
*
|
|
71
|
+
* This establishes a Server-Sent Events (SSE) connection that will receive
|
|
72
|
+
* all signals sent to the specified signal channel. The connection remains
|
|
73
|
+
* open until explicitly closed.
|
|
74
|
+
*
|
|
75
|
+
* @template V - The type of the payload that will be received
|
|
76
|
+
* @param signal - The signal channel name to subscribe to
|
|
77
|
+
* @param f - Callback function to handle received payloads
|
|
78
|
+
* @returns EventSource instance for managing the connection
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```typescript
|
|
82
|
+
* // Listen for user interaction events
|
|
83
|
+
* interface UserAction {
|
|
84
|
+
* type: 'click' | 'hover' | 'scroll';
|
|
85
|
+
* position: [number, number];
|
|
86
|
+
* timestamp: number;
|
|
87
|
+
* }
|
|
88
|
+
*
|
|
89
|
+
* const userEventStream = signals.stream<UserAction>(
|
|
90
|
+
* "user-interactions",
|
|
91
|
+
* async (action) => {
|
|
92
|
+
* console.log(`User ${action.type} at`, action.position);
|
|
93
|
+
* // Process the user action...
|
|
94
|
+
* }
|
|
95
|
+
* );
|
|
96
|
+
*
|
|
97
|
+
* // Later, close the stream
|
|
98
|
+
* userEventStream.close();
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
function stream(signal, f) {
|
|
102
|
+
const url = host.host.createUrl(`signals/${signal}`);
|
|
103
|
+
const es = new eventsource.EventSource(url);
|
|
104
|
+
es.addEventListener("message", async (event) => {
|
|
105
|
+
try {
|
|
106
|
+
const payload = JSON.parse(event.data);
|
|
107
|
+
await f(payload);
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
console.error(`Error processing signal ${signal}:`, error);
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
return es;
|
|
114
|
+
}
|
|
115
|
+
signals.stream = stream;
|
|
116
|
+
/**
|
|
117
|
+
* Sends a signal payload to all subscribers listening to the specified signal channel.
|
|
118
|
+
*
|
|
119
|
+
* This broadcasts the payload to all active EventSource connections that are
|
|
120
|
+
* streaming the same signal type. The operation is asynchronous and will
|
|
121
|
+
* complete once the signal has been distributed to all subscribers.
|
|
122
|
+
*
|
|
123
|
+
* @template V - The type of the payload being sent
|
|
124
|
+
* @param signal - The signal channel name to broadcast to
|
|
125
|
+
* @param payload - The data to send to all subscribers
|
|
126
|
+
*
|
|
127
|
+
* @throws Will throw an error if the signal broadcast fails
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* ```typescript
|
|
131
|
+
* // Send a notification to all mod windows
|
|
132
|
+
* await signals.send("notifications", {
|
|
133
|
+
* type: "info",
|
|
134
|
+
* title: "Update Available",
|
|
135
|
+
* message: "A new version of the character is available",
|
|
136
|
+
* timestamp: Date.now()
|
|
137
|
+
* });
|
|
138
|
+
*
|
|
139
|
+
* // Send real-time data updates
|
|
140
|
+
* await signals.send("data-update", {
|
|
141
|
+
* source: "weather-api",
|
|
142
|
+
* temperature: 72,
|
|
143
|
+
* conditions: "sunny"
|
|
144
|
+
* });
|
|
145
|
+
*
|
|
146
|
+
* // Trigger actions in mods
|
|
147
|
+
* await signals.send("vrm-action", {
|
|
148
|
+
* action: "wave",
|
|
149
|
+
* target: vrmEntity,
|
|
150
|
+
* duration: 2000
|
|
151
|
+
* });
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
async function send(signal, payload) {
|
|
155
|
+
await host.host.post(host.host.createUrl(`signals/${signal}`), payload);
|
|
156
|
+
}
|
|
157
|
+
signals.send = send;
|
|
158
|
+
})(exports.signals || (exports.signals = {}));
|
package/dist/signals.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { host } from './host.js';
|
|
2
|
+
import { EventSource } from 'eventsource';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Signals API namespace for cross-process communication.
|
|
6
|
+
*
|
|
7
|
+
* Provides a pub/sub mechanism that allows external processes to communicate
|
|
8
|
+
* with the Desktop Homunculus application and its mods through event streaming.
|
|
9
|
+
*
|
|
10
|
+
* Key features:
|
|
11
|
+
* - Real-time event streaming via Server-Sent Events (SSE)
|
|
12
|
+
* - Signal broadcasting to multiple subscribers
|
|
13
|
+
* - Type-safe payload handling
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* // Listen for custom events from external processes
|
|
18
|
+
* const eventSource = signals.stream<{action: string, data: any}>(
|
|
19
|
+
* "my-custom-signal",
|
|
20
|
+
* (payload) => {
|
|
21
|
+
* console.log("Received signal:", payload.action, payload.data);
|
|
22
|
+
* }
|
|
23
|
+
* );
|
|
24
|
+
*
|
|
25
|
+
* // Send signals to all listeners
|
|
26
|
+
* await signals.send("my-custom-signal", {
|
|
27
|
+
* action: "update",
|
|
28
|
+
* data: { message: "Hello from external app!" }
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* // Clean up when done
|
|
32
|
+
* eventSource.close();
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
var signals;
|
|
36
|
+
(function (signals) {
|
|
37
|
+
/**
|
|
38
|
+
* Lists all active signal channels and their subscriber counts.
|
|
39
|
+
*
|
|
40
|
+
* Returns information about every signal channel that has been created.
|
|
41
|
+
* Useful for debugging, monitoring, and discovering available channels.
|
|
42
|
+
*
|
|
43
|
+
* @returns Array of active signal channel information
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* // List all active signal channels
|
|
48
|
+
* const channels = await signals.list();
|
|
49
|
+
* for (const ch of channels) {
|
|
50
|
+
* console.log(`${ch.signal}: ${ch.subscribers} subscribers`);
|
|
51
|
+
* }
|
|
52
|
+
*
|
|
53
|
+
* // Check if a specific signal has listeners before sending
|
|
54
|
+
* const channels = await signals.list();
|
|
55
|
+
* const target = channels.find(ch => ch.signal === "my-signal");
|
|
56
|
+
* if (target && target.subscribers > 0) {
|
|
57
|
+
* await signals.send("my-signal", { data: "hello" });
|
|
58
|
+
* }
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
async function list() {
|
|
62
|
+
const response = await host.get(host.createUrl("signals"));
|
|
63
|
+
return await response.json();
|
|
64
|
+
}
|
|
65
|
+
signals.list = list;
|
|
66
|
+
/**
|
|
67
|
+
* Creates a persistent connection to stream signal events of a specific type.
|
|
68
|
+
*
|
|
69
|
+
* This establishes a Server-Sent Events (SSE) connection that will receive
|
|
70
|
+
* all signals sent to the specified signal channel. The connection remains
|
|
71
|
+
* open until explicitly closed.
|
|
72
|
+
*
|
|
73
|
+
* @template V - The type of the payload that will be received
|
|
74
|
+
* @param signal - The signal channel name to subscribe to
|
|
75
|
+
* @param f - Callback function to handle received payloads
|
|
76
|
+
* @returns EventSource instance for managing the connection
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* // Listen for user interaction events
|
|
81
|
+
* interface UserAction {
|
|
82
|
+
* type: 'click' | 'hover' | 'scroll';
|
|
83
|
+
* position: [number, number];
|
|
84
|
+
* timestamp: number;
|
|
85
|
+
* }
|
|
86
|
+
*
|
|
87
|
+
* const userEventStream = signals.stream<UserAction>(
|
|
88
|
+
* "user-interactions",
|
|
89
|
+
* async (action) => {
|
|
90
|
+
* console.log(`User ${action.type} at`, action.position);
|
|
91
|
+
* // Process the user action...
|
|
92
|
+
* }
|
|
93
|
+
* );
|
|
94
|
+
*
|
|
95
|
+
* // Later, close the stream
|
|
96
|
+
* userEventStream.close();
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
function stream(signal, f) {
|
|
100
|
+
const url = host.createUrl(`signals/${signal}`);
|
|
101
|
+
const es = new EventSource(url);
|
|
102
|
+
es.addEventListener("message", async (event) => {
|
|
103
|
+
try {
|
|
104
|
+
const payload = JSON.parse(event.data);
|
|
105
|
+
await f(payload);
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
console.error(`Error processing signal ${signal}:`, error);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
return es;
|
|
112
|
+
}
|
|
113
|
+
signals.stream = stream;
|
|
114
|
+
/**
|
|
115
|
+
* Sends a signal payload to all subscribers listening to the specified signal channel.
|
|
116
|
+
*
|
|
117
|
+
* This broadcasts the payload to all active EventSource connections that are
|
|
118
|
+
* streaming the same signal type. The operation is asynchronous and will
|
|
119
|
+
* complete once the signal has been distributed to all subscribers.
|
|
120
|
+
*
|
|
121
|
+
* @template V - The type of the payload being sent
|
|
122
|
+
* @param signal - The signal channel name to broadcast to
|
|
123
|
+
* @param payload - The data to send to all subscribers
|
|
124
|
+
*
|
|
125
|
+
* @throws Will throw an error if the signal broadcast fails
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```typescript
|
|
129
|
+
* // Send a notification to all mod windows
|
|
130
|
+
* await signals.send("notifications", {
|
|
131
|
+
* type: "info",
|
|
132
|
+
* title: "Update Available",
|
|
133
|
+
* message: "A new version of the character is available",
|
|
134
|
+
* timestamp: Date.now()
|
|
135
|
+
* });
|
|
136
|
+
*
|
|
137
|
+
* // Send real-time data updates
|
|
138
|
+
* await signals.send("data-update", {
|
|
139
|
+
* source: "weather-api",
|
|
140
|
+
* temperature: 72,
|
|
141
|
+
* conditions: "sunny"
|
|
142
|
+
* });
|
|
143
|
+
*
|
|
144
|
+
* // Trigger actions in mods
|
|
145
|
+
* await signals.send("vrm-action", {
|
|
146
|
+
* action: "wave",
|
|
147
|
+
* target: vrmEntity,
|
|
148
|
+
* duration: 2000
|
|
149
|
+
* });
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
async function send(signal, payload) {
|
|
153
|
+
await host.post(host.createUrl(`signals/${signal}`), payload);
|
|
154
|
+
}
|
|
155
|
+
signals.send = send;
|
|
156
|
+
})(signals || (signals = {}));
|
|
157
|
+
|
|
158
|
+
export { signals };
|
package/dist/speech.cjs
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Speech utilities for converting phoneme data to Timeline keyframes.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { speech, Vrm } from "@hmcs/sdk";
|
|
9
|
+
*
|
|
10
|
+
* const keyframes = speech.fromPhonemes([
|
|
11
|
+
* ["aa", 0.1],
|
|
12
|
+
* [null, 0.05],
|
|
13
|
+
* ["oh", 0.12],
|
|
14
|
+
* ]);
|
|
15
|
+
* const vrm = await Vrm.findByName("MyAvatar");
|
|
16
|
+
* await vrm.speakWithTimeline(wavData, keyframes);
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
exports.speech = void 0;
|
|
20
|
+
(function (speech) {
|
|
21
|
+
/**
|
|
22
|
+
* Creates timeline keyframes from a simple phoneme list.
|
|
23
|
+
*
|
|
24
|
+
* Each entry is a tuple of [expression_name | null, duration_seconds].
|
|
25
|
+
* A null expression name creates a silent keyframe.
|
|
26
|
+
*
|
|
27
|
+
* @param phonemes - Array of [expression_name, duration] tuples.
|
|
28
|
+
* @returns An array of timeline keyframes.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```typescript
|
|
32
|
+
* const keyframes = speech.fromPhonemes([
|
|
33
|
+
* ["aa", 0.1],
|
|
34
|
+
* [null, 0.05],
|
|
35
|
+
* ["oh", 0.12],
|
|
36
|
+
* ]);
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
function fromPhonemes(phonemes) {
|
|
40
|
+
return phonemes.map(([name, duration]) => {
|
|
41
|
+
if (name) {
|
|
42
|
+
return { duration, targets: { [name]: 1.0 } };
|
|
43
|
+
}
|
|
44
|
+
return { duration };
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
speech.fromPhonemes = fromPhonemes;
|
|
48
|
+
})(exports.speech || (exports.speech = {}));
|
package/dist/speech.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Speech utilities for converting phoneme data to Timeline keyframes.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```typescript
|
|
6
|
+
* import { speech, Vrm } from "@hmcs/sdk";
|
|
7
|
+
*
|
|
8
|
+
* const keyframes = speech.fromPhonemes([
|
|
9
|
+
* ["aa", 0.1],
|
|
10
|
+
* [null, 0.05],
|
|
11
|
+
* ["oh", 0.12],
|
|
12
|
+
* ]);
|
|
13
|
+
* const vrm = await Vrm.findByName("MyAvatar");
|
|
14
|
+
* await vrm.speakWithTimeline(wavData, keyframes);
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
var speech;
|
|
18
|
+
(function (speech) {
|
|
19
|
+
/**
|
|
20
|
+
* Creates timeline keyframes from a simple phoneme list.
|
|
21
|
+
*
|
|
22
|
+
* Each entry is a tuple of [expression_name | null, duration_seconds].
|
|
23
|
+
* A null expression name creates a silent keyframe.
|
|
24
|
+
*
|
|
25
|
+
* @param phonemes - Array of [expression_name, duration] tuples.
|
|
26
|
+
* @returns An array of timeline keyframes.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* const keyframes = speech.fromPhonemes([
|
|
31
|
+
* ["aa", 0.1],
|
|
32
|
+
* [null, 0.05],
|
|
33
|
+
* ["oh", 0.12],
|
|
34
|
+
* ]);
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
function fromPhonemes(phonemes) {
|
|
38
|
+
return phonemes.map(([name, duration]) => {
|
|
39
|
+
if (name) {
|
|
40
|
+
return { duration, targets: { [name]: 1.0 } };
|
|
41
|
+
}
|
|
42
|
+
return { duration };
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
speech.fromPhonemes = fromPhonemes;
|
|
46
|
+
})(speech || (speech = {}));
|
|
47
|
+
|
|
48
|
+
export { speech };
|
package/dist/utils.cjs
ADDED