@spatialwalk/avatarkit-rtc 1.0.0-beta.7 → 1.0.0-beta.8

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/dist/index9.js CHANGED
@@ -1,75 +1,178 @@
1
- var __defProp = Object.defineProperty;
2
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
- import { logger } from "./index7.js";
5
- class BaseProvider {
6
- constructor() {
7
- /** @internal */
8
- __publicField(this, "connectionState", "disconnected");
9
- /** @internal */
10
- __publicField(this, "eventHandlers", /* @__PURE__ */ new Map());
11
- }
12
- /**
13
- * Add event listener.
14
- * @param event - Event name
15
- * @param handler - Event handler
16
- */
17
- on(event, handler) {
18
- if (!this.eventHandlers.has(event)) {
19
- this.eventHandlers.set(event, /* @__PURE__ */ new Set());
20
- }
21
- this.eventHandlers.get(event).add(handler);
1
+ import { varint64read, varint32read } from "./index16.js";
2
+ import { protoInt64 } from "./index17.js";
3
+ import { getTextEncoding } from "./index18.js";
4
+ var WireType;
5
+ (function(WireType2) {
6
+ WireType2[WireType2["Varint"] = 0] = "Varint";
7
+ WireType2[WireType2["Bit64"] = 1] = "Bit64";
8
+ WireType2[WireType2["LengthDelimited"] = 2] = "LengthDelimited";
9
+ WireType2[WireType2["StartGroup"] = 3] = "StartGroup";
10
+ WireType2[WireType2["EndGroup"] = 4] = "EndGroup";
11
+ WireType2[WireType2["Bit32"] = 5] = "Bit32";
12
+ })(WireType || (WireType = {}));
13
+ class BinaryReader {
14
+ constructor(buf, decodeUtf8 = getTextEncoding().decodeUtf8) {
15
+ this.decodeUtf8 = decodeUtf8;
16
+ this.varint64 = varint64read;
17
+ this.uint32 = varint32read;
18
+ this.buf = buf;
19
+ this.len = buf.length;
20
+ this.pos = 0;
21
+ this.view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
22
22
  }
23
23
  /**
24
- * Remove event listener.
25
- * @param event - Event name
26
- * @param handler - Event handler
24
+ * Reads a tag - field number and wire type.
27
25
  */
28
- off(event, handler) {
29
- const handlers = this.eventHandlers.get(event);
30
- if (handlers) {
31
- handlers.delete(handler);
32
- }
26
+ tag() {
27
+ let tag = this.uint32(), fieldNo = tag >>> 3, wireType = tag & 7;
28
+ if (fieldNo <= 0 || wireType < 0 || wireType > 5)
29
+ throw new Error("illegal tag: field no " + fieldNo + " wire type " + wireType);
30
+ return [fieldNo, wireType];
33
31
  }
34
32
  /**
35
- * Emit event to all listeners.
36
- * @param event - Event name
37
- * @param args - Event arguments
38
- * @internal
33
+ * Skip one element and return the skipped data.
34
+ *
35
+ * When skipping StartGroup, provide the tags field number to check for
36
+ * matching field number in the EndGroup tag.
39
37
  */
40
- emit(event, ...args) {
41
- const handlers = this.eventHandlers.get(event);
42
- if (handlers) {
43
- handlers.forEach((handler) => {
44
- try {
45
- handler(...args);
46
- } catch (error) {
47
- logger.error(this.name, `Error in event handler for ${event}:`, error);
38
+ skip(wireType, fieldNo) {
39
+ let start = this.pos;
40
+ switch (wireType) {
41
+ case WireType.Varint:
42
+ while (this.buf[this.pos++] & 128) {
43
+ }
44
+ break;
45
+ // @ts-ignore TS7029: Fallthrough case in switch -- ignore instead of expect-error for compiler settings without noFallthroughCasesInSwitch: true
46
+ case WireType.Bit64:
47
+ this.pos += 4;
48
+ case WireType.Bit32:
49
+ this.pos += 4;
50
+ break;
51
+ case WireType.LengthDelimited:
52
+ let len = this.uint32();
53
+ this.pos += len;
54
+ break;
55
+ case WireType.StartGroup:
56
+ for (; ; ) {
57
+ const [fn, wt] = this.tag();
58
+ if (wt === WireType.EndGroup) {
59
+ if (fieldNo !== void 0 && fn !== fieldNo) {
60
+ throw new Error("invalid end group tag");
61
+ }
62
+ break;
63
+ }
64
+ this.skip(wt, fn);
48
65
  }
49
- });
66
+ break;
67
+ default:
68
+ throw new Error("cant skip wire type " + wireType);
50
69
  }
70
+ this.assertBounds();
71
+ return this.buf.subarray(start, this.pos);
51
72
  }
52
73
  /**
53
- * Update connection state and emit event.
54
- * @param state - New connection state
55
- * @internal
56
- */
57
- setConnectionState(state) {
58
- if (this.connectionState !== state) {
59
- const prevState = this.connectionState;
60
- this.connectionState = state;
61
- if (state === "disconnected" || state === "failed") {
62
- logger.error(this.name, `Connection state: ${prevState} -> ${state}`);
63
- } else if (state === "reconnecting") {
64
- logger.warn(this.name, `Connection state: ${prevState} -> ${state}`);
65
- } else {
66
- logger.info(this.name, `Connection state: ${prevState} -> ${state}`);
67
- }
68
- this.emit("connection-state-changed", state);
69
- }
74
+ * Throws error if position in byte array is out of range.
75
+ */
76
+ assertBounds() {
77
+ if (this.pos > this.len)
78
+ throw new RangeError("premature EOF");
79
+ }
80
+ /**
81
+ * Read a `int32` field, a signed 32 bit varint.
82
+ */
83
+ int32() {
84
+ return this.uint32() | 0;
85
+ }
86
+ /**
87
+ * Read a `sint32` field, a signed, zigzag-encoded 32-bit varint.
88
+ */
89
+ sint32() {
90
+ let zze = this.uint32();
91
+ return zze >>> 1 ^ -(zze & 1);
92
+ }
93
+ /**
94
+ * Read a `int64` field, a signed 64-bit varint.
95
+ */
96
+ int64() {
97
+ return protoInt64.dec(...this.varint64());
98
+ }
99
+ /**
100
+ * Read a `uint64` field, an unsigned 64-bit varint.
101
+ */
102
+ uint64() {
103
+ return protoInt64.uDec(...this.varint64());
104
+ }
105
+ /**
106
+ * Read a `sint64` field, a signed, zig-zag-encoded 64-bit varint.
107
+ */
108
+ sint64() {
109
+ let [lo, hi] = this.varint64();
110
+ let s = -(lo & 1);
111
+ lo = (lo >>> 1 | (hi & 1) << 31) ^ s;
112
+ hi = hi >>> 1 ^ s;
113
+ return protoInt64.dec(lo, hi);
114
+ }
115
+ /**
116
+ * Read a `bool` field, a variant.
117
+ */
118
+ bool() {
119
+ let [lo, hi] = this.varint64();
120
+ return lo !== 0 || hi !== 0;
121
+ }
122
+ /**
123
+ * Read a `fixed32` field, an unsigned, fixed-length 32-bit integer.
124
+ */
125
+ fixed32() {
126
+ return this.view.getUint32((this.pos += 4) - 4, true);
127
+ }
128
+ /**
129
+ * Read a `sfixed32` field, a signed, fixed-length 32-bit integer.
130
+ */
131
+ sfixed32() {
132
+ return this.view.getInt32((this.pos += 4) - 4, true);
133
+ }
134
+ /**
135
+ * Read a `fixed64` field, an unsigned, fixed-length 64 bit integer.
136
+ */
137
+ fixed64() {
138
+ return protoInt64.uDec(this.sfixed32(), this.sfixed32());
139
+ }
140
+ /**
141
+ * Read a `fixed64` field, a signed, fixed-length 64-bit integer.
142
+ */
143
+ sfixed64() {
144
+ return protoInt64.dec(this.sfixed32(), this.sfixed32());
145
+ }
146
+ /**
147
+ * Read a `float` field, 32-bit floating point number.
148
+ */
149
+ float() {
150
+ return this.view.getFloat32((this.pos += 4) - 4, true);
151
+ }
152
+ /**
153
+ * Read a `double` field, a 64-bit floating point number.
154
+ */
155
+ double() {
156
+ return this.view.getFloat64((this.pos += 8) - 8, true);
157
+ }
158
+ /**
159
+ * Read a `bytes` field, length-delimited arbitrary data.
160
+ */
161
+ bytes() {
162
+ let len = this.uint32(), start = this.pos;
163
+ this.pos += len;
164
+ this.assertBounds();
165
+ return this.buf.subarray(start, start + len);
166
+ }
167
+ /**
168
+ * Read a `string` field, length-delimited data converted to UTF-8 text.
169
+ */
170
+ string() {
171
+ return this.decodeUtf8(this.bytes());
70
172
  }
71
173
  }
72
174
  export {
73
- BaseProvider
175
+ BinaryReader,
176
+ WireType
74
177
  };
75
178
  //# sourceMappingURL=index9.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index9.js","sources":["../src/providers/base/BaseProvider.ts"],"sourcesContent":["/**\n * Base Provider - Common implementation for RTC providers.\n *\n * This class provides common functionality that can be shared\n * across different provider implementations.\n *\n * @internal\n * @packageDocumentation\n */\n\nimport type { RTCProviderEvents, AnimationTrackCallbacks, AudioTrackCallbacks } from '../../core/types';\nimport { logger } from '../../utils';\n\n/**\n * Base class for RTC providers.\n * Provides common event handling and state management.\n */\nexport abstract class BaseProvider {\n /** Provider name identifier */\n abstract readonly name: string;\n\n /** @internal */\n protected connectionState: string = 'disconnected';\n /** @internal */\n protected eventHandlers: Map<string, Set<Function>> = new Map();\n\n /**\n * Connect to RTC server.\n * @param config - Connection configuration\n */\n abstract connect(config: import('../../types').RTCConnectionConfig): Promise<void>;\n\n /**\n * Disconnect from RTC server.\n */\n abstract disconnect(): Promise<void>;\n\n /**\n * Get current connection state.\n */\n abstract getConnectionState(): string;\n\n /**\n * Subscribe to animation track.\n * @param callbacks - Animation track callbacks\n * @internal\n */\n abstract subscribeAnimationTrack(callbacks: AnimationTrackCallbacks): Promise<void>;\n\n /**\n * Unsubscribe from animation track.\n * @internal\n */\n abstract unsubscribeAnimationTrack(): Promise<void>;\n\n /**\n * Subscribe to audio track.\n * @param callbacks - Audio track callbacks\n * @internal\n */\n abstract subscribeAudioTrack(callbacks: AudioTrackCallbacks): Promise<void>;\n\n /**\n * Unsubscribe from audio track.\n * @internal\n */\n abstract unsubscribeAudioTrack(): Promise<void>;\n\n /**\n * Publish local audio track.\n * @param track - MediaStreamTrack to publish\n */\n abstract publishAudioTrack(track: MediaStreamTrack): Promise<void>;\n\n /**\n * Unpublish audio track.\n */\n abstract unpublishAudioTrack(): Promise<void>;\n\n /**\n * Get the native RTC client object.\n * @returns The native client, or null if not connected\n */\n abstract getNativeClient(): unknown;\n\n /**\n * Add event listener.\n * @param event - Event name\n * @param handler - Event handler\n */\n on(event: string, handler: Function): void {\n if (!this.eventHandlers.has(event)) {\n this.eventHandlers.set(event, new Set());\n }\n this.eventHandlers.get(event)!.add(handler);\n }\n\n /**\n * Remove event listener.\n * @param event - Event name\n * @param handler - Event handler\n */\n off(event: string, handler: Function): void {\n const handlers = this.eventHandlers.get(event);\n if (handlers) {\n handlers.delete(handler);\n }\n }\n\n /**\n * Emit event to all listeners.\n * @param event - Event name\n * @param args - Event arguments\n * @internal\n */\n protected emit<K extends keyof RTCProviderEvents>(\n event: K,\n ...args: Parameters<RTCProviderEvents[K]>\n ): void {\n const handlers = this.eventHandlers.get(event);\n if (handlers) {\n handlers.forEach((handler) => {\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (handler as any)(...args);\n } catch (error) {\n logger.error(this.name, `Error in event handler for ${event}:`, error);\n }\n });\n }\n }\n\n /**\n * Update connection state and emit event.\n * @param state - New connection state\n * @internal\n */\n protected setConnectionState(state: string): void {\n if (this.connectionState !== state) {\n const prevState = this.connectionState;\n this.connectionState = state;\n \n // Log connection state changes\n if (state === 'disconnected' || state === 'failed') {\n logger.error(this.name, `Connection state: ${prevState} -> ${state}`);\n } else if (state === 'reconnecting') {\n logger.warn(this.name, `Connection state: ${prevState} -> ${state}`);\n } else {\n logger.info(this.name, `Connection state: ${prevState} -> ${state}`);\n }\n \n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.emit('connection-state-changed', state as any);\n }\n }\n}\n"],"names":[],"mappings":";;;;AAiBO,MAAe,aAAa;AAAA,EAA5B;AAKK;AAAA,2CAA0B;AAE1B;AAAA,6DAAgD,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkE1D,GAAG,OAAe,SAAyB;AACzC,QAAI,CAAC,KAAK,cAAc,IAAI,KAAK,GAAG;AAClC,WAAK,cAAc,IAAI,OAAO,oBAAI,KAAK;AAAA,IACzC;AACA,SAAK,cAAc,IAAI,KAAK,EAAG,IAAI,OAAO;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,OAAe,SAAyB;AAC1C,UAAM,WAAW,KAAK,cAAc,IAAI,KAAK;AAC7C,QAAI,UAAU;AACZ,eAAS,OAAO,OAAO;AAAA,IACzB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQU,KACR,UACG,MACG;AACN,UAAM,WAAW,KAAK,cAAc,IAAI,KAAK;AAC7C,QAAI,UAAU;AACZ,eAAS,QAAQ,CAAC,YAAY;AAC5B,YAAI;AAED,kBAAgB,GAAG,IAAI;AAAA,QAC1B,SAAS,OAAO;AACd,iBAAO,MAAM,KAAK,MAAM,8BAA8B,KAAK,KAAK,KAAK;AAAA,QACvE;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOU,mBAAmB,OAAqB;AAChD,QAAI,KAAK,oBAAoB,OAAO;AAClC,YAAM,YAAY,KAAK;AACvB,WAAK,kBAAkB;AAGvB,UAAI,UAAU,kBAAkB,UAAU,UAAU;AAClD,eAAO,MAAM,KAAK,MAAM,qBAAqB,SAAS,OAAO,KAAK,EAAE;AAAA,MACtE,WAAW,UAAU,gBAAgB;AACnC,eAAO,KAAK,KAAK,MAAM,qBAAqB,SAAS,OAAO,KAAK,EAAE;AAAA,MACrE,OAAO;AACL,eAAO,KAAK,KAAK,MAAM,qBAAqB,SAAS,OAAO,KAAK,EAAE;AAAA,MACrE;AAGA,WAAK,KAAK,4BAA4B,KAAY;AAAA,IACpD;AAAA,EACF;AACF;"}
1
+ {"version":3,"file":"index9.js","sources":["../node_modules/.pnpm/@bufbuild+protobuf@2.11.0/node_modules/@bufbuild/protobuf/dist/esm/wire/binary-encoding.js"],"sourcesContent":["// Copyright 2021-2026 Buf Technologies, Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\nimport { varint32read, varint32write, varint64read, varint64write, } from \"./varint.js\";\nimport { protoInt64 } from \"../proto-int64.js\";\nimport { getTextEncoding } from \"./text-encoding.js\";\n/**\n * Protobuf binary format wire types.\n *\n * A wire type provides just enough information to find the length of the\n * following value.\n *\n * See https://developers.google.com/protocol-buffers/docs/encoding#structure\n */\nexport var WireType;\n(function (WireType) {\n /**\n * Used for int32, int64, uint32, uint64, sint32, sint64, bool, enum\n */\n WireType[WireType[\"Varint\"] = 0] = \"Varint\";\n /**\n * Used for fixed64, sfixed64, double.\n * Always 8 bytes with little-endian byte order.\n */\n WireType[WireType[\"Bit64\"] = 1] = \"Bit64\";\n /**\n * Used for string, bytes, embedded messages, packed repeated fields\n *\n * Only repeated numeric types (types which use the varint, 32-bit,\n * or 64-bit wire types) can be packed. In proto3, such fields are\n * packed by default.\n */\n WireType[WireType[\"LengthDelimited\"] = 2] = \"LengthDelimited\";\n /**\n * Start of a tag-delimited aggregate, such as a proto2 group, or a message\n * in editions with message_encoding = DELIMITED.\n */\n WireType[WireType[\"StartGroup\"] = 3] = \"StartGroup\";\n /**\n * End of a tag-delimited aggregate.\n */\n WireType[WireType[\"EndGroup\"] = 4] = \"EndGroup\";\n /**\n * Used for fixed32, sfixed32, float.\n * Always 4 bytes with little-endian byte order.\n */\n WireType[WireType[\"Bit32\"] = 5] = \"Bit32\";\n})(WireType || (WireType = {}));\n/**\n * Maximum value for a 32-bit floating point value (Protobuf FLOAT).\n */\nexport const FLOAT32_MAX = 3.4028234663852886e38;\n/**\n * Minimum value for a 32-bit floating point value (Protobuf FLOAT).\n */\nexport const FLOAT32_MIN = -3.4028234663852886e38;\n/**\n * Maximum value for an unsigned 32-bit integer (Protobuf UINT32, FIXED32).\n */\nexport const UINT32_MAX = 0xffffffff;\n/**\n * Maximum value for a signed 32-bit integer (Protobuf INT32, SFIXED32, SINT32).\n */\nexport const INT32_MAX = 0x7fffffff;\n/**\n * Minimum value for a signed 32-bit integer (Protobuf INT32, SFIXED32, SINT32).\n */\nexport const INT32_MIN = -0x80000000;\nexport class BinaryWriter {\n constructor(encodeUtf8 = getTextEncoding().encodeUtf8) {\n this.encodeUtf8 = encodeUtf8;\n /**\n * Previous fork states.\n */\n this.stack = [];\n this.chunks = [];\n this.buf = [];\n }\n /**\n * Return all bytes written and reset this writer.\n */\n finish() {\n if (this.buf.length) {\n this.chunks.push(new Uint8Array(this.buf)); // flush the buffer\n this.buf = [];\n }\n let len = 0;\n for (let i = 0; i < this.chunks.length; i++)\n len += this.chunks[i].length;\n let bytes = new Uint8Array(len);\n let offset = 0;\n for (let i = 0; i < this.chunks.length; i++) {\n bytes.set(this.chunks[i], offset);\n offset += this.chunks[i].length;\n }\n this.chunks = [];\n return bytes;\n }\n /**\n * Start a new fork for length-delimited data like a message\n * or a packed repeated field.\n *\n * Must be joined later with `join()`.\n */\n fork() {\n this.stack.push({ chunks: this.chunks, buf: this.buf });\n this.chunks = [];\n this.buf = [];\n return this;\n }\n /**\n * Join the last fork. Write its length and bytes, then\n * return to the previous state.\n */\n join() {\n // get chunk of fork\n let chunk = this.finish();\n // restore previous state\n let prev = this.stack.pop();\n if (!prev)\n throw new Error(\"invalid state, fork stack empty\");\n this.chunks = prev.chunks;\n this.buf = prev.buf;\n // write length of chunk as varint\n this.uint32(chunk.byteLength);\n return this.raw(chunk);\n }\n /**\n * Writes a tag (field number and wire type).\n *\n * Equivalent to `uint32( (fieldNo << 3 | type) >>> 0 )`.\n *\n * Generated code should compute the tag ahead of time and call `uint32()`.\n */\n tag(fieldNo, type) {\n return this.uint32(((fieldNo << 3) | type) >>> 0);\n }\n /**\n * Write a chunk of raw bytes.\n */\n raw(chunk) {\n if (this.buf.length) {\n this.chunks.push(new Uint8Array(this.buf));\n this.buf = [];\n }\n this.chunks.push(chunk);\n return this;\n }\n /**\n * Write a `uint32` value, an unsigned 32 bit varint.\n */\n uint32(value) {\n assertUInt32(value);\n // write value as varint 32, inlined for speed\n while (value > 0x7f) {\n this.buf.push((value & 0x7f) | 0x80);\n value = value >>> 7;\n }\n this.buf.push(value);\n return this;\n }\n /**\n * Write a `int32` value, a signed 32 bit varint.\n */\n int32(value) {\n assertInt32(value);\n varint32write(value, this.buf);\n return this;\n }\n /**\n * Write a `bool` value, a variant.\n */\n bool(value) {\n this.buf.push(value ? 1 : 0);\n return this;\n }\n /**\n * Write a `bytes` value, length-delimited arbitrary data.\n */\n bytes(value) {\n this.uint32(value.byteLength); // write length of chunk as varint\n return this.raw(value);\n }\n /**\n * Write a `string` value, length-delimited data converted to UTF-8 text.\n */\n string(value) {\n let chunk = this.encodeUtf8(value);\n this.uint32(chunk.byteLength); // write length of chunk as varint\n return this.raw(chunk);\n }\n /**\n * Write a `float` value, 32-bit floating point number.\n */\n float(value) {\n assertFloat32(value);\n let chunk = new Uint8Array(4);\n new DataView(chunk.buffer).setFloat32(0, value, true);\n return this.raw(chunk);\n }\n /**\n * Write a `double` value, a 64-bit floating point number.\n */\n double(value) {\n let chunk = new Uint8Array(8);\n new DataView(chunk.buffer).setFloat64(0, value, true);\n return this.raw(chunk);\n }\n /**\n * Write a `fixed32` value, an unsigned, fixed-length 32-bit integer.\n */\n fixed32(value) {\n assertUInt32(value);\n let chunk = new Uint8Array(4);\n new DataView(chunk.buffer).setUint32(0, value, true);\n return this.raw(chunk);\n }\n /**\n * Write a `sfixed32` value, a signed, fixed-length 32-bit integer.\n */\n sfixed32(value) {\n assertInt32(value);\n let chunk = new Uint8Array(4);\n new DataView(chunk.buffer).setInt32(0, value, true);\n return this.raw(chunk);\n }\n /**\n * Write a `sint32` value, a signed, zigzag-encoded 32-bit varint.\n */\n sint32(value) {\n assertInt32(value);\n // zigzag encode\n value = ((value << 1) ^ (value >> 31)) >>> 0;\n varint32write(value, this.buf);\n return this;\n }\n /**\n * Write a `fixed64` value, a signed, fixed-length 64-bit integer.\n */\n sfixed64(value) {\n let chunk = new Uint8Array(8), view = new DataView(chunk.buffer), tc = protoInt64.enc(value);\n view.setInt32(0, tc.lo, true);\n view.setInt32(4, tc.hi, true);\n return this.raw(chunk);\n }\n /**\n * Write a `fixed64` value, an unsigned, fixed-length 64 bit integer.\n */\n fixed64(value) {\n let chunk = new Uint8Array(8), view = new DataView(chunk.buffer), tc = protoInt64.uEnc(value);\n view.setInt32(0, tc.lo, true);\n view.setInt32(4, tc.hi, true);\n return this.raw(chunk);\n }\n /**\n * Write a `int64` value, a signed 64-bit varint.\n */\n int64(value) {\n let tc = protoInt64.enc(value);\n varint64write(tc.lo, tc.hi, this.buf);\n return this;\n }\n /**\n * Write a `sint64` value, a signed, zig-zag-encoded 64-bit varint.\n */\n sint64(value) {\n const tc = protoInt64.enc(value), \n // zigzag encode\n sign = tc.hi >> 31, lo = (tc.lo << 1) ^ sign, hi = ((tc.hi << 1) | (tc.lo >>> 31)) ^ sign;\n varint64write(lo, hi, this.buf);\n return this;\n }\n /**\n * Write a `uint64` value, an unsigned 64-bit varint.\n */\n uint64(value) {\n const tc = protoInt64.uEnc(value);\n varint64write(tc.lo, tc.hi, this.buf);\n return this;\n }\n}\nexport class BinaryReader {\n constructor(buf, decodeUtf8 = getTextEncoding().decodeUtf8) {\n this.decodeUtf8 = decodeUtf8;\n this.varint64 = varint64read; // dirty cast for `this`\n /**\n * Read a `uint32` field, an unsigned 32 bit varint.\n */\n this.uint32 = varint32read;\n this.buf = buf;\n this.len = buf.length;\n this.pos = 0;\n this.view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);\n }\n /**\n * Reads a tag - field number and wire type.\n */\n tag() {\n let tag = this.uint32(), fieldNo = tag >>> 3, wireType = tag & 7;\n if (fieldNo <= 0 || wireType < 0 || wireType > 5)\n throw new Error(\"illegal tag: field no \" + fieldNo + \" wire type \" + wireType);\n return [fieldNo, wireType];\n }\n /**\n * Skip one element and return the skipped data.\n *\n * When skipping StartGroup, provide the tags field number to check for\n * matching field number in the EndGroup tag.\n */\n skip(wireType, fieldNo) {\n let start = this.pos;\n switch (wireType) {\n case WireType.Varint:\n while (this.buf[this.pos++] & 0x80) {\n // ignore\n }\n break;\n // @ts-ignore TS7029: Fallthrough case in switch -- ignore instead of expect-error for compiler settings without noFallthroughCasesInSwitch: true\n case WireType.Bit64:\n this.pos += 4;\n case WireType.Bit32:\n this.pos += 4;\n break;\n case WireType.LengthDelimited:\n let len = this.uint32();\n this.pos += len;\n break;\n case WireType.StartGroup:\n for (;;) {\n const [fn, wt] = this.tag();\n if (wt === WireType.EndGroup) {\n if (fieldNo !== undefined && fn !== fieldNo) {\n throw new Error(\"invalid end group tag\");\n }\n break;\n }\n this.skip(wt, fn);\n }\n break;\n default:\n throw new Error(\"cant skip wire type \" + wireType);\n }\n this.assertBounds();\n return this.buf.subarray(start, this.pos);\n }\n /**\n * Throws error if position in byte array is out of range.\n */\n assertBounds() {\n if (this.pos > this.len)\n throw new RangeError(\"premature EOF\");\n }\n /**\n * Read a `int32` field, a signed 32 bit varint.\n */\n int32() {\n return this.uint32() | 0;\n }\n /**\n * Read a `sint32` field, a signed, zigzag-encoded 32-bit varint.\n */\n sint32() {\n let zze = this.uint32();\n // decode zigzag\n return (zze >>> 1) ^ -(zze & 1);\n }\n /**\n * Read a `int64` field, a signed 64-bit varint.\n */\n int64() {\n return protoInt64.dec(...this.varint64());\n }\n /**\n * Read a `uint64` field, an unsigned 64-bit varint.\n */\n uint64() {\n return protoInt64.uDec(...this.varint64());\n }\n /**\n * Read a `sint64` field, a signed, zig-zag-encoded 64-bit varint.\n */\n sint64() {\n let [lo, hi] = this.varint64();\n // decode zig zag\n let s = -(lo & 1);\n lo = ((lo >>> 1) | ((hi & 1) << 31)) ^ s;\n hi = (hi >>> 1) ^ s;\n return protoInt64.dec(lo, hi);\n }\n /**\n * Read a `bool` field, a variant.\n */\n bool() {\n let [lo, hi] = this.varint64();\n return lo !== 0 || hi !== 0;\n }\n /**\n * Read a `fixed32` field, an unsigned, fixed-length 32-bit integer.\n */\n fixed32() {\n // biome-ignore lint/suspicious/noAssignInExpressions: no\n return this.view.getUint32((this.pos += 4) - 4, true);\n }\n /**\n * Read a `sfixed32` field, a signed, fixed-length 32-bit integer.\n */\n sfixed32() {\n // biome-ignore lint/suspicious/noAssignInExpressions: no\n return this.view.getInt32((this.pos += 4) - 4, true);\n }\n /**\n * Read a `fixed64` field, an unsigned, fixed-length 64 bit integer.\n */\n fixed64() {\n return protoInt64.uDec(this.sfixed32(), this.sfixed32());\n }\n /**\n * Read a `fixed64` field, a signed, fixed-length 64-bit integer.\n */\n sfixed64() {\n return protoInt64.dec(this.sfixed32(), this.sfixed32());\n }\n /**\n * Read a `float` field, 32-bit floating point number.\n */\n float() {\n // biome-ignore lint/suspicious/noAssignInExpressions: no\n return this.view.getFloat32((this.pos += 4) - 4, true);\n }\n /**\n * Read a `double` field, a 64-bit floating point number.\n */\n double() {\n // biome-ignore lint/suspicious/noAssignInExpressions: no\n return this.view.getFloat64((this.pos += 8) - 8, true);\n }\n /**\n * Read a `bytes` field, length-delimited arbitrary data.\n */\n bytes() {\n let len = this.uint32(), start = this.pos;\n this.pos += len;\n this.assertBounds();\n return this.buf.subarray(start, start + len);\n }\n /**\n * Read a `string` field, length-delimited data converted to UTF-8 text.\n */\n string() {\n return this.decodeUtf8(this.bytes());\n }\n}\n/**\n * Assert a valid signed protobuf 32-bit integer as a number or string.\n */\nfunction assertInt32(arg) {\n if (typeof arg == \"string\") {\n arg = Number(arg);\n }\n else if (typeof arg != \"number\") {\n throw new Error(\"invalid int32: \" + typeof arg);\n }\n if (!Number.isInteger(arg) ||\n arg > INT32_MAX ||\n arg < INT32_MIN)\n throw new Error(\"invalid int32: \" + arg);\n}\n/**\n * Assert a valid unsigned protobuf 32-bit integer as a number or string.\n */\nfunction assertUInt32(arg) {\n if (typeof arg == \"string\") {\n arg = Number(arg);\n }\n else if (typeof arg != \"number\") {\n throw new Error(\"invalid uint32: \" + typeof arg);\n }\n if (!Number.isInteger(arg) ||\n arg > UINT32_MAX ||\n arg < 0)\n throw new Error(\"invalid uint32: \" + arg);\n}\n/**\n * Assert a valid protobuf float value as a number or string.\n */\nfunction assertFloat32(arg) {\n if (typeof arg == \"string\") {\n const o = arg;\n arg = Number(arg);\n if (Number.isNaN(arg) && o !== \"NaN\") {\n throw new Error(\"invalid float32: \" + o);\n }\n }\n else if (typeof arg != \"number\") {\n throw new Error(\"invalid float32: \" + typeof arg);\n }\n if (Number.isFinite(arg) &&\n (arg > FLOAT32_MAX || arg < FLOAT32_MIN))\n throw new Error(\"invalid float32: \" + arg);\n}\n"],"names":["WireType"],"mappings":"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","x_google_ignoreList":[0]}
@@ -1 +1 @@
1
- {"version":3,"file":"animation-worker.d.ts","sourceRoot":"","sources":["../../../src/providers/livekit/animation-worker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAgjBH,OAAO,EAAE,CAAC"}
1
+ {"version":3,"file":"animation-worker.d.ts","sourceRoot":"","sources":["../../../src/providers/livekit/animation-worker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAqkBH,OAAO,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@spatialwalk/avatarkit-rtc",
3
3
  "type": "module",
4
- "version": "1.0.0-beta.7",
4
+ "version": "1.0.0-beta.8",
5
5
  "description": "Unified RTC adapter for avatarkit - supports LiveKit, Agora and other RTC providers",
6
6
  "author": "SPAvatar Team",
7
7
  "license": "MIT",
@@ -33,7 +33,7 @@
33
33
  "@bufbuild/protobuf": "^2.10.2"
34
34
  },
35
35
  "peerDependencies": {
36
- "@spatialwalk/avatarkit": "^1.0.0-beta.74",
36
+ "@spatialwalk/avatarkit": "^1.0.0-beta.82",
37
37
  "livekit-client": "2.16.1",
38
38
  "agora-rtc-sdk-ng": "^4.x"
39
39
  },
@@ -46,7 +46,7 @@
46
46
  }
47
47
  },
48
48
  "devDependencies": {
49
- "@spatialwalk/avatarkit": "1.0.0-beta.74",
49
+ "@spatialwalk/avatarkit": "1.0.0-beta.82",
50
50
  "@types/node": "^22.10.2",
51
51
  "livekit-client": "2.16.1",
52
52
  "agora-rtc-sdk-ng": "^4.21.0",
@@ -1 +0,0 @@
1
- {"version":3,"file":"animation-worker-CUXZycUw.js","sources":["../src/providers/livekit/animation-worker.ts"],"sourcesContent":["/**\n * RTCRtpScriptTransform Worker for Animation Track (VP8 Video)\n *\n * This worker handles extracting animation data from VP8 video frames.\n * The server prepends a minimal VP8 header to trick the browser's depacketizer.\n *\n * Frame format after depacketization (VP8 descriptor is stripped by depacketizer):\n * [0-9] VP8 frame header (10 bytes) - minimal keyframe structure, skipped\n * [10] flags (uint8) - packet flags\n * [11-14] msgLen (little-endian u32) - length of protobuf message\n * [15..15+msgLen) protobuf Message binary\n */\n\n// Type declarations for RTCRtpScriptTransform API (experimental)\ndeclare interface RTCTransformEvent extends Event {\n transformer: {\n readable: ReadableStream;\n writable: WritableStream;\n options?: unknown;\n };\n}\n\n// Worker global scope with RTCRtpScriptTransform support\ndeclare const self: DedicatedWorkerGlobalScope & {\n onrtctransform?: ((event: RTCTransformEvent) => void) | null;\n};\n\n// VP8 header size (frame tag + sync code + dimensions, descriptor already stripped)\nconst VP8_FRAME_HEADER_SIZE = 10;\n\n// Protocol constants (must match egress-server/metadata_track.go)\nconst METADATA_FIXED_HEADER_SIZE = 5; // 1B flags + 4B length\n\n// Packet flags\nconst PACKET_FLAG_IDLE = 0x01;\nconst PACKET_FLAG_START = 0x02;\nconst PACKET_FLAG_END = 0x04;\nconst PACKET_FLAG_GZIPPED = 0x08;\nconst PACKET_FLAG_TRANSITION = 0x10; // Transition packet - contains target frame for generating transition from idle\nconst PACKET_FLAG_TRANSITION_END = 0x20; // Transition end packet - contains last frame for generating transition back to idle\nconst PACKET_FLAG_REDUNDANT = 0x40; // Packet contains redundant previous frame for ALR loss recovery\n\ninterface FrameMetadata {\n flags: number;\n protobufLength: number;\n protobufData: Uint8Array;\n // ALR (Application-Level Redundancy) data\n hasRedundant: boolean;\n redundantLength: number;\n redundantData: Uint8Array | null;\n}\n\ninterface TransformOptions {\n operation: 'receiver';\n}\n\n// State for receiver\nlet receiverMetaCount = 0;\nlet lastLogTime = 0;\nlet totalFrames = 0;\nlet framesWithMeta = 0;\nlet wasIdle = false; // Track idle state for transition detection\n\n// ALR (Application-Level Redundancy) state for loss detection\nlet lastReceivedTimestamp: number | null = null;\nlet framesRecovered = 0;\nlet framesLost = 0;\n// Expected timestamp increment per animation frame (90000 Hz * 40ms = 3600)\n// Animation is sent every 2nd audio frame (40ms intervals)\nconst EXPECTED_TIMESTAMP_INCREMENT = 3600;\n\n// Sequence tracking for out-of-order detection\nlet lastRenderedSeq: number = -1; // Last sequence number sent to main thread\nlet framesOutOfOrder = 0; // Count of out-of-order frames detected\nlet framesDuplicate = 0; // Count of duplicate frames skipped\nlet framesDropped = 0; // Count of frames that were permanently lost (gaps in sequence)\nlet framesSent = 0; // Total frames successfully sent to main thread\n\nfunction parseMetadataHeader(data: Uint8Array): { meta: FrameMetadata; headerSize: number } | null {\n if (data.byteLength < METADATA_FIXED_HEADER_SIZE) return null;\n const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n const flags = data[0];\n const msgLen = view.getUint32(1, true); // little-endian\n\n // Calculate minimum size needed\n const headerSize = METADATA_FIXED_HEADER_SIZE + msgLen;\n if (data.byteLength < headerSize) return null;\n\n // The compressed payload (will be decompressed later)\n const compressedData = data.slice(METADATA_FIXED_HEADER_SIZE, METADATA_FIXED_HEADER_SIZE + msgLen);\n\n // Note: With the new ALR optimization, both frames are gzipped together\n // The format INSIDE the gzip (after decompression) is:\n // - ALR: [currentLen (4B)][currentData][prevLen (4B)][prevData]\n // - Non-ALR: just the raw protobuf data\n // We return the compressed data here; decompression and ALR parsing happens in receiverTransform\n\n const hasRedundant = (flags & PACKET_FLAG_REDUNDANT) !== 0;\n\n return {\n meta: {\n flags,\n protobufLength: msgLen,\n protobufData: compressedData, // This is still compressed at this point\n hasRedundant,\n redundantLength: 0, // Will be determined after decompression\n redundantData: null, // Will be extracted after decompression\n },\n headerSize,\n };\n}\n\nfunction isIdlePacket(flags: number): boolean {\n return (flags & PACKET_FLAG_IDLE) !== 0;\n}\n\nfunction isStartPacket(flags: number): boolean {\n return (flags & PACKET_FLAG_START) !== 0;\n}\n\nfunction isEndPacket(flags: number): boolean {\n return (flags & PACKET_FLAG_END) !== 0;\n}\n\nfunction isGzipped(flags: number): boolean {\n return (flags & PACKET_FLAG_GZIPPED) !== 0;\n}\n\nfunction isTransitionPacket(flags: number): boolean {\n return (flags & PACKET_FLAG_TRANSITION) !== 0;\n}\n\nfunction isTransitionEndPacket(flags: number): boolean {\n return (flags & PACKET_FLAG_TRANSITION_END) !== 0;\n}\n\n// Decompress gzipped data using DecompressionStream API\nasync function decompressGzip(data: Uint8Array): Promise<Uint8Array> {\n const ds = new DecompressionStream('gzip');\n const writer = ds.writable.getWriter();\n // Create a copy to ensure we have a plain ArrayBuffer, not SharedArrayBuffer\n const copy = new Uint8Array(data);\n writer.write(copy);\n writer.close();\n\n const reader = ds.readable.getReader();\n const chunks: Uint8Array[] = [];\n let totalLength = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n chunks.push(value);\n totalLength += value.length;\n }\n\n const result = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of chunks) {\n result.set(chunk, offset);\n offset += chunk.length;\n }\n\n return result;\n}\n\n// Compression stats for logging\nlet totalCompressedBytes = 0;\nlet totalUncompressedBytes = 0;\n\n// ALR payload structure after decompression\ninterface ALRPayload {\n frameSeq: number; // Sequence number of current frame\n currentData: Uint8Array; // Current frame (N)\n prev1Data: Uint8Array | null; // Previous frame (N-1)\n prev2Data: Uint8Array | null; // Frame before previous (N-2)\n}\n\n// Parse ALR payload after decompression\n// ALR format: [frameSeq (4B)][currentLen (4B)][currentData][prev1Len (4B)][prev1Data][prev2Len (4B)][prev2Data]\n// Non-ALR format: [frameSeq (4B)][raw protobuf data]\n// Returns { frameSeq, currentData, prev1Data, prev2Data } or null if parsing fails\nfunction parseALRPayload(decompressed: Uint8Array, hasRedundant: boolean): ALRPayload | null {\n if (decompressed.byteLength < 4) return null;\n\n const view = new DataView(decompressed.buffer, decompressed.byteOffset, decompressed.byteLength);\n let offset = 0;\n\n // Parse frame sequence number\n const frameSeq = view.getUint32(offset, true);\n offset += 4;\n\n if (!hasRedundant) {\n // Non-ALR: rest is raw protobuf\n const currentData = decompressed.slice(offset);\n return { frameSeq, currentData, prev1Data: null, prev2Data: null };\n }\n\n // ALR format: parse current frame\n if (decompressed.byteLength < offset + 4) return null;\n const currentLen = view.getUint32(offset, true);\n offset += 4;\n if (decompressed.byteLength < offset + currentLen) return null;\n const currentData = decompressed.slice(offset, offset + currentLen);\n offset += currentLen;\n\n // Parse prev1 (N-1) if available\n let prev1Data: Uint8Array | null = null;\n if (decompressed.byteLength >= offset + 4) {\n const prev1Len = view.getUint32(offset, true);\n offset += 4;\n if (prev1Len > 0 && decompressed.byteLength >= offset + prev1Len) {\n prev1Data = decompressed.slice(offset, offset + prev1Len);\n offset += prev1Len;\n }\n }\n\n // Parse prev2 (N-2) if available\n let prev2Data: Uint8Array | null = null;\n if (decompressed.byteLength >= offset + 4) {\n const prev2Len = view.getUint32(offset, true);\n offset += 4;\n if (prev2Len > 0 && decompressed.byteLength >= offset + prev2Len) {\n prev2Data = decompressed.slice(offset, offset + prev2Len);\n }\n }\n\n return { frameSeq, currentData, prev1Data, prev2Data };\n}\n\n// Helper to send animation data to main thread with sequence tracking\n// Returns true if frame was sent, false if skipped (duplicate/out-of-order)\nfunction sendAnimationToMainThread(\n protobufData: Uint8Array,\n flags: number,\n frameSeq: number,\n isRecovered: boolean = false\n): boolean {\n const isIdle = isIdlePacket(flags);\n const isStart = isStartPacket(flags);\n const isEnd = isEndPacket(flags);\n\n // Check for out-of-order or duplicate frames\n if (frameSeq <= lastRenderedSeq && lastRenderedSeq !== -1 && !isStart) {\n if (frameSeq === lastRenderedSeq) {\n framesDuplicate++;\n } else {\n framesOutOfOrder++;\n }\n return false;\n }\n\n // Check for gap (frames we never received and couldn't recover) - these are DROPPED\n if (lastRenderedSeq !== -1 && frameSeq > lastRenderedSeq + 1 && !isStart) {\n const gap = frameSeq - lastRenderedSeq - 1;\n framesDropped += gap;\n }\n\n framesSent++;\n\n lastRenderedSeq = frameSeq;\n\n const protobufBuffer = new ArrayBuffer(protobufData.byteLength);\n new Uint8Array(protobufBuffer).set(protobufData);\n\n self.postMessage({\n type: 'animation',\n flags,\n isIdle,\n isStart,\n isEnd,\n isRecovered,\n frameSeq,\n protobufData: protobufBuffer,\n }, { transfer: [protobufBuffer] });\n\n return true;\n}\n\n// Receiver transform: extract animation data from video frames\n// Uses ALR (Application-Level Redundancy) to recover lost frames\nfunction receiverTransform(frame: RTCEncodedVideoFrame, _controller: TransformStreamDefaultController<RTCEncodedVideoFrame>) {\n totalFrames++;\n const data = new Uint8Array(frame.data);\n const currentTimestamp = frame.timestamp;\n\n // Skip the VP8 frame header (10 bytes) - the VP8 descriptor is already stripped by depacketizer\n // Check if we have enough data for VP8 header + at least 1 byte of animation data\n if (data.length <= VP8_FRAME_HEADER_SIZE) {\n return; // Frame too small, skip\n }\n\n // Extract animation data after VP8 header\n const animData = data.subarray(VP8_FRAME_HEADER_SIZE);\n\n const parsed = parseMetadataHeader(animData);\n\n if (parsed) {\n const { meta } = parsed;\n framesWithMeta++;\n receiverMetaCount++;\n\n const isIdle = isIdlePacket(meta.flags);\n const isStart = isStartPacket(meta.flags);\n const isEnd = isEndPacket(meta.flags);\n\n // ALR: Detect frame loss and recover using redundant data\n // Check if we missed frames by looking at timestamp gap\n if (lastReceivedTimestamp !== null && !isIdle && !isStart) {\n const timestampDelta = currentTimestamp - lastReceivedTimestamp;\n // Allow some tolerance (1.5x expected increment) for timing variations\n if (timestampDelta > EXPECTED_TIMESTAMP_INCREMENT * 1.5) {\n const missedFrames = Math.round(timestampDelta / EXPECTED_TIMESTAMP_INCREMENT) - 1;\n framesLost += missedFrames;\n\n // Try to recover using redundant data from current packet\n // With ALR optimization, up to 3 frames are gzipped together\n if (meta.hasRedundant && isGzipped(meta.flags)) {\n // Decompress to get all frames, then recover\n totalCompressedBytes += meta.protobufData.byteLength;\n\n decompressGzip(meta.protobufData)\n .then((decompressed) => {\n totalUncompressedBytes += decompressed.byteLength;\n\n const parsed = parseALRPayload(decompressed, true);\n if (parsed) {\n const currentSeq = parsed.frameSeq;\n\n // Determine how many frames we can recover based on how many were lost\n // and how many redundant frames we have\n const framesToRecover: Array<{data: Uint8Array, seq: number}> = [];\n\n if (missedFrames >= 2 && parsed.prev2Data) {\n framesToRecover.push({ data: parsed.prev2Data, seq: currentSeq - 2 });\n }\n if (missedFrames >= 1 && parsed.prev1Data) {\n framesToRecover.push({ data: parsed.prev1Data, seq: currentSeq - 1 });\n }\n\n const recovered = framesToRecover.length;\n if (recovered > 0) {\n framesRecovered += recovered;\n\n // Send recovered frames in chronological order (oldest first)\n for (const frame of framesToRecover) {\n sendAnimationToMainThread(frame.data, meta.flags & ~PACKET_FLAG_REDUNDANT, frame.seq, true);\n }\n }\n\n // Then send current frame\n sendAnimationToMainThread(parsed.currentData, meta.flags & ~PACKET_FLAG_REDUNDANT, currentSeq, false);\n }\n })\n .catch((err) => {\n console.error(`[Animation Worker] ALR decompression error:`, err);\n });\n\n // Update timestamp and return early (we've handled this frame)\n lastReceivedTimestamp = currentTimestamp;\n return;\n }\n }\n }\n\n // Update last received timestamp (skip for idle packets to avoid false loss detection)\n if (!isIdle) {\n lastReceivedTimestamp = currentTimestamp;\n }\n\n // Reset state on session start\n if (isStart) {\n lastReceivedTimestamp = currentTimestamp;\n framesRecovered = 0;\n framesLost = 0;\n lastRenderedSeq = -1;\n framesOutOfOrder = 0;\n framesDuplicate = 0;\n framesDropped = 0;\n framesSent = 0;\n }\n\n const isTransition = isTransitionPacket(meta.flags);\n\n if (isIdle) {\n // First idle packet - post idleStart event\n if (!wasIdle) {\n self.postMessage({ type: 'idleStart' });\n wasIdle = true;\n }\n } else if (isTransition && meta.protobufLength > 0) {\n // Transition packet - contains target frame for smooth transition from idle\n wasIdle = false;\n\n // Decompress if gzipped (transition packets are always gzipped)\n const gzipped = isGzipped(meta.flags);\n if (gzipped) {\n totalCompressedBytes += meta.protobufData.byteLength;\n\n decompressGzip(meta.protobufData).then((decompressed) => {\n totalUncompressedBytes += decompressed.byteLength;\n\n const protobufBuffer = new ArrayBuffer(decompressed.byteLength);\n new Uint8Array(protobufBuffer).set(decompressed);\n\n // Post transition event - main thread will generate transition frames\n self.postMessage({\n type: 'transition',\n flags: meta.flags,\n protobufData: protobufBuffer,\n }, { transfer: [protobufBuffer] });\n }).catch((err) => {\n console.error(`[Animation Worker] Gzip decompress error (transition):`, err);\n });\n } else {\n const protobufBuffer = new ArrayBuffer(meta.protobufData.byteLength);\n new Uint8Array(protobufBuffer).set(meta.protobufData);\n\n self.postMessage({\n type: 'transition',\n flags: meta.flags,\n protobufData: protobufBuffer,\n }, { transfer: [protobufBuffer] });\n }\n } else if (isTransitionEndPacket(meta.flags) && meta.protobufLength > 0) {\n // Transition end packet - contains last frame for smooth transition back to idle\n\n // Decompress if gzipped (transition end packets are always gzipped)\n const gzipped = isGzipped(meta.flags);\n if (gzipped) {\n totalCompressedBytes += meta.protobufData.byteLength;\n\n decompressGzip(meta.protobufData).then((decompressed) => {\n totalUncompressedBytes += decompressed.byteLength;\n\n const protobufBuffer = new ArrayBuffer(decompressed.byteLength);\n new Uint8Array(protobufBuffer).set(decompressed);\n\n // Post transition end event - main thread will generate reverse transition frames\n self.postMessage({\n type: 'transitionEnd',\n flags: meta.flags,\n protobufData: protobufBuffer,\n }, { transfer: [protobufBuffer] });\n }).catch((err) => {\n console.error(`[Animation Worker] Gzip decompress error (transitionEnd):`, err);\n });\n } else {\n const protobufBuffer = new ArrayBuffer(meta.protobufData.byteLength);\n new Uint8Array(protobufBuffer).set(meta.protobufData);\n\n self.postMessage({\n type: 'transitionEnd',\n flags: meta.flags,\n protobufData: protobufBuffer,\n }, { transfer: [protobufBuffer] });\n }\n } else if (meta.protobufLength > 0) {\n // Normal animation packet\n // Transition from idle to streaming (if not already transitioned via transition packet)\n if (wasIdle) {\n wasIdle = false;\n }\n\n // Decompress if gzipped\n const gzipped = isGzipped(meta.flags);\n if (gzipped) {\n // Track compression stats\n totalCompressedBytes += meta.protobufData.byteLength;\n\n // Async decompression\n decompressGzip(meta.protobufData).then((decompressed) => {\n totalUncompressedBytes += decompressed.byteLength;\n\n // Parse ALR format to get frame sequence and data\n // Format: [frameSeq (4B)][currentLen (4B)][currentData]... or [frameSeq (4B)][raw protobuf]\n const parsed = parseALRPayload(decompressed, meta.hasRedundant);\n if (parsed) {\n sendAnimationToMainThread(parsed.currentData, meta.flags & ~PACKET_FLAG_REDUNDANT, parsed.frameSeq, false);\n }\n }).catch(() => {});\n } else {\n // Uncompressed - this shouldn't happen in normal operation but handle it\n const protobufBuffer = new ArrayBuffer(meta.protobufData.byteLength);\n new Uint8Array(protobufBuffer).set(meta.protobufData);\n\n self.postMessage({\n type: 'animation',\n flags: meta.flags,\n isIdle: false,\n isStart,\n isEnd,\n frameSeq: -1, // Unknown sequence\n protobufData: protobufBuffer,\n }, { transfer: [protobufBuffer] });\n }\n }\n\n // Report stats every second\n const now = performance.now();\n if (now - lastLogTime > 1000) {\n lastLogTime = now;\n self.postMessage({\n type: 'metadata',\n protobufLength: meta.protobufLength,\n framesPerSec: receiverMetaCount,\n totalFrames,\n framesWithMeta,\n framesLost,\n framesRecovered,\n framesOutOfOrder,\n framesDuplicate,\n framesDropped,\n framesSent,\n lastRenderedSeq,\n });\n receiverMetaCount = 0;\n }\n }\n\n // For video, we don't enqueue the frame since it's not real video\n // The browser's VP8 decoder would fail on our custom data anyway\n // controller.enqueue(frame);\n}\n\n// Handle rtctransform event (RTCRtpScriptTransform)\nself.onrtctransform = (event: RTCTransformEvent) => {\n const transformer = event.transformer;\n const options = transformer.options as TransformOptions;\n\n try {\n if (options.operation === 'receiver') {\n // Reset state\n receiverMetaCount = 0;\n lastLogTime = 0;\n totalFrames = 0;\n framesWithMeta = 0;\n wasIdle = false;\n lastReceivedTimestamp = null;\n framesRecovered = 0;\n framesLost = 0;\n lastRenderedSeq = -1;\n framesOutOfOrder = 0;\n framesDuplicate = 0;\n framesDropped = 0;\n framesSent = 0;\n\n transformer.readable\n .pipeThrough(new TransformStream({ transform: receiverTransform }))\n .pipeTo(transformer.writable)\n .catch((err: unknown) => {\n console.error('[Animation Worker] Pipeline error:', err);\n self.postMessage({ type: 'error', error: `Animation receiver pipe error: ${err}` });\n });\n\n self.postMessage({ type: 'ready', operation: 'receiver' });\n }\n } catch (err) {\n console.error('[Animation Worker] Setup error:', err);\n self.postMessage({ type: 'error', error: `Animation transform setup error: ${err}` });\n }\n};\n\n// Handle message-based initialization for fallback\nself.onmessage = (event: MessageEvent) => {\n const { type } = event.data;\n if (type === 'init') {\n self.postMessage({ type: 'initialized' });\n }\n};\n\nexport {};\n"],"names":["currentData","parsed","frame"],"mappings":"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"}