@stinkycomputing/sesame-api-client 1.4.1-alpha.9 → 1.4.1-beta.1
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 +59 -137
- package/dist/index.browser.mjs +706 -274
- package/dist/index.browser.mjs.map +4 -4
- package/dist/index.cjs +710 -276
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +706 -274
- package/dist/index.mjs.map +4 -4
- package/dist/proto/api.d.ts +305 -0
- package/dist/proto/api.js +922 -0
- package/dist/rpc-client.d.ts.map +1 -1
- package/dist/sesame-api-client.d.ts +5 -6
- package/dist/sesame-api-client.d.ts.map +1 -1
- package/dist/sesame-connection.d.ts +11 -2
- package/dist/sesame-connection.d.ts.map +1 -1
- package/dist/sesame-wire-protocol.d.ts +29 -0
- package/dist/sesame-wire-protocol.d.ts.map +1 -0
- package/dist/status-api.d.ts +0 -1
- package/dist/status-api.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
# @stinkycomputing/sesame-api-client
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
TypeScript client library for the Sesame video production server. Provides type-safe protobuf definitions, a WebSocket RPC client with reconnection, and helpers for building command lists.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
All websocket traffic uses protobuf wire framing — see [Wire Protocol](#wire-protocol).
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- 🔧 **Command List Helper** - Fluent API for building command lists
|
|
9
|
-
- 🌐 **RPC Client** - WebSocket-based RPC client with automatic reconnection
|
|
10
|
-
- 📦 **Modular Design** - New v1 API with domain-specific modules
|
|
11
|
-
- 🔄 **Backward Compatible** - Supports both legacy and new API structures
|
|
12
|
-
|
|
13
|
-
## Installation
|
|
7
|
+
## Install
|
|
14
8
|
|
|
15
9
|
```bash
|
|
16
10
|
npm install @stinkycomputing/sesame-api-client
|
|
@@ -18,196 +12,124 @@ npm install @stinkycomputing/sesame-api-client
|
|
|
18
12
|
|
|
19
13
|
## Quick Start
|
|
20
14
|
|
|
21
|
-
### Node.js (Full Client with RPC)
|
|
22
|
-
|
|
23
|
-
For Node.js applications that need the full RPC client:
|
|
24
|
-
|
|
25
15
|
```typescript
|
|
26
16
|
import { SesameClient, CommandList } from '@stinkycomputing/sesame-api-client';
|
|
27
17
|
|
|
28
|
-
|
|
29
|
-
const client = new SesameClient(8080);
|
|
18
|
+
const client = new SesameClient(9000);
|
|
30
19
|
|
|
31
|
-
// Build command list
|
|
32
20
|
const cl = new CommandList();
|
|
33
|
-
cl.sourceAdd('my-source', {
|
|
34
|
-
type: 'file',
|
|
35
|
-
path: '/path/to/video.mp4'
|
|
36
|
-
});
|
|
21
|
+
cl.sourceAdd('my-source', { type: 'file', path: '/path/to/video.mp4' });
|
|
37
22
|
cl.compositorAdd('main', 1920, 1080, false);
|
|
38
23
|
|
|
39
|
-
// Execute commands
|
|
40
24
|
await client.execute(cl);
|
|
41
|
-
|
|
42
|
-
// Listen to events
|
|
43
|
-
client.on('status', (status) => {
|
|
44
|
-
console.log('Status update:', status);
|
|
45
|
-
});
|
|
46
25
|
```
|
|
47
26
|
|
|
48
|
-
|
|
27
|
+
Works in the browser too — the browser entry point bundles `events` and other Node built-ins so `SesameClient`, `RPCClient`, and `WireProtocol` all work without polyfills.
|
|
49
28
|
|
|
50
|
-
|
|
29
|
+
## Protobuf Modules
|
|
51
30
|
|
|
52
|
-
|
|
53
|
-
import { Sesame } from '@stinkycomputing/sesame-api-client/browser';
|
|
31
|
+
Types are generated from `.proto` files under `sesame.v1.*`:
|
|
54
32
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const status = Sesame.PB.StatusMessage.decode(statusBytes);
|
|
58
|
-
const statusObj = Sesame.PB.StatusMessage.toObject(status, { longs: Number });
|
|
59
|
-
console.log('Status:', statusObj);
|
|
33
|
+
```typescript
|
|
34
|
+
import { sesame } from '@stinkycomputing/sesame-api-client';
|
|
60
35
|
```
|
|
61
36
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
37
|
+
| Module | Contents |
|
|
38
|
+
|--------|----------|
|
|
39
|
+
| `sesame.v1.wire` | Wire framing (FrameHeader, FrameType, MediaCodecData) |
|
|
40
|
+
| `sesame.v1.common` | Shared types (Empty, Vec4, PropValue, EventTopic) |
|
|
41
|
+
| `sesame.v1.sources` | Source config and transport |
|
|
42
|
+
| `sesame.v1.outputs` | Output config and encoder settings |
|
|
43
|
+
| `sesame.v1.compositor` | Scene graph, nodes, properties, animations |
|
|
44
|
+
| `sesame.v1.audio` | Audio mixer and channels |
|
|
45
|
+
| `sesame.v1.recorder` | Recorder, clips, playlists |
|
|
46
|
+
| `sesame.v1.jobs` | Background export/import jobs |
|
|
47
|
+
| `sesame.v1.status` | Status polling and event subscriptions |
|
|
48
|
+
| `sesame.v1.commands` | Command list items |
|
|
49
|
+
| `sesame.v1.rpc` | RPC message envelope (Request/Response/Event) |
|
|
69
50
|
|
|
70
|
-
##
|
|
51
|
+
## Wire Protocol
|
|
71
52
|
|
|
72
|
-
|
|
53
|
+
Every websocket message is framed as:
|
|
73
54
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
```typescript
|
|
77
|
-
import { Sesame } from '@stinkycomputing/sesame-api-client';
|
|
78
|
-
|
|
79
|
-
const msg: Sesame.PB.AddSourceMessage = {
|
|
80
|
-
id: 'source1',
|
|
81
|
-
type: Sesame.PB.SourceType.ST_FILE,
|
|
82
|
-
// ...
|
|
83
|
-
};
|
|
55
|
+
```
|
|
56
|
+
[4-byte LE header_size][FrameHeader protobuf][payload bytes]
|
|
84
57
|
```
|
|
85
58
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
The new API is organized into domain-specific modules:
|
|
59
|
+
`WireProtocol.serialize` / `WireProtocol.parse` handle this:
|
|
89
60
|
|
|
90
61
|
```typescript
|
|
91
|
-
import { sesame } from '@stinkycomputing/sesame-api-client';
|
|
62
|
+
import { WireProtocol, sesame } from '@stinkycomputing/sesame-api-client';
|
|
92
63
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
type: sesame.v1.
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
```
|
|
64
|
+
// serialize
|
|
65
|
+
const frame = WireProtocol.serialize(
|
|
66
|
+
{ type: sesame.v1.wire.FrameType.FRAME_TYPE_RPC },
|
|
67
|
+
rpcPayload,
|
|
68
|
+
);
|
|
99
69
|
|
|
100
|
-
|
|
70
|
+
// parse
|
|
71
|
+
const parsed = WireProtocol.parse(incoming);
|
|
72
|
+
if (parsed.valid) {
|
|
73
|
+
// parsed.header.type, parsed.payload
|
|
74
|
+
}
|
|
75
|
+
```
|
|
101
76
|
|
|
102
|
-
|
|
103
|
-
- `sesame.v1.sources` - Source management
|
|
104
|
-
- `sesame.v1.outputs` - Output management
|
|
105
|
-
- `sesame.v1.compositor` - Compositor and scene graph
|
|
106
|
-
- `sesame.v1.audio` - Audio mixer
|
|
107
|
-
- `sesame.v1.recorder` - Recorder and clips
|
|
108
|
-
- `sesame.v1.jobs` - Background jobs (export/import)
|
|
109
|
-
- `sesame.v1.status` - Status and events
|
|
110
|
-
- `sesame.v1.commands` - Command list system
|
|
111
|
-
- `sesame.v1.rpc` - RPC protocol
|
|
77
|
+
Frame types: `FRAME_TYPE_RPC`, `FRAME_TYPE_VIDEO`, `FRAME_TYPE_AUDIO`, `FRAME_TYPE_MUXED`, `FRAME_TYPE_DECODER_DATA`.
|
|
112
78
|
|
|
113
|
-
## Command List
|
|
79
|
+
## Command List
|
|
114
80
|
|
|
115
|
-
|
|
81
|
+
`CommandList` builds a batch of operations to send in one `execute` call:
|
|
116
82
|
|
|
117
83
|
```typescript
|
|
118
84
|
const cl = new CommandList();
|
|
119
85
|
|
|
120
|
-
|
|
121
|
-
cl.sourceAdd('cam1', {
|
|
122
|
-
type: 'decklink',
|
|
123
|
-
deviceIndex: 0
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
// Add compositor
|
|
86
|
+
cl.sourceAdd('cam1', { type: 'decklink', deviceIndex: 0 });
|
|
127
87
|
cl.compositorAdd('main', 1920, 1080, false);
|
|
88
|
+
cl.nodeAdd('main', 'cam1-node', 'source', { sourceId: 'cam1' });
|
|
128
89
|
|
|
129
|
-
// Add node to compositor
|
|
130
|
-
cl.nodeAdd('main', 'cam1-node', 'source', {
|
|
131
|
-
sourceId: 'cam1'
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
// Set properties
|
|
135
90
|
cl.propertySet(
|
|
136
91
|
{ compositor: 'main', node: 'cam1-node' },
|
|
137
|
-
'transform',
|
|
138
|
-
|
|
139
|
-
{ vecValue: { r: 100, g: 100 } }
|
|
92
|
+
'transform', 'position',
|
|
93
|
+
{ vecValue: { r: 100, g: 100 } },
|
|
140
94
|
);
|
|
141
95
|
|
|
142
|
-
// Transport control
|
|
143
96
|
cl.transportCommand('cam1', { type: 'play' });
|
|
144
97
|
|
|
145
|
-
// Execute all commands
|
|
146
98
|
await client.execute(cl);
|
|
147
99
|
```
|
|
148
100
|
|
|
149
101
|
### Animations
|
|
150
102
|
|
|
151
|
-
Use the `keyframe()` helper to build type-safe animation keyframes. The easing parameters are constrained to the `EaseKind` enum, so invalid values are caught at compile time:
|
|
152
|
-
|
|
153
103
|
```typescript
|
|
154
104
|
import { CommandList, keyframe, EaseKind, sesame } from '@stinkycomputing/sesame-api-client';
|
|
155
105
|
|
|
156
106
|
const cl = new CommandList();
|
|
157
|
-
|
|
158
107
|
cl.propertyAnimate(
|
|
159
|
-
{ compositor: 'main', node: 'cam1-node' },
|
|
160
|
-
'cam1-node',
|
|
161
|
-
|
|
162
|
-
sesame.v1.compositor.AnimationChannelEvaluationMode.HOLD,
|
|
163
|
-
sesame.v1.compositor.AnimationChannelEvaluationMode.HOLD, // after
|
|
108
|
+
{ compositor: 'main', node: 'cam1-node' },
|
|
109
|
+
'cam1-node', 'opacity',
|
|
110
|
+
sesame.v1.compositor.AnimationChannelEvaluationMode.HOLD,
|
|
111
|
+
sesame.v1.compositor.AnimationChannelEvaluationMode.HOLD,
|
|
164
112
|
[
|
|
165
113
|
keyframe(0, { floatValue: 0.0 }),
|
|
166
114
|
keyframe(500000, { floatValue: 1.0 }, EaseKind.QUADRATIC_INOUT),
|
|
167
115
|
keyframe(1000000, { floatValue: 0.5 }, EaseKind.CUBIC_IN, EaseKind.CUBIC_OUT),
|
|
168
|
-
]
|
|
116
|
+
],
|
|
169
117
|
);
|
|
170
118
|
```
|
|
171
119
|
|
|
172
|
-
|
|
173
|
-
- **timeUs** — time in microseconds
|
|
174
|
-
- **value** — a `PropValue` (`floatValue`, `intValue`, `vec4Value`, `stringValue`, or `boolValue`)
|
|
175
|
-
- **easingIn** *(optional)* — easing curve entering this keyframe (`EaseKind`)
|
|
176
|
-
- **easingOut** *(optional)* — easing curve leaving this keyframe (`EaseKind`)
|
|
120
|
+
`keyframe(timeUs, value, easingIn?, easingOut?)` — time in microseconds, value is a `PropValue`, easing uses `EaseKind`.
|
|
177
121
|
|
|
178
|
-
##
|
|
122
|
+
## Bundling
|
|
179
123
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
- **Bundle the package**: Include `@stinkycomputing/sesame-api-client` in your bundle for zero-dependency deployment
|
|
183
|
-
- **External native deps**: Only mark native binary modules as external (`ws`, `bufferutil`, `utf-8-validate`)
|
|
184
|
-
- **Production install**: Only `npm install` the native dependencies in production
|
|
185
|
-
|
|
186
|
-
This approach gives you:
|
|
187
|
-
- ✅ Single bundle file with all code
|
|
188
|
-
- ✅ Minimal production dependencies (3 packages)
|
|
189
|
-
- ✅ Fast deployment
|
|
190
|
-
- ✅ No version conflicts
|
|
124
|
+
All dependencies (`events`, `long`, `protobufjs`) are pure JS — no native modules. The package bundles cleanly with esbuild or similar without any special `external` config.
|
|
191
125
|
|
|
192
126
|
## Publishing
|
|
193
127
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
1. Create the `@stinkycomputing` organization on [npmjs.com](https://www.npmjs.com/org/create)
|
|
199
|
-
2. Log in to npm: `npm login`
|
|
200
|
-
|
|
201
|
-
### Release process
|
|
202
|
-
|
|
203
|
-
1. Update the version in `package.json`
|
|
204
|
-
2. Build: `npm run build`
|
|
205
|
-
3. Publish:
|
|
206
|
-
- **Stable release:** `npm publish --access public`
|
|
207
|
-
- **Prerelease:** `npm publish --access public --tag alpha` (or `beta`, etc.)
|
|
208
|
-
4. Commit and tag: `git tag api-client-vX.Y.Z && git push origin api-client-vX.Y.Z`
|
|
128
|
+
1. Bump version in `package.json`
|
|
129
|
+
2. `npm run build`
|
|
130
|
+
3. `npm publish --access public` (or `--tag alpha` for prereleases)
|
|
131
|
+
4. `git tag api-client-vX.Y.Z && git push origin api-client-vX.Y.Z`
|
|
209
132
|
|
|
210
133
|
## License
|
|
211
134
|
|
|
212
135
|
MIT
|
|
213
|
-
|