@spatius/avatarkit 1.3.1-beta.4 → 1.3.1-beta.6

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/CHANGELOG.md CHANGED
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.3.1-beta.6] - 2026-08-01
9
+
10
+ ### Changed
11
+ - Internal telemetry changes only; no changes to the public API or runtime behavior.
12
+
13
+ ## [1.3.1-beta.5] - 2026-07-31
14
+
15
+ ### Changed
16
+ - Internal playback and telemetry changes only; no changes to the public API or runtime behavior.
17
+
8
18
  ## [1.3.1-beta.4] - 2026-07-30
9
19
 
10
20
  ### Added
@@ -1,8 +1,8 @@
1
1
  import { n as __exportAll } from "./rolldown-runtime-B-1-B7_t.js";
2
- import { t as AvatarSDK } from "./AvatarSDK-CuejGi0J.js";
3
- import { Et as ErrorCode, c as logEvent, gt as generateTraceId, l as logMetric, t as logger, vt as AvatarError, y as recordHttpClientDuration } from "./logger-C3fw-NWP.js";
4
- import { n as APP_CONFIG, r as getFlameCdnBase, t as errorToMessage } from "./error-utils-PtNzUHiL.js";
5
- import { t as PwaCacheManager } from "./pwa-cache-manager-D3nj4sd5.js";
2
+ import { t as AvatarSDK } from "./AvatarSDK-CnZqa_X4.js";
3
+ import { Et as ErrorCode, c as logEvent, gt as generateTraceId, l as logMetric, t as logger, vt as AvatarError, y as recordHttpClientDuration } from "./logger-fAU8oahT.js";
4
+ import { n as APP_CONFIG, r as getFlameCdnBase, t as errorToMessage } from "./error-utils-CqKOrHrY.js";
5
+ import { t as PwaCacheManager } from "./pwa-cache-manager-CwXaM3xR.js";
6
6
  //#region core/AvatarDownloader.ts
7
7
  var AvatarDownloader_exports = /* @__PURE__ */ __exportAll({ AvatarDownloader: () => AvatarDownloader });
8
8
  /**
@@ -1,5 +1,5 @@
1
1
  import { n as __exportAll } from "./rolldown-runtime-B-1-B7_t.js";
2
- import { $ as TraceFlags, A as ExportResultCode, B as ATTR_EXCEPTION_TYPE, C as createInstrumentationScope, D as defaultResource, E as OTLPExporterBase, F as isTimeInputHrTime, G as isTracingSuppressed, H as getNumberFromEnv, I as millisToHrTime, J as diag$1, K as suppressTracing, L as otperformance, M as hrTime, N as hrTimeDuration, O as resourceFromAttributes, P as isTimeInput, Q as INVALID_SPAN_CONTEXT, R as ATTR_EXCEPTION_MESSAGE, S as JSON_ENCODER, T as toAttributes, Tt as DrivingServiceMode, U as getStringFromEnv, V as ATTR_SERVICE_NAME, W as globalErrorHandler, X as isSpanContextValid, Y as context, Z as isValidTraceId, _ as cleanupOtelMetrics, a as clientContextFields, at as getGlobal, c as logEvent, ct as OTEL_LOGS_ENDPOINT, d as cleanupOtel, dt as OTEL_TRACES_ENDPOINT, et as ContextAPI, f as initializeOtel, ft as OTEL_TRACES_STREAM_NAME, g as fetchBootstrap, h as clockSync, ht as idManager, i as cleanupPostHog, it as DiagAPI, j as addHrTimes, k as BindOnceFuture, kt as LogLevel, lt as OTEL_PASSWORD, n as setLogLevel, nt as ROOT_CONTEXT, o as getLogsFeatureFlag, ot as registerGlobal, pt as OTEL_USERNAME, q as trace, r as logSink, rt as createContextKey, s as initializePostHog, st as unregisterGlobal, t as logger, tt as createNoopMeter, u as updatePostHogPersonPropertiesForFlags, ut as OTEL_STREAM_NAME, v as initializeOtelMetrics, w as createResource, x as createLegacyOtlpBrowserExportDelegate, z as ATTR_EXCEPTION_STACKTRACE } from "./logger-C3fw-NWP.js";
2
+ import { $ as TraceFlags, A as ExportResultCode, B as ATTR_EXCEPTION_TYPE, C as createInstrumentationScope, D as defaultResource, E as OTLPExporterBase, F as isTimeInputHrTime, G as isTracingSuppressed, H as getNumberFromEnv, I as millisToHrTime, J as diag$1, K as suppressTracing, L as otperformance, M as hrTime, N as hrTimeDuration, O as resourceFromAttributes, P as isTimeInput, Q as INVALID_SPAN_CONTEXT, R as ATTR_EXCEPTION_MESSAGE, S as JSON_ENCODER, T as toAttributes, Tt as DrivingServiceMode, U as getStringFromEnv, V as ATTR_SERVICE_NAME, W as globalErrorHandler, X as isSpanContextValid, Y as context, Z as isValidTraceId, _ as cleanupOtelMetrics, a as clientContextFields, at as getGlobal, c as logEvent, ct as OTEL_LOGS_ENDPOINT, d as cleanupOtel, dt as OTEL_TRACES_ENDPOINT, et as ContextAPI, f as initializeOtel, ft as OTEL_TRACES_STREAM_NAME, g as fetchBootstrap, h as clockSync, ht as idManager, i as cleanupPostHog, it as DiagAPI, j as addHrTimes, k as BindOnceFuture, kt as LogLevel, lt as OTEL_PASSWORD, n as setLogLevel, nt as ROOT_CONTEXT, o as getLogsFeatureFlag, ot as registerGlobal, pt as OTEL_USERNAME, q as trace, r as logSink, rt as createContextKey, s as initializePostHog, st as unregisterGlobal, t as logger, tt as createNoopMeter, u as updatePostHogPersonPropertiesForFlags, ut as OTEL_STREAM_NAME, v as initializeOtelMetrics, w as createResource, x as createLegacyOtlpBrowserExportDelegate, z as ATTR_EXCEPTION_STACKTRACE } from "./logger-fAU8oahT.js";
3
3
  //#region node_modules/.pnpm/@bufbuild+protobuf@2.10.1/node_modules/@bufbuild/protobuf/dist/esm/wire/varint.js
4
4
  /**
5
5
  * Read a 64 bit varint as two JS numbers.
@@ -4772,7 +4772,8 @@ function initializeOtelTrace(version, resourceAttrs) {
4772
4772
  "sdk.package": "spatius-web-sdk",
4773
4773
  "app_id": resourceAttrs.appId || "",
4774
4774
  "region": resourceAttrs.region,
4775
- "dsm": resourceAttrs.dsm
4775
+ "dsm": resourceAttrs.dsm,
4776
+ ...clientContextFields()
4776
4777
  }),
4777
4778
  spanProcessors: [new BatchSpanProcessor(new OTLPTraceExporter({
4778
4779
  url: OTEL_TRACES_ENDPOINT,
@@ -6320,7 +6321,7 @@ var AvatarSDK = class {
6320
6321
  static _initializationState = "uninitialized";
6321
6322
  static _initializingPromise = null;
6322
6323
  static _configuration = null;
6323
- static _version = "1.3.1-beta.4";
6324
+ static _version = "1.3.1-beta.6";
6324
6325
  static _avatarCore = null;
6325
6326
  static _cachedDeviceScore = null;
6326
6327
  static _rendererBackend = null;
@@ -6486,7 +6487,7 @@ var AvatarSDK = class {
6486
6487
  logger.log("[AvatarSDK] Loading template resources...");
6487
6488
  logEvent("template_init_start", "info", { stage: "sdk_init" });
6488
6489
  try {
6489
- const { AvatarDownloader } = await import("./AvatarDownloader-C2JJVqKm.js").then((n) => n.n);
6490
+ const { AvatarDownloader } = await import("./AvatarDownloader-Dfi7wtgQ.js").then((n) => n.n);
6490
6491
  const templateResources = await new AvatarDownloader().loadUnifiedTemplate();
6491
6492
  if (await this._avatarCore.loadTemplateResourcesFromBuffers(templateResources)) logger.log("[AvatarSDK] Template resources initialized successfully");
6492
6493
  else logger.log("[AvatarSDK] Template resources already initialized, skipping...");
@@ -1,5 +1,5 @@
1
1
  import { n as __exportAll, r as __toESM, t as __commonJSMin } from "./rolldown-runtime-B-1-B7_t.js";
2
- import { t as logger } from "./logger-C3fw-NWP.js";
2
+ import { t as logger } from "./logger-fAU8oahT.js";
3
3
  /** Opus granule positions are always in 48 kHz samples, regardless of input rate. */
4
4
  var OPUS_GRANULE_RATE = 48e3;
5
5
  /**
@@ -1,4 +1,4 @@
1
- import { t as logger } from "./logger-C3fw-NWP.js";
1
+ import { t as logger } from "./logger-fAU8oahT.js";
2
2
  //#region audio/OpusDecoderProxy.ts
3
3
  var OpusDecoderProxy = class OpusDecoderProxy {
4
4
  worker = null;
@@ -21,7 +21,7 @@ var OpusDecoderProxy = class OpusDecoderProxy {
21
21
  } catch (err) {
22
22
  logger.warn("[Opus][DecoderProxy] Worker unavailable, falling back to main-thread decode:", err instanceof Error ? err.message : String(err));
23
23
  }
24
- const { OggOpusDecoder } = await import("./OpusCodec-Bv4kzdt8.js").then((n) => n.n);
24
+ const { OggOpusDecoder } = await import("./OpusCodec-D9DcUV65.js").then((n) => n.n);
25
25
  proxy.fallbackDecoder = new OggOpusDecoder();
26
26
  proxy.backend = "main-thread";
27
27
  return proxy;
@@ -32,7 +32,7 @@ var OpusDecoderProxy = class OpusDecoderProxy {
32
32
  try {
33
33
  worker = new Worker(new URL(
34
34
  /* @vite-ignore */
35
- "/assets/OpusDecoderWorker.worker-Bd4svkEs.js",
35
+ "/assets/OpusDecoderWorker.worker-B7R93nev.js",
36
36
  "" + import.meta.url
37
37
  ), { type: "module" });
38
38
  } catch (err) {
@@ -1,4 +1,4 @@
1
- import { t as logger } from "./logger-C3fw-NWP.js";
1
+ import { t as logger } from "./logger-fAU8oahT.js";
2
2
  //#region audio/OpusEncoderProxy.ts
3
3
  var OpusEncoderProxy = class OpusEncoderProxy {
4
4
  worker = null;
@@ -26,7 +26,7 @@ var OpusEncoderProxy = class OpusEncoderProxy {
26
26
  } catch (err) {
27
27
  logger.warn("[Opus][Proxy] Worker unavailable, falling back to main-thread encode:", err instanceof Error ? err.message : String(err));
28
28
  }
29
- const { OggOpusEncoder } = await import("./OpusCodec-Bv4kzdt8.js").then((n) => n.n);
29
+ const { OggOpusEncoder } = await import("./OpusCodec-D9DcUV65.js").then((n) => n.n);
30
30
  proxy.fallbackEncoder = new OggOpusEncoder(sampleRate, bitrate);
31
31
  proxy.backend = "main-thread";
32
32
  return proxy;
@@ -37,7 +37,7 @@ var OpusEncoderProxy = class OpusEncoderProxy {
37
37
  try {
38
38
  worker = new Worker(new URL(
39
39
  /* @vite-ignore */
40
- "/assets/OpusEncoderWorker.worker-BdxYhZZ9.js",
40
+ "/assets/OpusEncoderWorker.worker-BYWIV5xu.js",
41
41
  "" + import.meta.url
42
42
  ), { type: "module" });
43
43
  } catch (err) {
@@ -1,5 +1,5 @@
1
- import { c as logEvent, t as logger } from "./logger-C3fw-NWP.js";
2
- import { n as APP_CONFIG, t as errorToMessage } from "./error-utils-PtNzUHiL.js";
1
+ import { c as logEvent, t as logger } from "./logger-fAU8oahT.js";
2
+ import { n as APP_CONFIG, t as errorToMessage } from "./error-utils-CqKOrHrY.js";
3
3
  //#region audio/StreamingAudioPlayer.ts
4
4
  /**
5
5
  * Streaming Audio Player
@@ -1,5 +1,5 @@
1
- import { _ as recordHttpClientDuration, c as logEvent, dt as isDebugMode, l as logMetric, mt as AvatarError, pt as generateTraceId, t as logger, vt as ErrorCode } from "./logger-B-X9jUON.js";
2
- import { t as AvatarSDK } from "./AvatarSDK-RVj90oMR.js";
1
+ import { _ as recordHttpClientDuration, c as logEvent, dt as isDebugMode, l as logMetric, mt as AvatarError, pt as generateTraceId, t as logger, vt as ErrorCode } from "./logger-D8rDVim7.js";
2
+ import { t as AvatarSDK } from "./AvatarSDK-DR8dNylh.js";
3
3
  //#region config/app-config.ts
4
4
  const GLOBAL_FLAME_CDN_BASE = "https://cdn.spatialwalk.cloud/public";
5
5
  const CN_FLAME_CDN_BASE = "https://cdn.spatialwalk.top/public";
@@ -1,5 +1,5 @@
1
1
  import { n as __exportAll } from "./rolldown-runtime-B-1-B7_t.js";
2
- import { $ as ROOT_CONTEXT, A as hrTimeDuration, B as getStringFromEnv, C as OTLPExporterBase, D as ExportResultCode, E as BindOnceFuture, F as ATTR_EXCEPTION_MESSAGE, G as diag$1, H as isTracingSuppressed, I as ATTR_EXCEPTION_STACKTRACE, J as isValidTraceId, K as context, L as ATTR_EXCEPTION_TYPE, M as isTimeInputHrTime, N as millisToHrTime, O as addHrTimes, P as otperformance, Q as createNoopMeter, R as ATTR_SERVICE_NAME, S as toAttributes, T as resourceFromAttributes, U as suppressTracing, V as globalErrorHandler, W as trace, X as TraceFlags, Y as INVALID_SPAN_CONTEXT, Z as ContextAPI, _t as DrivingServiceMode, a as clientContextFields, at as OTEL_LOGS_ENDPOINT, b as createInstrumentationScope, c as logEvent, ct as OTEL_TRACES_ENDPOINT, d as cleanupOtel, et as createContextKey, f as initializeOtel, ft as idManager, g as initializeOtelMetrics, h as cleanupOtelMetrics, i as cleanupPostHog, it as unregisterGlobal, j as isTimeInput, k as hrTime, lt as OTEL_TRACES_STREAM_NAME, m as fetchBootstrap, n as setLogLevel, nt as getGlobal, o as getLogsFeatureFlag, ot as OTEL_PASSWORD, p as clockSync, q as isSpanContextValid, r as logSink, rt as registerGlobal, s as initializePostHog, st as OTEL_STREAM_NAME, t as logger, tt as DiagAPI, u as updatePostHogPersonPropertiesForFlags, ut as OTEL_USERNAME, v as createLegacyOtlpBrowserExportDelegate, w as defaultResource, x as createResource, y as JSON_ENCODER, yt as LogLevel, z as getNumberFromEnv } from "./logger-B-X9jUON.js";
2
+ import { $ as ROOT_CONTEXT, A as hrTimeDuration, B as getStringFromEnv, C as OTLPExporterBase, D as ExportResultCode, E as BindOnceFuture, F as ATTR_EXCEPTION_MESSAGE, G as diag$1, H as isTracingSuppressed, I as ATTR_EXCEPTION_STACKTRACE, J as isValidTraceId, K as context, L as ATTR_EXCEPTION_TYPE, M as isTimeInputHrTime, N as millisToHrTime, O as addHrTimes, P as otperformance, Q as createNoopMeter, R as ATTR_SERVICE_NAME, S as toAttributes, T as resourceFromAttributes, U as suppressTracing, V as globalErrorHandler, W as trace, X as TraceFlags, Y as INVALID_SPAN_CONTEXT, Z as ContextAPI, _t as DrivingServiceMode, a as clientContextFields, at as OTEL_LOGS_ENDPOINT, b as createInstrumentationScope, c as logEvent, ct as OTEL_TRACES_ENDPOINT, d as cleanupOtel, et as createContextKey, f as initializeOtel, ft as idManager, g as initializeOtelMetrics, h as cleanupOtelMetrics, i as cleanupPostHog, it as unregisterGlobal, j as isTimeInput, k as hrTime, lt as OTEL_TRACES_STREAM_NAME, m as fetchBootstrap, n as setLogLevel, nt as getGlobal, o as getLogsFeatureFlag, ot as OTEL_PASSWORD, p as clockSync, q as isSpanContextValid, r as logSink, rt as registerGlobal, s as initializePostHog, st as OTEL_STREAM_NAME, t as logger, tt as DiagAPI, u as updatePostHogPersonPropertiesForFlags, ut as OTEL_USERNAME, v as createLegacyOtlpBrowserExportDelegate, w as defaultResource, x as createResource, y as JSON_ENCODER, yt as LogLevel, z as getNumberFromEnv } from "./logger-D8rDVim7.js";
3
3
  //#region node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/baggage/internal/baggage-impl.js
4
4
  var BaggageImpl = class BaggageImpl {
5
5
  constructor(entries) {
@@ -2344,7 +2344,8 @@ function initializeOtelTrace(version, resourceAttrs) {
2344
2344
  "sdk.package": "spatius-web-sdk",
2345
2345
  "app_id": resourceAttrs.appId || "",
2346
2346
  "region": resourceAttrs.region,
2347
- "dsm": resourceAttrs.dsm
2347
+ "dsm": resourceAttrs.dsm,
2348
+ ...clientContextFields()
2348
2349
  }),
2349
2350
  spanProcessors: [new BatchSpanProcessor(new OTLPTraceExporter({
2350
2351
  url: OTEL_TRACES_ENDPOINT,
@@ -6108,7 +6109,7 @@ var AvatarSDK = class {
6108
6109
  static _initializationState = "uninitialized";
6109
6110
  static _initializingPromise = null;
6110
6111
  static _configuration = null;
6111
- static _version = "1.3.1-beta.4";
6112
+ static _version = "1.3.1-beta.6";
6112
6113
  static _avatarCore = null;
6113
6114
  static _cachedDeviceScore = null;
6114
6115
  static _rendererBackend = null;
@@ -6274,7 +6275,7 @@ var AvatarSDK = class {
6274
6275
  logger.log("[AvatarSDK] Loading template resources...");
6275
6276
  logEvent("template_init_start", "info", { stage: "sdk_init" });
6276
6277
  try {
6277
- const { AvatarDownloader } = await import("./AvatarDownloader-C-CiIH1p.js");
6278
+ const { AvatarDownloader } = await import("./AvatarDownloader-D5GePpJ2.js");
6278
6279
  const templateResources = await new AvatarDownloader().loadUnifiedTemplate();
6279
6280
  if (await this._avatarCore.loadTemplateResourcesFromBuffers(templateResources)) logger.log("[AvatarSDK] Template resources initialized successfully");
6280
6281
  else logger.log("[AvatarSDK] Template resources already initialized, skipping...");
@@ -1,5 +1,5 @@
1
1
  import { r as __toESM, t as __commonJSMin } from "./rolldown-runtime-B-1-B7_t.js";
2
- import { t as logger } from "./logger-B-X9jUON.js";
2
+ import { t as logger } from "./logger-D8rDVim7.js";
3
3
  //#region __vite-browser-external
4
4
  var require___vite_browser_external = /* @__PURE__ */ __commonJSMin(((exports, module) => {
5
5
  module.exports = {};
@@ -1,5 +1,5 @@
1
1
  import { r as __toESM, t as __commonJSMin } from "./rolldown-runtime-B-1-B7_t.js";
2
- import { t as logger } from "./logger-B-X9jUON.js";
2
+ import { t as logger } from "./logger-D8rDVim7.js";
3
3
  //#region __vite-browser-external
4
4
  var require___vite_browser_external = /* @__PURE__ */ __commonJSMin(((exports, module) => {
5
5
  module.exports = {};
@@ -13549,6 +13549,165 @@ const HTTP_NETWORK_BUCKETS_MS = [
13549
13549
  4e3,
13550
13550
  5e3
13551
13551
  ];
13552
+ /**
13553
+ * RTC playback 指标的桶。默认桶(0/5/10/25/50/…/10000)对这批指标毫无分辨率:
13554
+ * 帧率只可能落在 0~25,缺帧数和卡顿次数几乎全部挤在第一个桶里,分位数因此毫无意义。
13555
+ * 桶按各指标的实际值域给:
13556
+ *
13557
+ * - 帧率:每帧一个桶。25fps 与 21fps 的观感差别正是要看的,5 档分级会把两者归成一类。
13558
+ * - 帧数:正常轮次对应播放时长桶、没上屏的帧对应卡顿时长桶,都按帧间隔换算。
13559
+ * - 卡顿次数:数的是次数不是帧,自成一组。
13560
+ * - 百分比:每 5% 一档,0~100。
13561
+ * - 时长:分两组——整轮播放是秒级,单次卡顿是一帧起步的毫秒级。
13562
+ *
13563
+ * 这些 metric 由 @spatius/avatarkit-rtc 发出(meter 名 spatius-avatarkit-rtc),
13564
+ * 但 view 只能配在创建 MeterProvider 的这一侧,所以桶定义留在这里。
13565
+ */
13566
+ const RTC_FPS_BUCKETS = [
13567
+ 0,
13568
+ 1,
13569
+ 2,
13570
+ 3,
13571
+ 4,
13572
+ 5,
13573
+ 6,
13574
+ 7,
13575
+ 8,
13576
+ 9,
13577
+ 10,
13578
+ 11,
13579
+ 12,
13580
+ 13,
13581
+ 14,
13582
+ 15,
13583
+ 16,
13584
+ 17,
13585
+ 18,
13586
+ 19,
13587
+ 20,
13588
+ 21,
13589
+ 22,
13590
+ 23,
13591
+ 24
13592
+ ];
13593
+ /**
13594
+ * 一轮播出的帧数。档位是播放时长桶除以帧间隔(40ms),和时长视角一一对应:
13595
+ * 「播了 10s」与「播了 250 帧」落在同一档。
13596
+ */
13597
+ const RTC_FRAME_COUNT_BUCKETS = [
13598
+ 0,
13599
+ 50,
13600
+ 125,
13601
+ 250,
13602
+ 375,
13603
+ 500,
13604
+ 750,
13605
+ 1500
13606
+ ];
13607
+ /**
13608
+ * 没能上屏的帧数(丢失/跳过/丢弃/过渡缺帧):与正常帧数差一个数量级,
13609
+ * 共用一组桶会让它们全挤在低位。档位是卡顿时长桶除以帧间隔(40ms),
13610
+ * 于是「卡了 320ms」和「丢了 8 帧」落在同一档,两个视角能直接对上。
13611
+ */
13612
+ const RTC_LOST_FRAME_BUCKETS = [
13613
+ 0,
13614
+ 1,
13615
+ 2,
13616
+ 4,
13617
+ 8,
13618
+ 16,
13619
+ 32,
13620
+ 64,
13621
+ 128,
13622
+ 256
13623
+ ];
13624
+ /**
13625
+ * 一轮里卡顿发生的次数。数的是次数不是帧,上面那套按帧间隔换算的档位对它没有意义。
13626
+ * 低位逐个分档、高位翻倍:一轮几次和一轮几十次是两种情况,都要看得出来。
13627
+ * 实测慢网络下一轮 35 次,因此高位必须留到三位数。
13628
+ */
13629
+ const RTC_STALL_COUNT_BUCKETS = [
13630
+ 0,
13631
+ 1,
13632
+ 2,
13633
+ 3,
13634
+ 4,
13635
+ 5,
13636
+ 10,
13637
+ 20,
13638
+ 40,
13639
+ 80,
13640
+ 160,
13641
+ 320
13642
+ ];
13643
+ const RTC_PERCENT_BUCKETS = [
13644
+ 0,
13645
+ 5,
13646
+ 10,
13647
+ 15,
13648
+ 20,
13649
+ 25,
13650
+ 30,
13651
+ 35,
13652
+ 40,
13653
+ 45,
13654
+ 50,
13655
+ 55,
13656
+ 60,
13657
+ 65,
13658
+ 70,
13659
+ 75,
13660
+ 80,
13661
+ 85,
13662
+ 90,
13663
+ 95,
13664
+ 100
13665
+ ];
13666
+ /** 一轮播放的时长,秒级量级。 */
13667
+ const RTC_PLAYBACK_DURATION_BUCKETS_MS = [
13668
+ 0,
13669
+ 2e3,
13670
+ 5e3,
13671
+ 1e4,
13672
+ 15e3,
13673
+ 2e4,
13674
+ 3e4,
13675
+ 6e4
13676
+ ];
13677
+ /**
13678
+ * 卡顿时长:一帧(40ms)起步逐档翻倍到 10240ms。用播放时长那组秒级的桶,
13679
+ * 绝大多数卡顿会挤进第一格。
13680
+ */
13681
+ const RTC_STALL_DURATION_BUCKETS_MS = [
13682
+ 0,
13683
+ 40,
13684
+ 80,
13685
+ 160,
13686
+ 320,
13687
+ 640,
13688
+ 1280,
13689
+ 2560,
13690
+ 5120,
13691
+ 10240
13692
+ ];
13693
+ /** metric 名 → 桶,供下面的 views 展开。 */
13694
+ const RTC_BUCKET_PROFILES = [
13695
+ ["rtc_playback_avg_fps", RTC_FPS_BUCKETS],
13696
+ ["rtc_playback_frame_count", RTC_FRAME_COUNT_BUCKETS],
13697
+ ["rtc_playback_skipped_frames", RTC_LOST_FRAME_BUCKETS],
13698
+ ["rtc_playback_tail_discarded", RTC_LOST_FRAME_BUCKETS],
13699
+ ["rtc_playback_stall_count", RTC_STALL_COUNT_BUCKETS],
13700
+ ["rtc_playback_start_transition_missing", RTC_LOST_FRAME_BUCKETS],
13701
+ ["rtc_playback_end_transition_missing", RTC_LOST_FRAME_BUCKETS],
13702
+ ["rtc_playback_skip_rate_pct", RTC_PERCENT_BUCKETS],
13703
+ ["rtc_playback_duration_ms", RTC_PLAYBACK_DURATION_BUCKETS_MS],
13704
+ ["rtc_playback_stall_total_ms", RTC_STALL_DURATION_BUCKETS_MS],
13705
+ ["rtc_playback_stall_max_ms", RTC_STALL_DURATION_BUCKETS_MS],
13706
+ ["rtc_transport_packets_lost", RTC_LOST_FRAME_BUCKETS],
13707
+ ["rtc_transport_packets_recovered", RTC_LOST_FRAME_BUCKETS],
13708
+ ["rtc_transport_packets_dropped", RTC_LOST_FRAME_BUCKETS],
13709
+ ["rtc_transport_packets_out_of_order", RTC_LOST_FRAME_BUCKETS]
13710
+ ];
13552
13711
  const METRIC_EXPORT_INTERVAL_MS = 1e4;
13553
13712
  let sdkVersion$2 = "1.0.0";
13554
13713
  let isInitialized$2 = false;
@@ -13594,7 +13753,13 @@ function initializeOtelMetrics(version, resourceAttrs) {
13594
13753
  type: AggregationType.EXPLICIT_BUCKET_HISTOGRAM,
13595
13754
  options: { boundaries: HTTP_NETWORK_BUCKETS_MS }
13596
13755
  }
13597
- }]
13756
+ }, ...RTC_BUCKET_PROFILES.map(([instrumentName, boundaries]) => ({
13757
+ instrumentName,
13758
+ aggregation: {
13759
+ type: AggregationType.EXPLICIT_BUCKET_HISTOGRAM,
13760
+ options: { boundaries: [...boundaries] }
13761
+ }
13762
+ }))]
13598
13763
  });
13599
13764
  metrics.setGlobalMeterProvider(meterProvider);
13600
13765
  isInitialized$2 = true;
@@ -14350,7 +14515,7 @@ function clientContextFields() {
14350
14515
  if (typeof document !== "undefined" && document.referrer) fields.referrer = document.referrer;
14351
14516
  if (typeof navigator !== "undefined") {
14352
14517
  if (navigator.userAgent) fields.user_agent = navigator.userAgent;
14353
- if (navigator.language) fields.language = navigator.language;
14518
+ if (navigator.language) fields.locale = navigator.language;
14354
14519
  }
14355
14520
  if (typeof screen !== "undefined") {
14356
14521
  if (screen.width) fields.screen_width = screen.width;
@@ -14950,7 +15115,7 @@ async function writeToLocalLog(message, level, extra = {}) {
14950
15115
  try {
14951
15116
  const { shouldPersist, sanitized } = sanitizeForLocalLog(message);
14952
15117
  if (!shouldPersist) return;
14953
- const { AvatarSDK } = await import("./AvatarSDK-RVj90oMR.js").then((n) => n.n);
15118
+ const { AvatarSDK } = await import("./AvatarSDK-DR8dNylh.js").then((n) => n.n);
14954
15119
  const version = AvatarSDK.version;
14955
15120
  const appId = idManager.getAppId();
14956
15121
  const userId = idManager.getUserId();
@@ -1,4 +1,4 @@
1
- import { mt as isDebugMode } from "./logger-C3fw-NWP.js";
1
+ import { mt as isDebugMode } from "./logger-fAU8oahT.js";
2
2
  //#region config/app-config.ts
3
3
  var GLOBAL_FLAME_CDN_BASE = "https://cdn.spatialwalk.cloud/public";
4
4
  var CN_FLAME_CDN_BASE = "https://cdn.spatialwalk.top/public";
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
- import { a as avatarViewRegistry, c as Message, d as BinaryReader, f as BinaryWriter, i as buildTraceparent, l as MessageType, o as AudioFormat, r as startPlaybackTrace, s as EgressType, t as AvatarSDK, u as TransportCompression } from "./AvatarSDK-CuejGi0J.js";
2
- import { At as RENDER_QUALITY_PARAMS, Ct as DEFAULT_REGION, Dt as FrameStarvationMode, Et as ErrorCode, Mt as TransitionType, Ot as LoadProgress, St as DEFAULT_OPUS_BITRATE, Tt as DrivingServiceMode, _t as AnimationType, b as recordMetric, bt as ConnectionState, c as logEvent, h as clockSync, ht as idManager, jt as RenderQuality, kt as LogLevel, l as logMetric, m as resolveMarks, p as monoTimestamp, t as logger, vt as AvatarError, wt as DEFAULT_REGION_REQUEST, xt as ConversationState, yt as AvatarState } from "./logger-C3fw-NWP.js";
3
- import { n as APP_CONFIG } from "./error-utils-PtNzUHiL.js";
4
- import { r as OggMuxer, t as OggPageSplitter } from "./OpusCodec-Bv4kzdt8.js";
5
- import { t as AvatarDownloader } from "./AvatarDownloader-C2JJVqKm.js";
1
+ import { a as avatarViewRegistry, c as Message, d as BinaryReader, f as BinaryWriter, i as buildTraceparent, l as MessageType, o as AudioFormat, r as startPlaybackTrace, s as EgressType, t as AvatarSDK, u as TransportCompression } from "./AvatarSDK-CnZqa_X4.js";
2
+ import { At as RENDER_QUALITY_PARAMS, Ct as DEFAULT_REGION, Dt as FrameStarvationMode, Et as ErrorCode, Mt as TransitionType, Ot as LoadProgress, St as DEFAULT_OPUS_BITRATE, Tt as DrivingServiceMode, _t as AnimationType, b as recordMetric, bt as ConnectionState, c as logEvent, h as clockSync, ht as idManager, jt as RenderQuality, kt as LogLevel, l as logMetric, m as resolveMarks, p as monoTimestamp, t as logger, vt as AvatarError, wt as DEFAULT_REGION_REQUEST, xt as ConversationState, yt as AvatarState } from "./logger-fAU8oahT.js";
3
+ import { n as APP_CONFIG } from "./error-utils-CqKOrHrY.js";
4
+ import { r as OggMuxer, t as OggPageSplitter } from "./OpusCodec-D9DcUV65.js";
5
+ import { t as AvatarDownloader } from "./AvatarDownloader-Dfi7wtgQ.js";
6
6
  //#region core/Avatar.ts
7
7
  var Avatar = class {
8
8
  id;
@@ -309,8 +309,8 @@ var AnimationPlayer = class AnimationPlayer {
309
309
  */
310
310
  async createAndInitializeStreamingPlayer() {
311
311
  if (this.streamingPlayer) return;
312
- const { StreamingAudioPlayer } = await import("./StreamingAudioPlayer-DmotFnXu.js");
313
- const { AvatarSDK } = await import("./AvatarSDK-CuejGi0J.js").then((n) => n.n);
312
+ const { StreamingAudioPlayer } = await import("./StreamingAudioPlayer-D4q7c1U0.js");
313
+ const { AvatarSDK } = await import("./AvatarSDK-CnZqa_X4.js").then((n) => n.n);
314
314
  const audioFormat = AvatarSDK.getAudioFormat();
315
315
  this.streamingPlayer = new StreamingAudioPlayer({
316
316
  sampleRate: audioFormat.sampleRate,
@@ -1281,7 +1281,7 @@ var AnimationWebSocketClient = class extends EventEmitter {
1281
1281
  return;
1282
1282
  }
1283
1283
  try {
1284
- const { OpusEncoderProxy } = await import("./OpusEncoderProxy-_AWpY7N6.js");
1284
+ const { OpusEncoderProxy } = await import("./OpusEncoderProxy-9YIZ7nIt.js");
1285
1285
  const bitrate = opusBitrate ?? 48e3;
1286
1286
  this.opusEncoder = await OpusEncoderProxy.create(sampleRate, bitrate);
1287
1287
  this.uplinkIsOpus = true;
@@ -2628,7 +2628,7 @@ var AvatarController = class {
2628
2628
  const { inputAudioFormat } = AvatarSDK.getAudioFormat();
2629
2629
  if (inputAudioFormat !== "opus" || this.inputOpusDecoderProxy) return;
2630
2630
  try {
2631
- const { OpusDecoderProxy } = await import("./OpusDecoderProxy-BTWRku-I.js");
2631
+ const { OpusDecoderProxy } = await import("./OpusDecoderProxy-Ar_dFXRB.js");
2632
2632
  this.inputOpusDecoderProxy = await OpusDecoderProxy.create();
2633
2633
  this.inputDecodeChain = Promise.resolve();
2634
2634
  } catch (error) {
@@ -2904,7 +2904,7 @@ var AvatarController = class {
2904
2904
  isLast
2905
2905
  });
2906
2906
  this.notifyConversationState(AvatarState.active);
2907
- if (!this.isPlaying && !this.isStartingPlayback && this.currentKeyframes.length > 0) this.startStreamingPlayback().catch((error) => {
2907
+ if (!this.isPlaying && !this.isStartingPlayback) this.startStreamingPlayback().catch((error) => {
2908
2908
  this.isStartingPlayback = false;
2909
2909
  logger.error("[AvatarController] Failed to start playback from audio arrival:", error instanceof Error ? error.message : String(error));
2910
2910
  });
@@ -3016,7 +3016,7 @@ var AvatarController = class {
3016
3016
  const arrayIndex = Math.round(audioTime * 25) - this.keyframesOffset;
3017
3017
  if (arrayIndex >= 0 && arrayIndex < this.currentKeyframes.length) this.resumeAudioFromStarvation();
3018
3018
  }
3019
- if (!this.isPlaying && !this.isStartingPlayback && this.pendingAudioChunks.length > 0 && this.currentKeyframes.length > 0) this.startStreamingPlayback().catch((error) => {
3019
+ if (!this.isPlaying && !this.isStartingPlayback) this.startStreamingPlayback().catch((error) => {
3020
3020
  this.isStartingPlayback = false;
3021
3021
  logger.error("[AvatarController] Failed to auto-start playback:", error);
3022
3022
  this.onError?.(new AvatarError("Failed to start playback", ErrorCode.playbackStartFailed));
@@ -3263,9 +3263,12 @@ var AvatarController = class {
3263
3263
  }
3264
3264
  if (this.isStartingPlayback) return;
3265
3265
  this.isStartingPlayback = true;
3266
+ if (this.pendingAudioChunks.length === 0) {
3267
+ this.isStartingPlayback = false;
3268
+ return;
3269
+ }
3266
3270
  if (!this.isFallbackMode && (!this.currentKeyframes || this.currentKeyframes.length === 0)) {
3267
3271
  this.isStartingPlayback = false;
3268
- logger.warn("[AvatarController] No animation data to play");
3269
3272
  return;
3270
3273
  }
3271
3274
  try {
@@ -3642,7 +3645,7 @@ var AvatarController = class {
3642
3645
  isLast
3643
3646
  });
3644
3647
  if (this.isFallbackMode && !this.isPlaying && !this.isStartingPlayback) this.startFallbackPlayback();
3645
- else if (!this.isFallbackMode && !this.isPlaying && !this.isStartingPlayback && this.currentKeyframes.length > 0) this.startStreamingPlayback().catch((error) => {
3648
+ else if (!this.isFallbackMode && !this.isPlaying && !this.isStartingPlayback) this.startStreamingPlayback().catch((error) => {
3646
3649
  this.isStartingPlayback = false;
3647
3650
  logger.error("[AvatarController] Failed to start playback from audio arrival:", error instanceof Error ? error.message : String(error));
3648
3651
  });
@@ -3838,7 +3841,7 @@ var AvatarManager = class AvatarManager {
3838
3841
  } else {
3839
3842
  logger.log(`[AvatarManager] Avatar ${id} cache invalid: updatedAt=${cachedUpdatedAt}->${newUpdatedAt}, modelType=${cachedModelType}->${requestedModelType}, reloading...`);
3840
3843
  this.avatarCache.delete(id);
3841
- const { PwaCacheManager } = await import("./pwa-cache-manager-D3nj4sd5.js").then((n) => n.n);
3844
+ const { PwaCacheManager } = await import("./pwa-cache-manager-CwXaM3xR.js").then((n) => n.n);
3842
3845
  await PwaCacheManager.clearCharacterCache(id);
3843
3846
  }
3844
3847
  }
@@ -6375,7 +6378,7 @@ var AvatarView = class {
6375
6378
  */
6376
6379
  const scheduleNextTick = () => {
6377
6380
  let delay = frameIntervalMs;
6378
- if (this.isConversationActive && !this.avatarController.getIsFallbackMode()) {
6381
+ if (this.avatarController.getIsPlaying() && !this.avatarController.getIsFallbackMode()) {
6379
6382
  const audioTime = this.avatarController.getAudioTime();
6380
6383
  if (audioTime > 0) {
6381
6384
  const remainingMs = ((Math.floor(audioTime * fps + 1e-6) + 1) / fps - audioTime) * 1e3;
@@ -6416,31 +6419,27 @@ var AvatarView = class {
6416
6419
  scheduleNextTick();
6417
6420
  return;
6418
6421
  }
6419
- if (this.isConversationActive && !this.avatarController.getIsFallbackMode()) {
6422
+ if (this.avatarController.getIsPlaying() && !this.avatarController.getIsFallbackMode()) {
6420
6423
  const audioTime = this.avatarController.getAudioTime();
6421
- if (audioTime > 0) {
6422
- const frameIndex = Math.max(0, Math.floor(audioTime * fps + 1e-6));
6423
- if (frameIndex > this.lastRenderedFrameIndex) {
6424
- this.lastRenderedFrameIndex = frameIndex;
6425
- this.avatarController.monitorPlaybackTick(audioTime, frameIndex);
6426
- const keyframes = this.avatarController.getKeyframes();
6427
- let arrayIndex = frameIndex - this.avatarController.getKeyframesOffset();
6428
- if (arrayIndex < 0) arrayIndex = 0;
6429
- if (arrayIndex >= keyframes.length) arrayIndex = keyframes.length - 1;
6430
- if (arrayIndex >= 0 && arrayIndex < keyframes.length) {
6431
- const currentFrame = keyframes[arrayIndex];
6432
- this.currentFrame = currentFrame;
6433
- const wasmParams = convertProtoFlameToWasmParams(currentFrame);
6434
- computeInFlight = true;
6435
- avatarCore.computeFrameFlatFromParams(wasmParams, this.characterHandle ?? void 0).then((splatData) => {
6436
- if (splatData && !this.isPureRenderingMode) this.doRender(splatData);
6437
- }).catch((e) => logger.warn("[AvatarView] Conversation frame compute failed:", e instanceof Error ? e.message : String(e))).finally(() => {
6438
- computeInFlight = false;
6439
- });
6440
- }
6424
+ const frameIndex = Math.max(0, Math.floor(audioTime * fps + 1e-6));
6425
+ if (frameIndex > this.lastRenderedFrameIndex) {
6426
+ this.lastRenderedFrameIndex = frameIndex;
6427
+ this.avatarController.monitorPlaybackTick(audioTime, frameIndex);
6428
+ const keyframes = this.avatarController.getKeyframes();
6429
+ let arrayIndex = frameIndex - this.avatarController.getKeyframesOffset();
6430
+ if (arrayIndex < 0) arrayIndex = 0;
6431
+ if (arrayIndex >= keyframes.length) arrayIndex = keyframes.length - 1;
6432
+ if (arrayIndex >= 0 && arrayIndex < keyframes.length) {
6433
+ const currentFrame = keyframes[arrayIndex];
6434
+ this.currentFrame = currentFrame;
6435
+ const wasmParams = convertProtoFlameToWasmParams(currentFrame);
6436
+ computeInFlight = true;
6437
+ avatarCore.computeFrameFlatFromParams(wasmParams, this.characterHandle ?? void 0).then((splatData) => {
6438
+ if (splatData && !this.isPureRenderingMode) this.doRender(splatData);
6439
+ }).catch((e) => logger.warn("[AvatarView] Conversation frame compute failed:", e instanceof Error ? e.message : String(e))).finally(() => {
6440
+ computeInFlight = false;
6441
+ });
6441
6442
  }
6442
- scheduleNextTick();
6443
- return;
6444
6443
  }
6445
6444
  scheduleNextTick();
6446
6445
  return;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Internal telemetry surface for the companion RTC SDK.
3
+ *
4
+ * `@spatius/avatarkit-rtc` reports into the same OpenObserve backend and shares
5
+ * this SDK's OTel providers, so its spans must sit on the same calibrated
6
+ * timeline. Without that, a client whose wall clock is off puts RTC spans at a
7
+ * time that does not line up with the server-side records they need to be read
8
+ * against.
9
+ *
10
+ * Deliberately NOT re-exported from the package root: this is a bridge between
11
+ * two first-party packages, not API for integrators. It exposes conversion only
12
+ * — nothing here can alter the clock baseline.
13
+ *
14
+ * NOTE: nothing in this file may be tagged `@internal`. The dts plugin runs with
15
+ * `stripInternal: true`, which erases such declarations from the emitted `.d.ts`
16
+ * — the entry would still export both functions at runtime while shipping an
17
+ * empty `export {}` type file, leaving the RTC package with no types.
18
+ *
19
+ * @packageDocumentation
20
+ */
21
+ /**
22
+ * Convert a `performance.now()` reading taken earlier into a timeline
23
+ * timestamp (epoch ms), preferring the server-calibrated baseline and falling
24
+ * back to the local clock until calibration completes.
25
+ *
26
+ * Collect marks on the monotonic clock and convert at report time: the wall
27
+ * clock and `performance.now()` drift apart while the main thread is blocked,
28
+ * and calibration may not have finished when the mark was taken.
29
+ *
30
+ * @param mono - the `performance.now()` value recorded at collection time
31
+ */
32
+ export declare function resolveMonoTimestamp(mono: number): number;
33
+ /**
34
+ * Whether clock calibration against the backend has completed. Timestamps
35
+ * resolve either way; this only reports whether they are server-aligned yet.
36
+ */
37
+ export declare function isClockCalibrated(): boolean;
@@ -0,0 +1,45 @@
1
+ import { h as clockSync } from "./logger-fAU8oahT.js";
2
+ //#region internal-telemetry.ts
3
+ /**
4
+ * Internal telemetry surface for the companion RTC SDK.
5
+ *
6
+ * `@spatius/avatarkit-rtc` reports into the same OpenObserve backend and shares
7
+ * this SDK's OTel providers, so its spans must sit on the same calibrated
8
+ * timeline. Without that, a client whose wall clock is off puts RTC spans at a
9
+ * time that does not line up with the server-side records they need to be read
10
+ * against.
11
+ *
12
+ * Deliberately NOT re-exported from the package root: this is a bridge between
13
+ * two first-party packages, not API for integrators. It exposes conversion only
14
+ * — nothing here can alter the clock baseline.
15
+ *
16
+ * NOTE: nothing in this file may be tagged `@internal`. The dts plugin runs with
17
+ * `stripInternal: true`, which erases such declarations from the emitted `.d.ts`
18
+ * — the entry would still export both functions at runtime while shipping an
19
+ * empty `export {}` type file, leaving the RTC package with no types.
20
+ *
21
+ * @packageDocumentation
22
+ */
23
+ /**
24
+ * Convert a `performance.now()` reading taken earlier into a timeline
25
+ * timestamp (epoch ms), preferring the server-calibrated baseline and falling
26
+ * back to the local clock until calibration completes.
27
+ *
28
+ * Collect marks on the monotonic clock and convert at report time: the wall
29
+ * clock and `performance.now()` drift apart while the main thread is blocked,
30
+ * and calibration may not have finished when the mark was taken.
31
+ *
32
+ * @param mono - the `performance.now()` value recorded at collection time
33
+ */
34
+ function resolveMonoTimestamp(mono) {
35
+ return clockSync.resolveMono(mono);
36
+ }
37
+ /**
38
+ * Whether clock calibration against the backend has completed. Timestamps
39
+ * resolve either way; this only reports whether they are server-aligned yet.
40
+ */
41
+ function isClockCalibrated() {
42
+ return clockSync.isReady();
43
+ }
44
+ //#endregion
45
+ export { isClockCalibrated, resolveMonoTimestamp };
@@ -13624,6 +13624,165 @@ var HTTP_NETWORK_BUCKETS_MS = [
13624
13624
  4e3,
13625
13625
  5e3
13626
13626
  ];
13627
+ /**
13628
+ * RTC playback 指标的桶。默认桶(0/5/10/25/50/…/10000)对这批指标毫无分辨率:
13629
+ * 帧率只可能落在 0~25,缺帧数和卡顿次数几乎全部挤在第一个桶里,分位数因此毫无意义。
13630
+ * 桶按各指标的实际值域给:
13631
+ *
13632
+ * - 帧率:每帧一个桶。25fps 与 21fps 的观感差别正是要看的,5 档分级会把两者归成一类。
13633
+ * - 帧数:正常轮次对应播放时长桶、没上屏的帧对应卡顿时长桶,都按帧间隔换算。
13634
+ * - 卡顿次数:数的是次数不是帧,自成一组。
13635
+ * - 百分比:每 5% 一档,0~100。
13636
+ * - 时长:分两组——整轮播放是秒级,单次卡顿是一帧起步的毫秒级。
13637
+ *
13638
+ * 这些 metric 由 @spatius/avatarkit-rtc 发出(meter 名 spatius-avatarkit-rtc),
13639
+ * 但 view 只能配在创建 MeterProvider 的这一侧,所以桶定义留在这里。
13640
+ */
13641
+ var RTC_FPS_BUCKETS = [
13642
+ 0,
13643
+ 1,
13644
+ 2,
13645
+ 3,
13646
+ 4,
13647
+ 5,
13648
+ 6,
13649
+ 7,
13650
+ 8,
13651
+ 9,
13652
+ 10,
13653
+ 11,
13654
+ 12,
13655
+ 13,
13656
+ 14,
13657
+ 15,
13658
+ 16,
13659
+ 17,
13660
+ 18,
13661
+ 19,
13662
+ 20,
13663
+ 21,
13664
+ 22,
13665
+ 23,
13666
+ 24
13667
+ ];
13668
+ /**
13669
+ * 一轮播出的帧数。档位是播放时长桶除以帧间隔(40ms),和时长视角一一对应:
13670
+ * 「播了 10s」与「播了 250 帧」落在同一档。
13671
+ */
13672
+ var RTC_FRAME_COUNT_BUCKETS = [
13673
+ 0,
13674
+ 50,
13675
+ 125,
13676
+ 250,
13677
+ 375,
13678
+ 500,
13679
+ 750,
13680
+ 1500
13681
+ ];
13682
+ /**
13683
+ * 没能上屏的帧数(丢失/跳过/丢弃/过渡缺帧):与正常帧数差一个数量级,
13684
+ * 共用一组桶会让它们全挤在低位。档位是卡顿时长桶除以帧间隔(40ms),
13685
+ * 于是「卡了 320ms」和「丢了 8 帧」落在同一档,两个视角能直接对上。
13686
+ */
13687
+ var RTC_LOST_FRAME_BUCKETS = [
13688
+ 0,
13689
+ 1,
13690
+ 2,
13691
+ 4,
13692
+ 8,
13693
+ 16,
13694
+ 32,
13695
+ 64,
13696
+ 128,
13697
+ 256
13698
+ ];
13699
+ /**
13700
+ * 一轮里卡顿发生的次数。数的是次数不是帧,上面那套按帧间隔换算的档位对它没有意义。
13701
+ * 低位逐个分档、高位翻倍:一轮几次和一轮几十次是两种情况,都要看得出来。
13702
+ * 实测慢网络下一轮 35 次,因此高位必须留到三位数。
13703
+ */
13704
+ var RTC_STALL_COUNT_BUCKETS = [
13705
+ 0,
13706
+ 1,
13707
+ 2,
13708
+ 3,
13709
+ 4,
13710
+ 5,
13711
+ 10,
13712
+ 20,
13713
+ 40,
13714
+ 80,
13715
+ 160,
13716
+ 320
13717
+ ];
13718
+ var RTC_PERCENT_BUCKETS = [
13719
+ 0,
13720
+ 5,
13721
+ 10,
13722
+ 15,
13723
+ 20,
13724
+ 25,
13725
+ 30,
13726
+ 35,
13727
+ 40,
13728
+ 45,
13729
+ 50,
13730
+ 55,
13731
+ 60,
13732
+ 65,
13733
+ 70,
13734
+ 75,
13735
+ 80,
13736
+ 85,
13737
+ 90,
13738
+ 95,
13739
+ 100
13740
+ ];
13741
+ /** 一轮播放的时长,秒级量级。 */
13742
+ var RTC_PLAYBACK_DURATION_BUCKETS_MS = [
13743
+ 0,
13744
+ 2e3,
13745
+ 5e3,
13746
+ 1e4,
13747
+ 15e3,
13748
+ 2e4,
13749
+ 3e4,
13750
+ 6e4
13751
+ ];
13752
+ /**
13753
+ * 卡顿时长:一帧(40ms)起步逐档翻倍到 10240ms。用播放时长那组秒级的桶,
13754
+ * 绝大多数卡顿会挤进第一格。
13755
+ */
13756
+ var RTC_STALL_DURATION_BUCKETS_MS = [
13757
+ 0,
13758
+ 40,
13759
+ 80,
13760
+ 160,
13761
+ 320,
13762
+ 640,
13763
+ 1280,
13764
+ 2560,
13765
+ 5120,
13766
+ 10240
13767
+ ];
13768
+ /** metric 名 → 桶,供下面的 views 展开。 */
13769
+ var RTC_BUCKET_PROFILES = [
13770
+ ["rtc_playback_avg_fps", RTC_FPS_BUCKETS],
13771
+ ["rtc_playback_frame_count", RTC_FRAME_COUNT_BUCKETS],
13772
+ ["rtc_playback_skipped_frames", RTC_LOST_FRAME_BUCKETS],
13773
+ ["rtc_playback_tail_discarded", RTC_LOST_FRAME_BUCKETS],
13774
+ ["rtc_playback_stall_count", RTC_STALL_COUNT_BUCKETS],
13775
+ ["rtc_playback_start_transition_missing", RTC_LOST_FRAME_BUCKETS],
13776
+ ["rtc_playback_end_transition_missing", RTC_LOST_FRAME_BUCKETS],
13777
+ ["rtc_playback_skip_rate_pct", RTC_PERCENT_BUCKETS],
13778
+ ["rtc_playback_duration_ms", RTC_PLAYBACK_DURATION_BUCKETS_MS],
13779
+ ["rtc_playback_stall_total_ms", RTC_STALL_DURATION_BUCKETS_MS],
13780
+ ["rtc_playback_stall_max_ms", RTC_STALL_DURATION_BUCKETS_MS],
13781
+ ["rtc_transport_packets_lost", RTC_LOST_FRAME_BUCKETS],
13782
+ ["rtc_transport_packets_recovered", RTC_LOST_FRAME_BUCKETS],
13783
+ ["rtc_transport_packets_dropped", RTC_LOST_FRAME_BUCKETS],
13784
+ ["rtc_transport_packets_out_of_order", RTC_LOST_FRAME_BUCKETS]
13785
+ ];
13627
13786
  var METRIC_EXPORT_INTERVAL_MS = 1e4;
13628
13787
  var sdkVersion$2 = "1.0.0";
13629
13788
  var isInitialized$2 = false;
@@ -13670,7 +13829,13 @@ function initializeOtelMetrics(version, resourceAttrs) {
13670
13829
  type: AggregationType.EXPLICIT_BUCKET_HISTOGRAM,
13671
13830
  options: { boundaries: HTTP_NETWORK_BUCKETS_MS }
13672
13831
  }
13673
- }]
13832
+ }, ...RTC_BUCKET_PROFILES.map(([instrumentName, boundaries]) => ({
13833
+ instrumentName,
13834
+ aggregation: {
13835
+ type: AggregationType.EXPLICIT_BUCKET_HISTOGRAM,
13836
+ options: { boundaries: [...boundaries] }
13837
+ }
13838
+ }))]
13674
13839
  });
13675
13840
  metrics.setGlobalMeterProvider(meterProvider);
13676
13841
  isInitialized$2 = true;
@@ -14438,7 +14603,7 @@ function clientContextFields() {
14438
14603
  if (typeof document !== "undefined" && document.referrer) fields.referrer = document.referrer;
14439
14604
  if (typeof navigator !== "undefined") {
14440
14605
  if (navigator.userAgent) fields.user_agent = navigator.userAgent;
14441
- if (navigator.language) fields.language = navigator.language;
14606
+ if (navigator.language) fields.locale = navigator.language;
14442
14607
  }
14443
14608
  if (typeof screen !== "undefined") {
14444
14609
  if (screen.width) fields.screen_width = screen.width;
@@ -15038,7 +15203,7 @@ async function writeToLocalLog(message, level, extra = {}) {
15038
15203
  try {
15039
15204
  const { shouldPersist, sanitized } = sanitizeForLocalLog(message);
15040
15205
  if (!shouldPersist) return;
15041
- const { AvatarSDK } = await import("./AvatarSDK-CuejGi0J.js").then((n) => n.n);
15206
+ const { AvatarSDK } = await import("./AvatarSDK-CnZqa_X4.js").then((n) => n.n);
15042
15207
  const version = AvatarSDK.version;
15043
15208
  const appId = idManager.getAppId();
15044
15209
  const userId = idManager.getUserId();
@@ -1,5 +1,5 @@
1
1
  import { n as __exportAll } from "./rolldown-runtime-B-1-B7_t.js";
2
- import { t as logger } from "./logger-C3fw-NWP.js";
2
+ import { t as logger } from "./logger-fAU8oahT.js";
3
3
  //#region utils/pwa-cache-manager.ts
4
4
  /**
5
5
  * PWA Cache Manager
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "@spatius/avatarkit",
3
3
  "type": "module",
4
- "version": "1.3.1-beta.4",
4
+ "version": "1.3.1-beta.6",
5
5
  "packageManager": "pnpm@10.18.2",
6
- "description": "AvatarKit SDK - Real-time Avatar Rendering SDK for Web",
6
+ "description": "AvatarKit real-time, audio-driven avatar rendering SDK for Web.",
7
+ "homepage": "https://spatius.ai/",
7
8
  "author": "AvatarKit Team",
8
9
  "license": "UNLICENSED",
9
10
  "keywords": [
@@ -26,6 +27,10 @@
26
27
  "types": "./next.d.ts",
27
28
  "import": "./next.js"
28
29
  },
30
+ "./internal-telemetry": {
31
+ "types": "./dist/internal-telemetry.d.ts",
32
+ "import": "./dist/internal-telemetry.js"
33
+ },
29
34
  "./*": {
30
35
  "types": "./dist/*.d.ts",
31
36
  "import": "./dist/*.js"