@camstack/addon-pipeline 1.2.57 → 1.2.58

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.
@@ -1851,15 +1851,15 @@ async function readGopRange(file, args) {
1851
1851
  bytesRead += chunk.length;
1852
1852
  return chunk;
1853
1853
  };
1854
- const parsed = await parseTail(file, read);
1855
- if (parsed === null) return null;
1856
- const { tail, index } = parsed;
1854
+ const parsed = args.seededIndex === void 0 ? await parseTail(file, read) : null;
1855
+ if (args.seededIndex === void 0 && parsed === null) return null;
1856
+ const index = args.seededIndex ?? parsed.index;
1857
1857
  const firstMoof = index.samples[0]?.moofOffset ?? 0;
1858
1858
  if (firstMoof <= 0 || firstMoof >= file.size) return null;
1859
1859
  const head = await read(0, firstMoof);
1860
1860
  const init = parseInitInfo(head);
1861
1861
  if (init === null) return null;
1862
- const videoIndex = index.trackId === init.videoTrackId ? index : reparseTail(tail, file.size, init.videoTrackId);
1862
+ const videoIndex = index.trackId === init.videoTrackId ? index : parsed === null ? null : reparseTail(parsed.tail, file.size, init.videoTrackId);
1863
1863
  if (videoIndex === null) return null;
1864
1864
  const { start, end, sampleIndex } = fragmentRangeFor(videoIndex, Math.max(0, args.epochMs - args.segmentStartMs) / 1e3 * init.videoTimescale);
1865
1865
  if (start <= 0 || end <= start || end > file.size) return null;
@@ -2668,7 +2668,8 @@ function buildRecordingProvider(deps) {
2668
2668
  const gop = await readGopRange(file, {
2669
2669
  segmentStartMs: seg.startMs,
2670
2670
  segmentDurMs: seg.durMs,
2671
- epochMs
2671
+ epochMs,
2672
+ seededIndex: deps.mfraFor?.(deviceId, profile, startMs)
2672
2673
  });
2673
2674
  if (gop !== null) return {
2674
2675
  data: gop.data,
@@ -5437,6 +5438,7 @@ var RecorderV2Addon = class extends require_dist.BaseAddon {
5437
5438
  capacity: (root) => this.locationCapacity(root),
5438
5439
  hydrateDevice: (deviceId, locations) => hydrateDeviceFromStorage(this.ctx.api, this.index, deviceId, locations, this.ctx.logger),
5439
5440
  calendar: this.calendar,
5441
+ mfraFor: (deviceId, profile, startMs) => this.mfraTables.get(deviceId, profile, startMs),
5440
5442
  hydrateWindow: (deviceId, fromMs, toMs) => hydrateWindowFromStorage(this.index, deviceId, fromMs, toMs, this.resolvedLocations, this.ctx.logger),
5441
5443
  onConfigChanged: (deviceId) => this.controller?.onConfigChanged(deviceId) ?? Promise.resolve(),
5442
5444
  dataDir: this.ctx.dataDir,
@@ -1849,15 +1849,15 @@ async function readGopRange(file, args) {
1849
1849
  bytesRead += chunk.length;
1850
1850
  return chunk;
1851
1851
  };
1852
- const parsed = await parseTail(file, read);
1853
- if (parsed === null) return null;
1854
- const { tail, index } = parsed;
1852
+ const parsed = args.seededIndex === void 0 ? await parseTail(file, read) : null;
1853
+ if (args.seededIndex === void 0 && parsed === null) return null;
1854
+ const index = args.seededIndex ?? parsed.index;
1855
1855
  const firstMoof = index.samples[0]?.moofOffset ?? 0;
1856
1856
  if (firstMoof <= 0 || firstMoof >= file.size) return null;
1857
1857
  const head = await read(0, firstMoof);
1858
1858
  const init = parseInitInfo(head);
1859
1859
  if (init === null) return null;
1860
- const videoIndex = index.trackId === init.videoTrackId ? index : reparseTail(tail, file.size, init.videoTrackId);
1860
+ const videoIndex = index.trackId === init.videoTrackId ? index : parsed === null ? null : reparseTail(parsed.tail, file.size, init.videoTrackId);
1861
1861
  if (videoIndex === null) return null;
1862
1862
  const { start, end, sampleIndex } = fragmentRangeFor(videoIndex, Math.max(0, args.epochMs - args.segmentStartMs) / 1e3 * init.videoTimescale);
1863
1863
  if (start <= 0 || end <= start || end > file.size) return null;
@@ -2666,7 +2666,8 @@ function buildRecordingProvider(deps) {
2666
2666
  const gop = await readGopRange(file, {
2667
2667
  segmentStartMs: seg.startMs,
2668
2668
  segmentDurMs: seg.durMs,
2669
- epochMs
2669
+ epochMs,
2670
+ seededIndex: deps.mfraFor?.(deviceId, profile, startMs)
2670
2671
  });
2671
2672
  if (gop !== null) return {
2672
2673
  data: gop.data,
@@ -5435,6 +5436,7 @@ var RecorderV2Addon = class extends BaseAddon {
5435
5436
  capacity: (root) => this.locationCapacity(root),
5436
5437
  hydrateDevice: (deviceId, locations) => hydrateDeviceFromStorage(this.ctx.api, this.index, deviceId, locations, this.ctx.logger),
5437
5438
  calendar: this.calendar,
5439
+ mfraFor: (deviceId, profile, startMs) => this.mfraTables.get(deviceId, profile, startMs),
5438
5440
  hydrateWindow: (deviceId, fromMs, toMs) => hydrateWindowFromStorage(this.index, deviceId, fromMs, toMs, this.resolvedLocations, this.ctx.logger),
5439
5441
  onConfigChanged: (deviceId) => this.controller?.onConfigChanged(deviceId) ?? Promise.resolve(),
5440
5442
  dataDir: this.ctx.dataDir,
@@ -22426,13 +22426,7 @@ var RecordedFeeder = class {
22426
22426
  const loadStartedAt = performance.now();
22427
22427
  let prefixFed = false;
22428
22428
  let gopFirst = false;
22429
- const fullLoad = this.loadAus(loc.startMs, this.rate !== 0, this.deps.readGop ? void 0 : (video) => {
22430
- if (this.disposed || token !== this.seekToken) return;
22431
- this.feedPrefix(loc, video, landMs);
22432
- prefixFed = true;
22433
- firstFrameMs = performance.now() - seekStartedAt;
22434
- });
22435
- fullLoad.catch(() => {});
22429
+ let stateAnnounced = false;
22436
22430
  if (this.deps.readGop) {
22437
22431
  const cached = this.scrubCache.covering(this.deps.profile, landMs);
22438
22432
  let fragment;
@@ -22454,7 +22448,18 @@ var RecordedFeeder = class {
22454
22448
  prefixFed = true;
22455
22449
  gopFirst = true;
22456
22450
  firstFrameMs = performance.now() - seekStartedAt;
22451
+ this.deps.onState(this.rate === 0 ? "paused" : "playing");
22452
+ this.deps.onPosition(this.cursorMs);
22453
+ this.startPositionReports();
22454
+ stateAnnounced = true;
22457
22455
  }
22456
+ const fullLoad = this.loadAus(loc.startMs, this.rate !== 0, this.deps.readGop ? void 0 : (video) => {
22457
+ if (this.disposed || token !== this.seekToken) return;
22458
+ this.feedPrefix(loc, video, landMs);
22459
+ prefixFed = true;
22460
+ firstFrameMs = performance.now() - seekStartedAt;
22461
+ });
22462
+ fullLoad.catch(() => {});
22458
22463
  const loaded = await fullLoad;
22459
22464
  loadMs = performance.now() - loadStartedAt;
22460
22465
  if (this.disposed || token !== this.seekToken || loaded === null) return;
@@ -22478,15 +22483,19 @@ var RecordedFeeder = class {
22478
22483
  }
22479
22484
  }
22480
22485
  if (this.rate === 0) {
22481
- this.deps.onState("paused");
22482
- this.deps.onPosition(this.cursorMs);
22483
- this.startPositionReports();
22486
+ if (!stateAnnounced) {
22487
+ this.deps.onState("paused");
22488
+ this.deps.onPosition(this.cursorMs);
22489
+ this.startPositionReports();
22490
+ }
22484
22491
  this.logSeekReady(epochMs, seekStartedAt, locateMs, travelMs, loadMs, firstFrameMs, "paused");
22485
22492
  return;
22486
22493
  }
22487
- this.deps.onState("playing");
22488
- this.deps.onPosition(this.cursorMs);
22489
- this.startPositionReports();
22494
+ if (!stateAnnounced) {
22495
+ this.deps.onState("playing");
22496
+ this.deps.onPosition(this.cursorMs);
22497
+ this.startPositionReports();
22498
+ }
22490
22499
  this.logSeekReady(epochMs, seekStartedAt, locateMs, travelMs, loadMs, firstFrameMs, "playing");
22491
22500
  const firstFullAu = loaded.video[0];
22492
22501
  const resumeAfterPtsMs = gopFirst ? firstFullAu ? firstFullAu.ptsMs + Math.max(0, this.cursorMs - loc.startMs) : null : this.lastFedVideoIdx >= 0 ? loaded.video[this.lastFedVideoIdx]?.ptsMs ?? null : null;
@@ -22420,13 +22420,7 @@ var RecordedFeeder = class {
22420
22420
  const loadStartedAt = performance.now();
22421
22421
  let prefixFed = false;
22422
22422
  let gopFirst = false;
22423
- const fullLoad = this.loadAus(loc.startMs, this.rate !== 0, this.deps.readGop ? void 0 : (video) => {
22424
- if (this.disposed || token !== this.seekToken) return;
22425
- this.feedPrefix(loc, video, landMs);
22426
- prefixFed = true;
22427
- firstFrameMs = performance.now() - seekStartedAt;
22428
- });
22429
- fullLoad.catch(() => {});
22423
+ let stateAnnounced = false;
22430
22424
  if (this.deps.readGop) {
22431
22425
  const cached = this.scrubCache.covering(this.deps.profile, landMs);
22432
22426
  let fragment;
@@ -22448,7 +22442,18 @@ var RecordedFeeder = class {
22448
22442
  prefixFed = true;
22449
22443
  gopFirst = true;
22450
22444
  firstFrameMs = performance.now() - seekStartedAt;
22445
+ this.deps.onState(this.rate === 0 ? "paused" : "playing");
22446
+ this.deps.onPosition(this.cursorMs);
22447
+ this.startPositionReports();
22448
+ stateAnnounced = true;
22451
22449
  }
22450
+ const fullLoad = this.loadAus(loc.startMs, this.rate !== 0, this.deps.readGop ? void 0 : (video) => {
22451
+ if (this.disposed || token !== this.seekToken) return;
22452
+ this.feedPrefix(loc, video, landMs);
22453
+ prefixFed = true;
22454
+ firstFrameMs = performance.now() - seekStartedAt;
22455
+ });
22456
+ fullLoad.catch(() => {});
22452
22457
  const loaded = await fullLoad;
22453
22458
  loadMs = performance.now() - loadStartedAt;
22454
22459
  if (this.disposed || token !== this.seekToken || loaded === null) return;
@@ -22472,15 +22477,19 @@ var RecordedFeeder = class {
22472
22477
  }
22473
22478
  }
22474
22479
  if (this.rate === 0) {
22475
- this.deps.onState("paused");
22476
- this.deps.onPosition(this.cursorMs);
22477
- this.startPositionReports();
22480
+ if (!stateAnnounced) {
22481
+ this.deps.onState("paused");
22482
+ this.deps.onPosition(this.cursorMs);
22483
+ this.startPositionReports();
22484
+ }
22478
22485
  this.logSeekReady(epochMs, seekStartedAt, locateMs, travelMs, loadMs, firstFrameMs, "paused");
22479
22486
  return;
22480
22487
  }
22481
- this.deps.onState("playing");
22482
- this.deps.onPosition(this.cursorMs);
22483
- this.startPositionReports();
22488
+ if (!stateAnnounced) {
22489
+ this.deps.onState("playing");
22490
+ this.deps.onPosition(this.cursorMs);
22491
+ this.startPositionReports();
22492
+ }
22484
22493
  this.logSeekReady(epochMs, seekStartedAt, locateMs, travelMs, loadMs, firstFrameMs, "playing");
22485
22494
  const firstFullAu = loaded.video[0];
22486
22495
  const resumeAfterPtsMs = gopFirst ? firstFullAu ? firstFullAu.ptsMs + Math.max(0, this.cursorMs - loc.startMs) : null : this.lastFedVideoIdx >= 0 ? loaded.video[this.lastFedVideoIdx]?.ptsMs ?? null : null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-pipeline",
3
- "version": "1.2.57",
3
+ "version": "1.2.58",
4
4
  "description": "Pipeline bundle — runner, detection, motion, audio + stream broker. Multi-entry npm package shipping pipeline addons under a single bundle.",
5
5
  "keywords": [
6
6
  "camstack",