@matbee/remotemedia-native 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/README.md +229 -0
- package/index.d.ts +717 -0
- package/index.js +138 -0
- package/node-schemas.json +343 -0
- package/node-schemas.ts +689 -0
- package/package.json +106 -0
- package/proto-utils.d.ts +97 -0
- package/proto-utils.js +376 -0
- package/remotemedia-native.x86_64-unknown-linux-gnu.node +0 -0
package/README.md
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# @remotemedia/native
|
|
2
|
+
|
|
3
|
+
Native Node.js bindings for RemoteMedia zero-copy IPC with iceoryx2 shared memory.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This package provides high-performance Node.js bindings for the RemoteMedia pipeline execution framework. It enables:
|
|
8
|
+
|
|
9
|
+
- **Zero-copy IPC**: Share data between Node.js, Python, and Rust processes via shared memory
|
|
10
|
+
- **Pipeline execution**: Run audio/video/ML pipelines with native performance
|
|
11
|
+
- **Type-safe API**: Full TypeScript definitions generated from Rust schemas
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @remotemedia/native
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Requirements
|
|
20
|
+
|
|
21
|
+
- Node.js >= 18
|
|
22
|
+
- Linux (x64, arm64) or macOS (x64, arm64)
|
|
23
|
+
- For WebRTC features: see `@remotemedia/native-webrtc`
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import {
|
|
29
|
+
createSession,
|
|
30
|
+
NapiRuntimeData,
|
|
31
|
+
isNativeLoaded,
|
|
32
|
+
} from '@remotemedia/native';
|
|
33
|
+
|
|
34
|
+
// Check if native bindings loaded successfully
|
|
35
|
+
if (!isNativeLoaded()) {
|
|
36
|
+
console.error('Native bindings failed to load');
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Create an IPC session for zero-copy communication
|
|
41
|
+
const session = createSession({
|
|
42
|
+
id: 'my_session',
|
|
43
|
+
default_channel_config: {
|
|
44
|
+
capacity: 64,
|
|
45
|
+
max_payload_size: 1_048_576, // 1MB
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Create a channel for audio data
|
|
50
|
+
const channel = session.channel('audio_data');
|
|
51
|
+
|
|
52
|
+
// Publisher side
|
|
53
|
+
const publisher = channel.createPublisher();
|
|
54
|
+
const audioData = NapiRuntimeData.audio(
|
|
55
|
+
new Float32Array(16000), // 1 second of silence at 16kHz
|
|
56
|
+
16000, // sample rate
|
|
57
|
+
1 // channels
|
|
58
|
+
);
|
|
59
|
+
publisher.publish(audioData);
|
|
60
|
+
|
|
61
|
+
// Subscriber side
|
|
62
|
+
const subscriber = channel.createSubscriber();
|
|
63
|
+
const unsubscribe = subscriber.onData((sample) => {
|
|
64
|
+
try {
|
|
65
|
+
const buffer = sample.buffer;
|
|
66
|
+
// Process audio data...
|
|
67
|
+
} finally {
|
|
68
|
+
sample.release(); // IMPORTANT: Return sample to pool
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Cleanup
|
|
73
|
+
unsubscribe();
|
|
74
|
+
subscriber.close();
|
|
75
|
+
publisher.close();
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## API Reference
|
|
79
|
+
|
|
80
|
+
### Session Management
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
// Create a new IPC session
|
|
84
|
+
const session = createSession({
|
|
85
|
+
id: 'session_id', // 8-64 chars, alphanumeric + underscore/hyphen
|
|
86
|
+
default_channel_config: {
|
|
87
|
+
capacity: 64, // Message queue size
|
|
88
|
+
max_payload_size: 1_048_576,
|
|
89
|
+
backpressure: false,
|
|
90
|
+
history_size: 0,
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// Get existing session
|
|
95
|
+
const existing = getSession('session_id');
|
|
96
|
+
|
|
97
|
+
// List all sessions
|
|
98
|
+
const sessions = listSessions();
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### RuntimeData Types
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
// Audio data
|
|
105
|
+
const audio = NapiRuntimeData.audio(samples: Float32Array, sampleRate: number, channels: number);
|
|
106
|
+
|
|
107
|
+
// Video data
|
|
108
|
+
const video = NapiRuntimeData.video(
|
|
109
|
+
pixels: Uint8Array,
|
|
110
|
+
width: number,
|
|
111
|
+
height: number,
|
|
112
|
+
format: 'yuv420p' | 'rgb24' | 'rgba32' | 'gray8',
|
|
113
|
+
codec?: string,
|
|
114
|
+
frameNumber?: number,
|
|
115
|
+
isKeyframe?: boolean
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
// Text/JSON
|
|
119
|
+
const text = NapiRuntimeData.text('hello world');
|
|
120
|
+
const json = NapiRuntimeData.json({ key: 'value' });
|
|
121
|
+
|
|
122
|
+
// Binary/Tensor
|
|
123
|
+
const binary = NapiRuntimeData.binary(buffer: Uint8Array);
|
|
124
|
+
const tensor = NapiRuntimeData.tensor(data: Uint8Array, shape: number[], dtype: string);
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Publisher
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
const publisher = channel.createPublisher();
|
|
131
|
+
|
|
132
|
+
// Direct publish
|
|
133
|
+
publisher.publish(runtimeData);
|
|
134
|
+
|
|
135
|
+
// Zero-copy loan pattern (for large data)
|
|
136
|
+
const loaned = publisher.loan(bufferSize);
|
|
137
|
+
loaned.write(data);
|
|
138
|
+
loaned.send();
|
|
139
|
+
|
|
140
|
+
publisher.close();
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Subscriber
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
const subscriber = channel.createSubscriber();
|
|
147
|
+
|
|
148
|
+
// Register callback
|
|
149
|
+
const unsubscribe = subscriber.onData((sample) => {
|
|
150
|
+
const buffer = sample.buffer;
|
|
151
|
+
const timestamp = sample.timestampNs;
|
|
152
|
+
|
|
153
|
+
// Process data...
|
|
154
|
+
|
|
155
|
+
sample.release(); // Required!
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// Cleanup
|
|
159
|
+
unsubscribe();
|
|
160
|
+
subscriber.close();
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Pipeline Execution
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
import { executePipeline, createStreamSession } from '@remotemedia/native';
|
|
167
|
+
|
|
168
|
+
// One-shot pipeline execution
|
|
169
|
+
const manifest = {
|
|
170
|
+
version: '1.0',
|
|
171
|
+
nodes: [
|
|
172
|
+
{ id: 'input', nodeType: 'AudioInput' },
|
|
173
|
+
{ id: 'vad', nodeType: 'SileroVAD', config: { threshold: 0.5 } },
|
|
174
|
+
],
|
|
175
|
+
connections: [
|
|
176
|
+
{ source: 'input', destination: 'vad' },
|
|
177
|
+
],
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const output = await executePipeline(JSON.stringify(manifest), inputs);
|
|
181
|
+
|
|
182
|
+
// Streaming session
|
|
183
|
+
const session = await createStreamSession(JSON.stringify(manifest));
|
|
184
|
+
await session.sendInput(audioData);
|
|
185
|
+
const result = await session.recvOutput();
|
|
186
|
+
await session.close();
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Type Generation
|
|
190
|
+
|
|
191
|
+
TypeScript types are auto-generated from the Rust node registry:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
npm run generate-types
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
This creates:
|
|
198
|
+
- `node-schemas.ts` - TypeScript definitions for all nodes
|
|
199
|
+
- `node-schemas.json` - JSON schema for runtime validation
|
|
200
|
+
|
|
201
|
+
## Building from Source
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
# Install dependencies
|
|
205
|
+
npm install
|
|
206
|
+
|
|
207
|
+
# Build native addon
|
|
208
|
+
npm run build
|
|
209
|
+
|
|
210
|
+
# Build with WebRTC support
|
|
211
|
+
npm run build:webrtc
|
|
212
|
+
|
|
213
|
+
# Run tests
|
|
214
|
+
npm test
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Platform Support
|
|
218
|
+
|
|
219
|
+
| Platform | Architecture | Status |
|
|
220
|
+
|----------|-------------|--------|
|
|
221
|
+
| Linux | x64 | ✅ |
|
|
222
|
+
| Linux | arm64 | ✅ |
|
|
223
|
+
| macOS | x64 | ✅ |
|
|
224
|
+
| macOS | arm64 | ✅ |
|
|
225
|
+
| Windows | x64 | 🚧 |
|
|
226
|
+
|
|
227
|
+
## License
|
|
228
|
+
|
|
229
|
+
MIT
|