@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/index.d.ts ADDED
@@ -0,0 +1,717 @@
1
+ /**
2
+ * RemoteMedia Native Node.js Bindings
3
+ *
4
+ * Zero-copy IPC between Node.js, Python, and Rust via iceoryx2.
5
+ */
6
+
7
+ // =============================================================================
8
+ // Data Types
9
+ // =============================================================================
10
+
11
+ export enum DataType {
12
+ Audio = 1,
13
+ Video = 2,
14
+ Text = 3,
15
+ Tensor = 4,
16
+ ControlMessage = 5,
17
+ Numpy = 6,
18
+ }
19
+
20
+ export enum PixelFormat {
21
+ RGB24 = 0,
22
+ RGBA32 = 1,
23
+ YUV420P = 2,
24
+ GRAY8 = 3,
25
+ }
26
+
27
+ export enum VideoCodec {
28
+ Raw = 0,
29
+ H264 = 1,
30
+ VP8 = 2,
31
+ VP9 = 3,
32
+ AV1 = 4,
33
+ }
34
+
35
+ export enum TensorDtype {
36
+ F32 = 0,
37
+ F16 = 1,
38
+ I32 = 2,
39
+ I8 = 3,
40
+ U8 = 4,
41
+ }
42
+
43
+ // =============================================================================
44
+ // Data Structures
45
+ // =============================================================================
46
+
47
+ export interface AudioBuffer {
48
+ sampleRate: number;
49
+ channels: number;
50
+ numSamples: bigint;
51
+ samples: Float32Array;
52
+ }
53
+
54
+ export interface VideoFrame {
55
+ width: number;
56
+ height: number;
57
+ format: PixelFormat;
58
+ codec: VideoCodec;
59
+ frameNum: bigint;
60
+ isKeyframe: boolean;
61
+ pixelData: Uint8Array;
62
+ }
63
+
64
+ export interface TextBuffer {
65
+ text: string;
66
+ language?: string;
67
+ }
68
+
69
+ export interface TensorBuffer {
70
+ shape: number[];
71
+ dtype: TensorDtype;
72
+ data: Uint8Array;
73
+ }
74
+
75
+ export interface ControlMessage {
76
+ type: string;
77
+ payload: Record<string, unknown>;
78
+ cancelRange?: { start: number; end: number };
79
+ }
80
+
81
+ export type RuntimeData =
82
+ | { type: DataType.Audio; data: AudioBuffer; sessionId: string; timestampNs: bigint }
83
+ | { type: DataType.Video; data: VideoFrame; sessionId: string; timestampNs: bigint }
84
+ | { type: DataType.Text; data: TextBuffer; sessionId: string; timestampNs: bigint }
85
+ | { type: DataType.Tensor; data: TensorBuffer; sessionId: string; timestampNs: bigint }
86
+ | { type: DataType.ControlMessage; data: ControlMessage; sessionId: string; timestampNs: bigint };
87
+
88
+ // =============================================================================
89
+ // Type Guards
90
+ // =============================================================================
91
+
92
+ export function isAudio(data: RuntimeData): data is RuntimeData & { type: DataType.Audio };
93
+ export function isVideo(data: RuntimeData): data is RuntimeData & { type: DataType.Video };
94
+ export function isText(data: RuntimeData): data is RuntimeData & { type: DataType.Text };
95
+ export function isTensor(data: RuntimeData): data is RuntimeData & { type: DataType.Tensor };
96
+ export function isControlMessage(data: RuntimeData): data is RuntimeData & { type: DataType.ControlMessage };
97
+
98
+ // =============================================================================
99
+ // Sample Types
100
+ // =============================================================================
101
+
102
+ /**
103
+ * A received sample with zero-copy buffer access.
104
+ */
105
+ export interface ReceivedSample {
106
+ readonly buffer: Buffer;
107
+ readonly size: number;
108
+ readonly isReleased: boolean;
109
+ readonly timestampNs: bigint;
110
+ release(): void;
111
+ toRuntimeData(): RuntimeData;
112
+ }
113
+
114
+ /**
115
+ * A loaned sample buffer for zero-copy publishing.
116
+ */
117
+ export interface LoanedSample {
118
+ readonly buffer: Buffer;
119
+ readonly size: number;
120
+ readonly isConsumed: boolean;
121
+ send(): void;
122
+ release(): void;
123
+ }
124
+
125
+ // =============================================================================
126
+ // Subscriber Interface
127
+ // =============================================================================
128
+
129
+ export interface Subscriber {
130
+ readonly channelName: string;
131
+ readonly isValid: boolean;
132
+ readonly pendingCount: number;
133
+ readonly bufferSize: number;
134
+ receive(): ReceivedSample | null;
135
+ receiveTimeout(timeoutMs: number): Promise<ReceivedSample | null>;
136
+ receiveAsync(): Promise<ReceivedSample>;
137
+ onData(callback: (sample: ReceivedSample) => void): () => void;
138
+ [Symbol.asyncIterator](): AsyncIterableIterator<ReceivedSample>;
139
+ close(): void;
140
+ }
141
+
142
+ export interface SubscriberStats {
143
+ samplesReceived: number;
144
+ bytesReceived: bigint;
145
+ samplesDropped: number;
146
+ publisherCount: number;
147
+ averageLatencyUs: number;
148
+ }
149
+
150
+ export interface SubscriberWithStats extends Subscriber {
151
+ getStats(): SubscriberStats;
152
+ resetStats(): void;
153
+ }
154
+
155
+ // =============================================================================
156
+ // Publisher Interface
157
+ // =============================================================================
158
+
159
+ export interface Publisher {
160
+ readonly channelName: string;
161
+ readonly isValid: boolean;
162
+ readonly loanedCount: number;
163
+ readonly maxLoans: number;
164
+ loan(size: number): LoanedSample;
165
+ tryLoan(size: number): LoanedSample | null;
166
+ publish(data: RuntimeData): void;
167
+ close(): void;
168
+ }
169
+
170
+ export interface PublisherStats {
171
+ samplesSent: number;
172
+ bytesSent: bigint;
173
+ samplesDropped: number;
174
+ subscriberCount: number;
175
+ }
176
+
177
+ export interface PublisherWithStats extends Publisher {
178
+ getStats(): PublisherStats;
179
+ resetStats(): void;
180
+ }
181
+
182
+ // =============================================================================
183
+ // Channel Interface
184
+ // =============================================================================
185
+
186
+ export interface ChannelConfig {
187
+ capacity?: number;
188
+ maxPayloadSize?: number;
189
+ backpressure?: boolean;
190
+ historySize?: number;
191
+ }
192
+
193
+ export interface Channel {
194
+ readonly name: string;
195
+ readonly config: Readonly<ChannelConfig>;
196
+ readonly isOpen: boolean;
197
+ createPublisher(): Publisher;
198
+ createSubscriber(bufferSize?: number): Subscriber;
199
+ close(): void;
200
+ }
201
+
202
+ // =============================================================================
203
+ // Session Interface
204
+ // =============================================================================
205
+
206
+ export interface SessionConfig {
207
+ id: string;
208
+ defaultChannelConfig?: ChannelConfig;
209
+ }
210
+
211
+ export interface Session {
212
+ readonly id: string;
213
+ readonly isActive: boolean;
214
+ channel(name: string, config?: ChannelConfig): Channel;
215
+ listChannels(): string[];
216
+ close(): void;
217
+ }
218
+
219
+ // =============================================================================
220
+ // Factory Functions
221
+ // =============================================================================
222
+
223
+ export function createSession(config: SessionConfig): Session;
224
+ export function getSession(sessionId: string): Session | null;
225
+ export function listSessions(): string[];
226
+
227
+ // =============================================================================
228
+ // IPC Node Management
229
+ // =============================================================================
230
+
231
+ export interface IpcNode {
232
+ readonly name: string;
233
+ readonly isValid: boolean;
234
+ close(): void;
235
+ }
236
+
237
+ export function createIpcNode(name?: string): IpcNode;
238
+
239
+ // =============================================================================
240
+ // WebRTC Types (requires napi-webrtc feature)
241
+ // =============================================================================
242
+
243
+ /** TURN server configuration */
244
+ export interface TurnServer {
245
+ url: string;
246
+ username: string;
247
+ credential: string;
248
+ }
249
+
250
+ /** WebRTC server configuration */
251
+ export interface WebRtcServerConfig {
252
+ /** Port for embedded signaling server (mutually exclusive with signalingUrl) */
253
+ port?: number;
254
+ /** URL for external signaling server (mutually exclusive with port) */
255
+ signalingUrl?: string;
256
+ /** Pipeline manifest as JSON string */
257
+ manifest: string;
258
+ /** STUN server URLs (at least one required) */
259
+ stunServers: string[];
260
+ /** TURN server configurations (optional) */
261
+ turnServers?: TurnServer[];
262
+ /** Maximum concurrent peers (1-10, default 10) */
263
+ maxPeers?: number;
264
+ /** Audio codec (only "opus" supported) */
265
+ audioCodec?: 'opus';
266
+ /** Video codec */
267
+ videoCodec?: 'vp8' | 'vp9' | 'h264';
268
+ }
269
+
270
+ /** Peer media capabilities */
271
+ export interface PeerCapabilities {
272
+ audio: boolean;
273
+ video: boolean;
274
+ data: boolean;
275
+ }
276
+
277
+ /** Connected peer information */
278
+ export interface PeerInfo {
279
+ peerId: string;
280
+ capabilities: PeerCapabilities;
281
+ metadata: Record<string, string>;
282
+ state: 'connecting' | 'connected' | 'disconnecting' | 'disconnected';
283
+ connectedAt: number;
284
+ }
285
+
286
+ /** Session (room) information */
287
+ export interface SessionInfo {
288
+ sessionId: string;
289
+ peerIds: string[];
290
+ createdAt: number;
291
+ metadata: Record<string, string>;
292
+ }
293
+
294
+ // WebRTC Event Data Types
295
+
296
+ export interface PeerConnectedData {
297
+ peerId: string;
298
+ capabilities: PeerCapabilities;
299
+ metadata: Record<string, string>;
300
+ }
301
+
302
+ export interface PeerDisconnectedData {
303
+ peerId: string;
304
+ reason?: string;
305
+ }
306
+
307
+ export interface PipelineOutputData {
308
+ peerId: string;
309
+ data: Buffer;
310
+ timestamp: number;
311
+ }
312
+
313
+ export interface DataReceivedData {
314
+ peerId: string;
315
+ data: Buffer;
316
+ timestamp: number;
317
+ }
318
+
319
+ export interface ErrorData {
320
+ code: string;
321
+ message: string;
322
+ peerId?: string;
323
+ }
324
+
325
+ export interface SessionEventData {
326
+ sessionId: string;
327
+ eventType: 'peer_joined' | 'peer_left';
328
+ peerId: string;
329
+ }
330
+
331
+ /** WebRTC Session for room/group management */
332
+ export interface WebRtcSession {
333
+ /** Session identifier */
334
+ readonly sessionId: string;
335
+ /** Peer IDs in this session */
336
+ readonly peers: Promise<string[]>;
337
+ /** Session creation timestamp */
338
+ readonly createdAt: Promise<number>;
339
+ /** Session metadata */
340
+ readonly metadata: Promise<Record<string, string>>;
341
+
342
+ /**
343
+ * Register event listener for session events
344
+ * @param event - Event name ('peer_joined', 'peer_left')
345
+ * @param callback - Event handler
346
+ */
347
+ on(event: 'peer_joined', callback: (peerId: string) => void): void;
348
+ on(event: 'peer_left', callback: (peerId: string) => void): void;
349
+
350
+ /**
351
+ * Broadcast data to all peers in the session
352
+ * @param data - Data to broadcast
353
+ */
354
+ broadcast(data: Buffer): Promise<void>;
355
+
356
+ /**
357
+ * Send data to a specific peer in the session
358
+ * @param peerId - Target peer ID
359
+ * @param data - Data to send
360
+ */
361
+ sendToPeer(peerId: string, data: Buffer): Promise<void>;
362
+
363
+ /**
364
+ * Add a peer to this session
365
+ * @param peerId - Peer ID to add
366
+ */
367
+ addPeer(peerId: string): Promise<void>;
368
+
369
+ /**
370
+ * Remove a peer from this session
371
+ * @param peerId - Peer ID to remove
372
+ */
373
+ removePeer(peerId: string): Promise<void>;
374
+
375
+ /**
376
+ * Get session info
377
+ */
378
+ getInfo(): Promise<SessionInfo>;
379
+ }
380
+
381
+ /** WebRTC server for real-time media streaming */
382
+ export interface WebRtcServer {
383
+ /** Server unique identifier */
384
+ readonly id: string;
385
+ /** Current server state */
386
+ readonly state: Promise<'created' | 'starting' | 'running' | 'stopping' | 'stopped'>;
387
+
388
+ /**
389
+ * Register event listener
390
+ * @param event - Event name
391
+ * @param callback - Event handler
392
+ */
393
+ on(event: 'peer_connected', callback: (data: PeerConnectedData) => void): void;
394
+ on(event: 'peer_disconnected', callback: (data: PeerDisconnectedData) => void): void;
395
+ on(event: 'pipeline_output', callback: (data: PipelineOutputData) => void): void;
396
+ on(event: 'data', callback: (data: DataReceivedData) => void): void;
397
+ on(event: 'error', callback: (data: ErrorData) => void): void;
398
+ on(event: 'session', callback: (data: SessionEventData) => void): void;
399
+
400
+ /** Start the server */
401
+ start(): Promise<void>;
402
+
403
+ /** Stop the server gracefully */
404
+ shutdown(): Promise<void>;
405
+
406
+ /** Get connected peers */
407
+ getPeers(): Promise<PeerInfo[]>;
408
+
409
+ /** Get active sessions */
410
+ getSessions(): Promise<SessionInfo[]>;
411
+
412
+ /**
413
+ * Send data to a specific peer
414
+ * @param peerId - Target peer ID
415
+ * @param data - Data to send
416
+ */
417
+ sendToPeer(peerId: string, data: Buffer): Promise<void>;
418
+
419
+ /**
420
+ * Broadcast data to all connected peers
421
+ * @param data - Data to broadcast
422
+ */
423
+ broadcast(data: Buffer): Promise<void>;
424
+
425
+ /**
426
+ * Disconnect a peer
427
+ * @param peerId - Peer to disconnect
428
+ * @param reason - Optional disconnect reason
429
+ */
430
+ disconnectPeer(peerId: string, reason?: string): Promise<void>;
431
+
432
+ /**
433
+ * Create a new session (room)
434
+ * @param sessionId - Unique session identifier
435
+ * @param metadata - Optional session metadata
436
+ * @returns WebRtcSession instance
437
+ */
438
+ createSession(sessionId: string, metadata?: Record<string, string>): Promise<WebRtcSession>;
439
+
440
+ /**
441
+ * Create a new session and return info only
442
+ * @param sessionId - Unique session identifier
443
+ * @param metadata - Optional session metadata
444
+ * @returns SessionInfo
445
+ */
446
+ createSessionInfo(sessionId: string, metadata?: Record<string, string>): Promise<SessionInfo>;
447
+
448
+ /**
449
+ * Get an existing session
450
+ * @param sessionId - Session identifier
451
+ */
452
+ getSession(sessionId: string): Promise<SessionInfo | null>;
453
+
454
+ /**
455
+ * Delete a session
456
+ * @param sessionId - Session to delete
457
+ */
458
+ deleteSession(sessionId: string): Promise<void>;
459
+ }
460
+
461
+ /** WebRTC server factory */
462
+ export interface WebRtcServerFactory {
463
+ /**
464
+ * Create a server with embedded signaling
465
+ * @param config - Server configuration with port set
466
+ */
467
+ create(config: WebRtcServerConfig): Promise<WebRtcServer>;
468
+
469
+ /**
470
+ * Connect to an external signaling server
471
+ * @param config - Server configuration with signalingUrl set
472
+ */
473
+ connect(config: WebRtcServerConfig): Promise<WebRtcServer>;
474
+ }
475
+
476
+ /**
477
+ * WebRTC server module (available when built with napi-webrtc feature)
478
+ */
479
+ export const WebRtcServer: WebRtcServerFactory | undefined;
480
+
481
+ // =============================================================================
482
+ // Proto Utils (Browser/Node.js compatible)
483
+ // =============================================================================
484
+
485
+ export * from './proto-utils';
486
+
487
+ import * as protoUtilsModule from './proto-utils';
488
+ export const protoUtils: typeof protoUtilsModule;
489
+
490
+ // =============================================================================
491
+ // Node Schema Registry (Pipeline Introspection)
492
+ // =============================================================================
493
+
494
+ /** RuntimeData type variants that nodes can accept/produce */
495
+ export enum NapiRuntimeDataType {
496
+ Audio = 0,
497
+ Video = 1,
498
+ Json = 2,
499
+ Text = 3,
500
+ Binary = 4,
501
+ Tensor = 5,
502
+ Numpy = 6,
503
+ ControlMessage = 7,
504
+ }
505
+
506
+ /** Processing latency classification */
507
+ export enum NapiLatencyClass {
508
+ /** Sub-millisecond (< 1ms) - audio resampling */
509
+ Realtime = 0,
510
+ /** Fast (1-10ms) - VAD, format conversion */
511
+ Fast = 1,
512
+ /** Medium (10-100ms) - text processing */
513
+ Medium = 2,
514
+ /** Slow (100ms-1s) - TTS synthesis */
515
+ Slow = 3,
516
+ /** Very slow (> 1s) - ML inference, transcription */
517
+ Batch = 4,
518
+ }
519
+
520
+ /** Node execution capabilities for scheduling hints */
521
+ export interface NapiNodeCapabilities {
522
+ /** Can process inputs in parallel */
523
+ parallelizable: boolean;
524
+ /** Benefits from batched inputs */
525
+ batchAware: boolean;
526
+ /** Supports control messages */
527
+ supportsControl: boolean;
528
+ /** Latency class (0=realtime, 1=fast, 2=medium, 3=slow, 4=batch) */
529
+ latencyClass: number;
530
+ }
531
+
532
+ /** Parameter type enumeration */
533
+ export enum NapiParameterType {
534
+ String = 0,
535
+ Number = 1,
536
+ Integer = 2,
537
+ Boolean = 3,
538
+ Array = 4,
539
+ Object = 5,
540
+ }
541
+
542
+ /** A single configuration parameter for a node */
543
+ export interface NapiNodeParameter {
544
+ /** Parameter name */
545
+ name: string;
546
+ /** Parameter type as string (string, number, integer, boolean, array, object) */
547
+ paramType: string;
548
+ /** Human-readable description */
549
+ description?: string;
550
+ /** Default value as JSON string */
551
+ defaultValue?: string;
552
+ /** Whether the parameter is required */
553
+ required: boolean;
554
+ /** Allowed values as JSON array string (for enum constraints) */
555
+ enumValues?: string;
556
+ /** Minimum value (for numbers) */
557
+ minimum?: number;
558
+ /** Maximum value (for numbers) */
559
+ maximum?: number;
560
+ }
561
+
562
+ /** Complete schema for a pipeline node */
563
+ export interface NapiNodeSchema {
564
+ /** Node type identifier (e.g., "KokoroTTSNode", "AudioResample") */
565
+ nodeType: string;
566
+ /** Human-readable description */
567
+ description?: string;
568
+ /** Category for grouping (e.g., "audio", "text", "ml", "video") */
569
+ category?: string;
570
+ /** Accepted input RuntimeData types as strings */
571
+ accepts: string[];
572
+ /** Produced output RuntimeData types as strings */
573
+ produces: string[];
574
+ /** Configuration parameters (extracted from config_schema) */
575
+ parameters: NapiNodeParameter[];
576
+ /** Configuration JSON Schema (as JSON string) */
577
+ configSchema?: string;
578
+ /** Default configuration values (as JSON string) */
579
+ configDefaults?: string;
580
+ /** Whether this is a Python node */
581
+ isPython: boolean;
582
+ /** Whether this node supports streaming */
583
+ streaming: boolean;
584
+ /** Whether this node produces multiple outputs per input */
585
+ multiOutput: boolean;
586
+ /** Execution capabilities */
587
+ capabilities?: NapiNodeCapabilities;
588
+ }
589
+
590
+ /**
591
+ * Get all registered node schemas
592
+ *
593
+ * @example
594
+ * ```javascript
595
+ * const schemas = getNodeSchemas();
596
+ * schemas.forEach(schema => {
597
+ * console.log(`${schema.nodeType}: ${schema.description}`);
598
+ * });
599
+ * ```
600
+ */
601
+ export function getNodeSchemas(): NapiNodeSchema[];
602
+
603
+ /**
604
+ * Get schema for a specific node type
605
+ *
606
+ * @param nodeType - The node type identifier (e.g., "KokoroTTSNode")
607
+ * @returns The node schema, or null if not found
608
+ *
609
+ * @example
610
+ * ```javascript
611
+ * const schema = getNodeSchema('KokoroTTSNode');
612
+ * if (schema) {
613
+ * console.log('Accepts:', schema.accepts);
614
+ * console.log('Produces:', schema.produces);
615
+ * }
616
+ * ```
617
+ */
618
+ export function getNodeSchema(nodeType: string): NapiNodeSchema | null;
619
+
620
+ /**
621
+ * Get configuration parameters for a specific node type
622
+ *
623
+ * @param nodeType - The node type identifier (e.g., "KokoroTTSNode")
624
+ * @returns Array of parameter definitions, or empty array if node not found
625
+ *
626
+ * @example
627
+ * ```javascript
628
+ * const params = getNodeParameters('KokoroTTSNode');
629
+ * params.forEach(p => {
630
+ * console.log(`${p.name} (${p.paramType}): ${p.description}`);
631
+ * if (p.enumValues) {
632
+ * console.log(` Allowed: ${JSON.parse(p.enumValues).join(', ')}`);
633
+ * }
634
+ * if (p.defaultValue) {
635
+ * console.log(` Default: ${p.defaultValue}`);
636
+ * }
637
+ * });
638
+ * ```
639
+ */
640
+ export function getNodeParameters(nodeType: string): NapiNodeParameter[];
641
+
642
+ /**
643
+ * Get all node schemas as JSON string
644
+ *
645
+ * @returns JSON array of all node schemas
646
+ */
647
+ export function getNodeSchemasJson(): string;
648
+
649
+ /**
650
+ * Get schema for a specific node type as JSON string
651
+ *
652
+ * @param nodeType - The node type identifier
653
+ * @returns JSON string of the schema, or null if not found
654
+ */
655
+ export function getNodeSchemaJson(nodeType: string): string | null;
656
+
657
+ /**
658
+ * Get all registered node type names
659
+ *
660
+ * @returns Array of node type identifiers
661
+ *
662
+ * @example
663
+ * ```javascript
664
+ * const nodeTypes = getNodeTypes();
665
+ * console.log('Available nodes:', nodeTypes.join(', '));
666
+ * ```
667
+ */
668
+ export function getNodeTypes(): string[];
669
+
670
+ /**
671
+ * Get node types filtered by category
672
+ *
673
+ * @param category - Category to filter by (e.g., "audio", "ml", "video")
674
+ * @returns Array of node type identifiers in that category
675
+ *
676
+ * @example
677
+ * ```javascript
678
+ * const audioNodes = getNodeTypesByCategory('audio');
679
+ * ```
680
+ */
681
+ export function getNodeTypesByCategory(category: string): string[];
682
+
683
+ /**
684
+ * Check if a node type is registered
685
+ *
686
+ * @param nodeType - The node type identifier to check
687
+ */
688
+ export function hasNodeType(nodeType: string): boolean;
689
+
690
+ /**
691
+ * Get all unique categories from registered nodes
692
+ *
693
+ * @returns Array of category names
694
+ *
695
+ * @example
696
+ * ```javascript
697
+ * const categories = getNodeCategories();
698
+ * // ['audio', 'ml', 'text', 'utility', 'video']
699
+ * ```
700
+ */
701
+ export function getNodeCategories(): string[];
702
+
703
+ /**
704
+ * Validate a pipeline manifest against node schemas
705
+ *
706
+ * @param manifestJson - Pipeline manifest as JSON string
707
+ * @returns Array of validation errors (empty if valid)
708
+ *
709
+ * @example
710
+ * ```javascript
711
+ * const errors = validateManifest(JSON.stringify(manifest));
712
+ * if (errors.length > 0) {
713
+ * console.error('Invalid manifest:', errors);
714
+ * }
715
+ * ```
716
+ */
717
+ export function validateManifest(manifestJson: string): string[];