@runwayml/avatars-react 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/NOTICES +41 -0
- package/README.md +328 -0
- package/dist/api.cjs +52 -0
- package/dist/api.cjs.map +1 -0
- package/dist/api.d.cts +33 -0
- package/dist/api.d.ts +33 -0
- package/dist/api.js +47 -0
- package/dist/api.js.map +1 -0
- package/dist/index.cjs +636 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +221 -0
- package/dist/index.d.ts +221 -0
- package/dist/index.js +623 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.css +193 -0
- package/package.json +94 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 RunwayML
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/NOTICES
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
This project includes the following third-party dependencies:
|
|
2
|
+
|
|
3
|
+
================================================================================
|
|
4
|
+
livekit-client
|
|
5
|
+
https://github.com/livekit/client-sdk-js
|
|
6
|
+
--------------------------------------------------------------------------------
|
|
7
|
+
Licensed under the Apache License, Version 2.0
|
|
8
|
+
|
|
9
|
+
Copyright 2023 LiveKit, Inc.
|
|
10
|
+
|
|
11
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
12
|
+
you may not use this file except in compliance with the License.
|
|
13
|
+
You may obtain a copy of the License at
|
|
14
|
+
|
|
15
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
16
|
+
|
|
17
|
+
Unless required by applicable law or agreed to in writing, software
|
|
18
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
19
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
20
|
+
See the License for the specific language governing permissions and
|
|
21
|
+
limitations under the License.
|
|
22
|
+
|
|
23
|
+
================================================================================
|
|
24
|
+
@livekit/components-react
|
|
25
|
+
https://github.com/livekit/components-js
|
|
26
|
+
--------------------------------------------------------------------------------
|
|
27
|
+
Licensed under the Apache License, Version 2.0
|
|
28
|
+
|
|
29
|
+
Copyright 2023 LiveKit, Inc.
|
|
30
|
+
|
|
31
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
32
|
+
you may not use this file except in compliance with the License.
|
|
33
|
+
You may obtain a copy of the License at
|
|
34
|
+
|
|
35
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
36
|
+
|
|
37
|
+
Unless required by applicable law or agreed to in writing, software
|
|
38
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
39
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
40
|
+
See the License for the specific language governing permissions and
|
|
41
|
+
limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
# @runwayml/avatars-react
|
|
2
|
+
|
|
3
|
+
React SDK for real-time AI avatar interactions with GWM-1.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
- React 18+
|
|
8
|
+
- A Runway API secret ([get one here](https://dev.runwayml.com/))
|
|
9
|
+
- A server-side endpoint to create sessions (API secrets must not be exposed to the client)
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @runwayml/avatars-react
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
Add an avatar call to your app with just a few lines:
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { AvatarCall } from '@runwayml/avatars-react';
|
|
23
|
+
|
|
24
|
+
function App() {
|
|
25
|
+
return (
|
|
26
|
+
<AvatarCall
|
|
27
|
+
avatarId="game-host"
|
|
28
|
+
connectUrl="/api/avatar/connect"
|
|
29
|
+
/>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
That's it! The component handles session creation, WebRTC connection, and renders a default UI with the avatar video and controls.
|
|
35
|
+
|
|
36
|
+
You can use preset avatars like `game-host`, `coding-teacher`, `language-tutor`, and more. See the [Runway Developer Portal](https://dev.runwayml.com/) for the full list and creating custom avatars.
|
|
37
|
+
|
|
38
|
+
### Optional: Add Default Styles
|
|
39
|
+
|
|
40
|
+
Import the optional stylesheet for a polished look out of the box:
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
import '@runwayml/avatars-react/styles.css';
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The styles use CSS custom properties for easy customization:
|
|
47
|
+
|
|
48
|
+
```css
|
|
49
|
+
:root {
|
|
50
|
+
--avatar-bg: #a78bfa; /* Video background color */
|
|
51
|
+
--avatar-radius: 16px; /* Container border radius */
|
|
52
|
+
--avatar-control-size: 48px; /* Control button size */
|
|
53
|
+
--avatar-end-call-bg: #ef4444; /* End call button color */
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
See [`examples/`](./examples) for complete working examples:
|
|
58
|
+
- [`nextjs`](./examples/nextjs) - Next.js App Router
|
|
59
|
+
- [`react-router`](./examples/react-router) - React Router v7 framework mode
|
|
60
|
+
- [`express`](./examples/express) - Express + Vite
|
|
61
|
+
|
|
62
|
+
## How It Works
|
|
63
|
+
|
|
64
|
+
1. **Client** calls your server endpoint with the `avatarId`
|
|
65
|
+
2. **Server** uses your Runway API secret to create a session via `@runwayml/sdk`
|
|
66
|
+
3. **Server** returns connection credentials (token, URL) to the client
|
|
67
|
+
4. **Client** establishes a WebRTC connection for real-time video/audio
|
|
68
|
+
|
|
69
|
+
This flow keeps your API secret secure on the server while enabling low-latency communication.
|
|
70
|
+
|
|
71
|
+
## Server Setup
|
|
72
|
+
|
|
73
|
+
Your server endpoint receives the `avatarId` and returns session credentials. Use `@runwayml/sdk` to create the session:
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
// /api/avatar/connect (Next.js App Router example)
|
|
77
|
+
import Runway from '@runwayml/sdk';
|
|
78
|
+
|
|
79
|
+
const runway = new Runway(); // Uses RUNWAYML_API_SECRET env var
|
|
80
|
+
|
|
81
|
+
export async function POST(req: Request) {
|
|
82
|
+
const { avatarId } = await req.json();
|
|
83
|
+
|
|
84
|
+
const session = await runway.realtime.sessions.create({
|
|
85
|
+
model: 'gwm1_avatars',
|
|
86
|
+
options: { avatar: avatarId },
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
return Response.json({
|
|
90
|
+
sessionId: session.id,
|
|
91
|
+
serverUrl: session.url,
|
|
92
|
+
token: session.token,
|
|
93
|
+
roomName: session.room_name,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Customization
|
|
99
|
+
|
|
100
|
+
### Custom Connect Function
|
|
101
|
+
|
|
102
|
+
For more control over the connection flow:
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
<AvatarCall
|
|
106
|
+
avatarId="game-host"
|
|
107
|
+
connect={async (avatarId) => {
|
|
108
|
+
const res = await fetch('/api/avatar/connect', {
|
|
109
|
+
method: 'POST',
|
|
110
|
+
headers: {
|
|
111
|
+
'Authorization': `Bearer ${token}`,
|
|
112
|
+
'Content-Type': 'application/json',
|
|
113
|
+
},
|
|
114
|
+
body: JSON.stringify({ avatarId }),
|
|
115
|
+
});
|
|
116
|
+
return res.json();
|
|
117
|
+
}}
|
|
118
|
+
/>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Custom UI with Child Components
|
|
122
|
+
|
|
123
|
+
Use the built-in components for custom layouts:
|
|
124
|
+
|
|
125
|
+
```tsx
|
|
126
|
+
import { AvatarCall, AvatarVideo, ControlBar, UserVideo } from '@runwayml/avatars-react';
|
|
127
|
+
|
|
128
|
+
<AvatarCall avatarId="game-host" connectUrl="/api/avatar/connect">
|
|
129
|
+
<div className="call-layout">
|
|
130
|
+
<AvatarVideo className="avatar" />
|
|
131
|
+
<UserVideo className="self-view" />
|
|
132
|
+
<ControlBar className="controls" />
|
|
133
|
+
</div>
|
|
134
|
+
</AvatarCall>
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Render Props
|
|
138
|
+
|
|
139
|
+
All components support render props for complete control:
|
|
140
|
+
|
|
141
|
+
```tsx
|
|
142
|
+
<AvatarVideo>
|
|
143
|
+
{({ hasVideo, isConnecting, isSpeaking, trackRef }) => (
|
|
144
|
+
<div className={isSpeaking ? 'speaking' : ''}>
|
|
145
|
+
{isConnecting && <Spinner />}
|
|
146
|
+
{hasVideo && <VideoTrack trackRef={trackRef} />}
|
|
147
|
+
</div>
|
|
148
|
+
)}
|
|
149
|
+
</AvatarVideo>
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### CSS Styling with Data Attributes
|
|
153
|
+
|
|
154
|
+
Style connection states with CSS:
|
|
155
|
+
|
|
156
|
+
```tsx
|
|
157
|
+
<AvatarCall avatarId="game-host" connectUrl="/api/avatar/connect" className="my-avatar" />
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
```css
|
|
161
|
+
.my-avatar[data-state="connecting"] {
|
|
162
|
+
opacity: 0.5;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.my-avatar[data-state="error"] {
|
|
166
|
+
border: 2px solid red;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.my-avatar[data-state="connected"] {
|
|
170
|
+
border: 2px solid green;
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Callbacks
|
|
175
|
+
|
|
176
|
+
```tsx
|
|
177
|
+
<AvatarCall
|
|
178
|
+
avatarId="game-host"
|
|
179
|
+
connectUrl="/api/avatar/connect"
|
|
180
|
+
onEnd={() => console.log('Call ended')}
|
|
181
|
+
onError={(error) => console.error('Error:', error)}
|
|
182
|
+
/>
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Hooks
|
|
186
|
+
|
|
187
|
+
Use hooks for custom components within an `AvatarCall` or `AvatarSession`:
|
|
188
|
+
|
|
189
|
+
### useAvatarSession
|
|
190
|
+
|
|
191
|
+
Access session state and controls:
|
|
192
|
+
|
|
193
|
+
```tsx
|
|
194
|
+
function MyComponent() {
|
|
195
|
+
const { state, sessionId, error, end } = useAvatarSession();
|
|
196
|
+
|
|
197
|
+
if (state === 'connecting') return <Loading />;
|
|
198
|
+
if (state === 'error') return <Error message={error.message} />;
|
|
199
|
+
|
|
200
|
+
return <button onClick={end}>End Call</button>;
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### useAvatar
|
|
205
|
+
|
|
206
|
+
Access the remote avatar's video/audio:
|
|
207
|
+
|
|
208
|
+
```tsx
|
|
209
|
+
function CustomAvatar() {
|
|
210
|
+
const { videoTrackRef, isSpeaking, hasVideo, hasAudio } = useAvatar();
|
|
211
|
+
|
|
212
|
+
return (
|
|
213
|
+
<div data-speaking={isSpeaking}>
|
|
214
|
+
{hasVideo && <VideoTrack trackRef={videoTrackRef} />}
|
|
215
|
+
</div>
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### useLocalMedia
|
|
221
|
+
|
|
222
|
+
Control local camera and microphone:
|
|
223
|
+
|
|
224
|
+
```tsx
|
|
225
|
+
function MediaControls() {
|
|
226
|
+
const {
|
|
227
|
+
isMicEnabled,
|
|
228
|
+
isCameraEnabled,
|
|
229
|
+
toggleMic,
|
|
230
|
+
toggleCamera,
|
|
231
|
+
toggleScreenShare,
|
|
232
|
+
} = useLocalMedia();
|
|
233
|
+
|
|
234
|
+
return (
|
|
235
|
+
<div>
|
|
236
|
+
<button onClick={toggleMic}>{isMicEnabled ? 'Mute' : 'Unmute'}</button>
|
|
237
|
+
<button onClick={toggleCamera}>{isCameraEnabled ? 'Hide' : 'Show'}</button>
|
|
238
|
+
</div>
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Advanced: AvatarSession
|
|
244
|
+
|
|
245
|
+
For full control over session management, use `AvatarSession` directly with pre-fetched credentials:
|
|
246
|
+
|
|
247
|
+
```tsx
|
|
248
|
+
import { AvatarSession, AvatarVideo, ControlBar } from '@runwayml/avatars-react';
|
|
249
|
+
|
|
250
|
+
function AdvancedUsage({ credentials }) {
|
|
251
|
+
return (
|
|
252
|
+
<AvatarSession
|
|
253
|
+
credentials={credentials}
|
|
254
|
+
audio={true}
|
|
255
|
+
video={true}
|
|
256
|
+
onEnd={() => console.log('Ended')}
|
|
257
|
+
onError={(err) => console.error(err)}
|
|
258
|
+
>
|
|
259
|
+
<AvatarVideo />
|
|
260
|
+
<ControlBar />
|
|
261
|
+
</AvatarSession>
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Components Reference
|
|
267
|
+
|
|
268
|
+
| Component | Description |
|
|
269
|
+
|-----------|-------------|
|
|
270
|
+
| `AvatarCall` | High-level component that handles session creation |
|
|
271
|
+
| `AvatarSession` | Low-level wrapper that requires credentials |
|
|
272
|
+
| `AvatarVideo` | Renders the remote avatar video |
|
|
273
|
+
| `UserVideo` | Renders the local user's camera |
|
|
274
|
+
| `ControlBar` | Media control buttons (mic, camera, end call) |
|
|
275
|
+
| `ScreenShareVideo` | Renders screen share content |
|
|
276
|
+
| `AudioRenderer` | Handles avatar audio playback |
|
|
277
|
+
|
|
278
|
+
## TypeScript
|
|
279
|
+
|
|
280
|
+
All components and hooks are fully typed:
|
|
281
|
+
|
|
282
|
+
```tsx
|
|
283
|
+
import type {
|
|
284
|
+
AvatarCallProps,
|
|
285
|
+
SessionCredentials,
|
|
286
|
+
SessionState,
|
|
287
|
+
} from '@runwayml/avatars-react';
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
## Browser Support
|
|
291
|
+
|
|
292
|
+
This SDK uses WebRTC for real-time communication. Supported browsers:
|
|
293
|
+
|
|
294
|
+
- Chrome 74+
|
|
295
|
+
- Firefox 78+
|
|
296
|
+
- Safari 14.1+
|
|
297
|
+
- Edge 79+
|
|
298
|
+
|
|
299
|
+
Users must grant camera and microphone permissions when prompted.
|
|
300
|
+
|
|
301
|
+
## Troubleshooting
|
|
302
|
+
|
|
303
|
+
**"Failed to connect" or timeout errors**
|
|
304
|
+
- Verify your server endpoint is returning the correct credential format
|
|
305
|
+
- Check that `RUNWAYML_API_SECRET` is set correctly on your server
|
|
306
|
+
|
|
307
|
+
**No video/audio**
|
|
308
|
+
- Ensure the user has granted camera/microphone permissions
|
|
309
|
+
- Check browser console for WebRTC errors
|
|
310
|
+
- Verify the device has a working camera/microphone
|
|
311
|
+
|
|
312
|
+
**CORS errors**
|
|
313
|
+
- Your server endpoint must accept requests from your client's origin
|
|
314
|
+
- For local development, ensure both client and server are on compatible origins
|
|
315
|
+
|
|
316
|
+
## Agent Skill
|
|
317
|
+
|
|
318
|
+
This SDK includes an [Agent Skill](https://agentskills.io/) that teaches AI agents how to use the Runway Avatar SDK effectively. Install it with:
|
|
319
|
+
|
|
320
|
+
```bash
|
|
321
|
+
npx skills add runwayml/avatars-sdk-react
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
Once installed, AI coding assistants like Claude Code, Cursor, Cline, and others will have access to SDK documentation, patterns, and best practices when helping you build avatar-powered applications.
|
|
325
|
+
|
|
326
|
+
## License
|
|
327
|
+
|
|
328
|
+
MIT
|
package/dist/api.cjs
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/api/config.ts
|
|
4
|
+
var DEFAULT_BASE_URL = "https://api.dev.runwayml.com";
|
|
5
|
+
function getBaseUrl() {
|
|
6
|
+
try {
|
|
7
|
+
const envUrl = process.env.RUNWAYML_BASE_URL;
|
|
8
|
+
if (envUrl) return envUrl;
|
|
9
|
+
} catch {
|
|
10
|
+
}
|
|
11
|
+
return DEFAULT_BASE_URL;
|
|
12
|
+
}
|
|
13
|
+
var config = null;
|
|
14
|
+
function configure(options) {
|
|
15
|
+
config = { ...getConfig(), ...options };
|
|
16
|
+
}
|
|
17
|
+
function getConfig() {
|
|
18
|
+
if (!config) {
|
|
19
|
+
config = { baseUrl: getBaseUrl() };
|
|
20
|
+
}
|
|
21
|
+
return config;
|
|
22
|
+
}
|
|
23
|
+
function resetConfig() {
|
|
24
|
+
config = null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// src/api/consume.ts
|
|
28
|
+
async function consumeSession(options) {
|
|
29
|
+
const { sessionId, sessionKey, baseUrl = getConfig().baseUrl } = options;
|
|
30
|
+
const url = `${baseUrl}/v1/realtime_sessions/${sessionId}/consume`;
|
|
31
|
+
const response = await fetch(url, {
|
|
32
|
+
method: "POST",
|
|
33
|
+
headers: {
|
|
34
|
+
"Content-Type": "application/json",
|
|
35
|
+
Authorization: `Bearer ${sessionKey}`
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
if (!response.ok) {
|
|
39
|
+
const errorText = await response.text();
|
|
40
|
+
throw new Error(
|
|
41
|
+
`Failed to consume session: ${response.status} ${errorText}`
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
return response.json();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
exports.configure = configure;
|
|
48
|
+
exports.consumeSession = consumeSession;
|
|
49
|
+
exports.getConfig = getConfig;
|
|
50
|
+
exports.resetConfig = resetConfig;
|
|
51
|
+
//# sourceMappingURL=api.cjs.map
|
|
52
|
+
//# sourceMappingURL=api.cjs.map
|
package/dist/api.cjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/api/config.ts","../src/api/consume.ts"],"names":[],"mappings":";;;AAIA,IAAM,gBAAA,GAAmB,8BAAA;AAEzB,SAAS,UAAA,GAAqB;AAC5B,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,QAAQ,GAAA,CAAI,iBAAA;AAC3B,IAAA,IAAI,QAAQ,OAAO,MAAA;AAAA,EACrB,CAAA,CAAA,MAAQ;AAAA,EAER;AACA,EAAA,OAAO,gBAAA;AACT;AAEA,IAAI,MAAA,GAA2B,IAAA;AAExB,SAAS,UAAU,OAAA,EAAmC;AAC3D,EAAA,MAAA,GAAS,EAAE,GAAG,SAAA,EAAU,EAAG,GAAG,OAAA,EAAQ;AACxC;AAEO,SAAS,SAAA,GAAuB;AACrC,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,MAAA,GAAS,EAAE,OAAA,EAAS,UAAA,EAAW,EAAE;AAAA,EACnC;AACA,EAAA,OAAO,MAAA;AACT;AAEO,SAAS,WAAA,GAAoB;AAClC,EAAA,MAAA,GAAS,IAAA;AACX;;;AC5BA,eAAsB,eACpB,OAAA,EACiC;AACjC,EAAA,MAAM,EAAE,SAAA,EAAW,UAAA,EAAY,UAAU,SAAA,EAAU,CAAE,SAAQ,GAAI,OAAA;AAEjE,EAAA,MAAM,GAAA,GAAM,CAAA,EAAG,OAAO,CAAA,sBAAA,EAAyB,SAAS,CAAA,QAAA,CAAA;AACxD,EAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK;AAAA,IAChC,MAAA,EAAQ,MAAA;AAAA,IACR,OAAA,EAAS;AAAA,MACP,cAAA,EAAgB,kBAAA;AAAA,MAChB,aAAA,EAAe,UAAU,UAAU,CAAA;AAAA;AACrC,GACD,CAAA;AAED,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,IAAA,MAAM,SAAA,GAAY,MAAM,QAAA,CAAS,IAAA,EAAK;AACtC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,2BAAA,EAA8B,QAAA,CAAS,MAAM,CAAA,CAAA,EAAI,SAAS,CAAA;AAAA,KAC5D;AAAA,EACF;AAEA,EAAA,OAAO,SAAS,IAAA,EAAK;AACvB","file":"api.cjs","sourcesContent":["export interface ApiConfig {\n baseUrl: string;\n}\n\nconst DEFAULT_BASE_URL = 'https://api.dev.runwayml.com';\n\nfunction getBaseUrl(): string {\n try {\n const envUrl = process.env.RUNWAYML_BASE_URL;\n if (envUrl) return envUrl;\n } catch {\n // process not available in browser\n }\n return DEFAULT_BASE_URL;\n}\n\nlet config: ApiConfig | null = null;\n\nexport function configure(options: Partial<ApiConfig>): void {\n config = { ...getConfig(), ...options };\n}\n\nexport function getConfig(): ApiConfig {\n if (!config) {\n config = { baseUrl: getBaseUrl() };\n }\n return config;\n}\n\nexport function resetConfig(): void {\n config = null;\n}\n","import type { ConsumeSessionOptions, ConsumeSessionResponse } from '../types';\nimport { getConfig } from './config';\n\nexport async function consumeSession(\n options: ConsumeSessionOptions,\n): Promise<ConsumeSessionResponse> {\n const { sessionId, sessionKey, baseUrl = getConfig().baseUrl } = options;\n\n const url = `${baseUrl}/v1/realtime_sessions/${sessionId}/consume`;\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${sessionKey}`,\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to consume session: ${response.status} ${errorText}`,\n );\n }\n\n return response.json();\n}\n"]}
|
package/dist/api.d.cts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connection credentials returned from the Runway API consume endpoint
|
|
3
|
+
*/
|
|
4
|
+
interface ConsumeSessionResponse {
|
|
5
|
+
/** WebRTC server URL */
|
|
6
|
+
url: string;
|
|
7
|
+
/** Authentication token */
|
|
8
|
+
token: string;
|
|
9
|
+
/** Room name for the session */
|
|
10
|
+
roomName: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Options for consuming a session from the Runway API
|
|
14
|
+
*/
|
|
15
|
+
interface ConsumeSessionOptions {
|
|
16
|
+
/** The session ID to consume */
|
|
17
|
+
sessionId: string;
|
|
18
|
+
/** The session key for authentication (from GET session response when READY) */
|
|
19
|
+
sessionKey: string;
|
|
20
|
+
/** Optional base URL for the Runway API (defaults to production) */
|
|
21
|
+
baseUrl?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface ApiConfig {
|
|
25
|
+
baseUrl: string;
|
|
26
|
+
}
|
|
27
|
+
declare function configure(options: Partial<ApiConfig>): void;
|
|
28
|
+
declare function getConfig(): ApiConfig;
|
|
29
|
+
declare function resetConfig(): void;
|
|
30
|
+
|
|
31
|
+
declare function consumeSession(options: ConsumeSessionOptions): Promise<ConsumeSessionResponse>;
|
|
32
|
+
|
|
33
|
+
export { type ApiConfig, type ConsumeSessionOptions, type ConsumeSessionResponse, configure, consumeSession, getConfig, resetConfig };
|
package/dist/api.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connection credentials returned from the Runway API consume endpoint
|
|
3
|
+
*/
|
|
4
|
+
interface ConsumeSessionResponse {
|
|
5
|
+
/** WebRTC server URL */
|
|
6
|
+
url: string;
|
|
7
|
+
/** Authentication token */
|
|
8
|
+
token: string;
|
|
9
|
+
/** Room name for the session */
|
|
10
|
+
roomName: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Options for consuming a session from the Runway API
|
|
14
|
+
*/
|
|
15
|
+
interface ConsumeSessionOptions {
|
|
16
|
+
/** The session ID to consume */
|
|
17
|
+
sessionId: string;
|
|
18
|
+
/** The session key for authentication (from GET session response when READY) */
|
|
19
|
+
sessionKey: string;
|
|
20
|
+
/** Optional base URL for the Runway API (defaults to production) */
|
|
21
|
+
baseUrl?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface ApiConfig {
|
|
25
|
+
baseUrl: string;
|
|
26
|
+
}
|
|
27
|
+
declare function configure(options: Partial<ApiConfig>): void;
|
|
28
|
+
declare function getConfig(): ApiConfig;
|
|
29
|
+
declare function resetConfig(): void;
|
|
30
|
+
|
|
31
|
+
declare function consumeSession(options: ConsumeSessionOptions): Promise<ConsumeSessionResponse>;
|
|
32
|
+
|
|
33
|
+
export { type ApiConfig, type ConsumeSessionOptions, type ConsumeSessionResponse, configure, consumeSession, getConfig, resetConfig };
|
package/dist/api.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// src/api/config.ts
|
|
2
|
+
var DEFAULT_BASE_URL = "https://api.dev.runwayml.com";
|
|
3
|
+
function getBaseUrl() {
|
|
4
|
+
try {
|
|
5
|
+
const envUrl = process.env.RUNWAYML_BASE_URL;
|
|
6
|
+
if (envUrl) return envUrl;
|
|
7
|
+
} catch {
|
|
8
|
+
}
|
|
9
|
+
return DEFAULT_BASE_URL;
|
|
10
|
+
}
|
|
11
|
+
var config = null;
|
|
12
|
+
function configure(options) {
|
|
13
|
+
config = { ...getConfig(), ...options };
|
|
14
|
+
}
|
|
15
|
+
function getConfig() {
|
|
16
|
+
if (!config) {
|
|
17
|
+
config = { baseUrl: getBaseUrl() };
|
|
18
|
+
}
|
|
19
|
+
return config;
|
|
20
|
+
}
|
|
21
|
+
function resetConfig() {
|
|
22
|
+
config = null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// src/api/consume.ts
|
|
26
|
+
async function consumeSession(options) {
|
|
27
|
+
const { sessionId, sessionKey, baseUrl = getConfig().baseUrl } = options;
|
|
28
|
+
const url = `${baseUrl}/v1/realtime_sessions/${sessionId}/consume`;
|
|
29
|
+
const response = await fetch(url, {
|
|
30
|
+
method: "POST",
|
|
31
|
+
headers: {
|
|
32
|
+
"Content-Type": "application/json",
|
|
33
|
+
Authorization: `Bearer ${sessionKey}`
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
if (!response.ok) {
|
|
37
|
+
const errorText = await response.text();
|
|
38
|
+
throw new Error(
|
|
39
|
+
`Failed to consume session: ${response.status} ${errorText}`
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
return response.json();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export { configure, consumeSession, getConfig, resetConfig };
|
|
46
|
+
//# sourceMappingURL=api.js.map
|
|
47
|
+
//# sourceMappingURL=api.js.map
|
package/dist/api.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/api/config.ts","../src/api/consume.ts"],"names":[],"mappings":";AAIA,IAAM,gBAAA,GAAmB,8BAAA;AAEzB,SAAS,UAAA,GAAqB;AAC5B,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,QAAQ,GAAA,CAAI,iBAAA;AAC3B,IAAA,IAAI,QAAQ,OAAO,MAAA;AAAA,EACrB,CAAA,CAAA,MAAQ;AAAA,EAER;AACA,EAAA,OAAO,gBAAA;AACT;AAEA,IAAI,MAAA,GAA2B,IAAA;AAExB,SAAS,UAAU,OAAA,EAAmC;AAC3D,EAAA,MAAA,GAAS,EAAE,GAAG,SAAA,EAAU,EAAG,GAAG,OAAA,EAAQ;AACxC;AAEO,SAAS,SAAA,GAAuB;AACrC,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,MAAA,GAAS,EAAE,OAAA,EAAS,UAAA,EAAW,EAAE;AAAA,EACnC;AACA,EAAA,OAAO,MAAA;AACT;AAEO,SAAS,WAAA,GAAoB;AAClC,EAAA,MAAA,GAAS,IAAA;AACX;;;AC5BA,eAAsB,eACpB,OAAA,EACiC;AACjC,EAAA,MAAM,EAAE,SAAA,EAAW,UAAA,EAAY,UAAU,SAAA,EAAU,CAAE,SAAQ,GAAI,OAAA;AAEjE,EAAA,MAAM,GAAA,GAAM,CAAA,EAAG,OAAO,CAAA,sBAAA,EAAyB,SAAS,CAAA,QAAA,CAAA;AACxD,EAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK;AAAA,IAChC,MAAA,EAAQ,MAAA;AAAA,IACR,OAAA,EAAS;AAAA,MACP,cAAA,EAAgB,kBAAA;AAAA,MAChB,aAAA,EAAe,UAAU,UAAU,CAAA;AAAA;AACrC,GACD,CAAA;AAED,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,IAAA,MAAM,SAAA,GAAY,MAAM,QAAA,CAAS,IAAA,EAAK;AACtC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,2BAAA,EAA8B,QAAA,CAAS,MAAM,CAAA,CAAA,EAAI,SAAS,CAAA;AAAA,KAC5D;AAAA,EACF;AAEA,EAAA,OAAO,SAAS,IAAA,EAAK;AACvB","file":"api.js","sourcesContent":["export interface ApiConfig {\n baseUrl: string;\n}\n\nconst DEFAULT_BASE_URL = 'https://api.dev.runwayml.com';\n\nfunction getBaseUrl(): string {\n try {\n const envUrl = process.env.RUNWAYML_BASE_URL;\n if (envUrl) return envUrl;\n } catch {\n // process not available in browser\n }\n return DEFAULT_BASE_URL;\n}\n\nlet config: ApiConfig | null = null;\n\nexport function configure(options: Partial<ApiConfig>): void {\n config = { ...getConfig(), ...options };\n}\n\nexport function getConfig(): ApiConfig {\n if (!config) {\n config = { baseUrl: getBaseUrl() };\n }\n return config;\n}\n\nexport function resetConfig(): void {\n config = null;\n}\n","import type { ConsumeSessionOptions, ConsumeSessionResponse } from '../types';\nimport { getConfig } from './config';\n\nexport async function consumeSession(\n options: ConsumeSessionOptions,\n): Promise<ConsumeSessionResponse> {\n const { sessionId, sessionKey, baseUrl = getConfig().baseUrl } = options;\n\n const url = `${baseUrl}/v1/realtime_sessions/${sessionId}/consume`;\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${sessionKey}`,\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to consume session: ${response.status} ${errorText}`,\n );\n }\n\n return response.json();\n}\n"]}
|