@camstack/addon-pipeline 1.2.285 → 1.2.286
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/stream-broker/index.js +116 -15
- package/dist/stream-broker/index.mjs +116 -15
- package/package.json +1 -1
|
@@ -26692,6 +26692,14 @@ var ServerMessageSchema = require_dist.discriminatedUnion("t", [
|
|
|
26692
26692
|
clipId: require_dist.string().min(1),
|
|
26693
26693
|
durationMs: require_dist.number().positive()
|
|
26694
26694
|
}),
|
|
26695
|
+
require_dist.object({
|
|
26696
|
+
t: require_dist.literal("clipTransport"),
|
|
26697
|
+
clipId: require_dist.string().min(1),
|
|
26698
|
+
/** `forward` = only ahead of the playhead. `free` = anywhere. */
|
|
26699
|
+
seek: require_dist._enum(["forward", "free"]),
|
|
26700
|
+
/** Frame-step BACKWARD is meaningful. Forward always is. */
|
|
26701
|
+
stepBack: require_dist.boolean()
|
|
26702
|
+
}),
|
|
26695
26703
|
require_dist.object({
|
|
26696
26704
|
t: require_dist.literal("clipAudio"),
|
|
26697
26705
|
clipId: require_dist.string().min(1),
|
|
@@ -26722,11 +26730,49 @@ function serializeServerMessage(msg) {
|
|
|
26722
26730
|
//#endregion
|
|
26723
26731
|
//#region src/stream-broker/recorded/feed-clock.ts
|
|
26724
26732
|
/**
|
|
26733
|
+
* The ORIGIN two tracks are measured from — the base and the source anchor,
|
|
26734
|
+
* shared, so the offset between video and audio survives a discontinuity.
|
|
26735
|
+
*
|
|
26736
|
+
* ## Why this exists
|
|
26737
|
+
*
|
|
26738
|
+
* `markDiscontinuity` re-bases on the last output. With one instance per
|
|
26739
|
+
* track, that last output is the TRACK'S own, and the two differ by however
|
|
26740
|
+
* far apart the interleave left them — so every seek replaced the real A/V
|
|
26741
|
+
* offset with that gap, in the same direction each time. Measured on the
|
|
26742
|
+
* clock alone it grows by a fixed step each time and never comes back; how
|
|
26743
|
+
* big that step is, is the interleave's business — 10–23 ms a seek on a
|
|
26744
|
+
* synthetic fixture, **900 ms over three seeks on a real clip**.
|
|
26745
|
+
*
|
|
26746
|
+
* Calling `markSeek()` on both instances "together" did not help and could
|
|
26747
|
+
* not: it is not the CALL that has to be shared, it is the ORIGIN. With one,
|
|
26748
|
+
* `out_video − out_audio` is `(vPts − aPts) / rate` — exactly the source
|
|
26749
|
+
* offset, which is the entire content of lip sync — and there is nothing left
|
|
26750
|
+
* to keep in step.
|
|
26751
|
+
*
|
|
26752
|
+
* `lastOutMs` stays per-track: monotonicity is a promise to ONE receiver
|
|
26753
|
+
* track, and clamping video against audio's last stamp would move video.
|
|
26754
|
+
*/
|
|
26755
|
+
var FeedOrigin = class {
|
|
26756
|
+
/** Output ms the current run is measured from. */
|
|
26757
|
+
outBaseMs = 0;
|
|
26758
|
+
/** Source ms the current run is measured from; `null` until the next stamp. */
|
|
26759
|
+
srcAnchorMs = null;
|
|
26760
|
+
/**
|
|
26761
|
+
* The furthest EITHER track has been stamped. What a discontinuity clears,
|
|
26762
|
+
* so the gap is opened past both — and so two clocks marking the same
|
|
26763
|
+
* discontinuity in a row produce one gap, not two.
|
|
26764
|
+
*/
|
|
26765
|
+
highWaterMs = 0;
|
|
26766
|
+
};
|
|
26767
|
+
/**
|
|
26725
26768
|
* Maps arbitrary, possibly-resetting source PTS (ms) onto a strictly increasing
|
|
26726
26769
|
* output clock at `rateHz` (default 90 kHz video; pass 8000 for PCMU audio). On
|
|
26727
26770
|
* seek the output keeps advancing while the source anchor re-bases, so
|
|
26728
|
-
* per-segment PTS resets never rewind the track.
|
|
26729
|
-
*
|
|
26771
|
+
* per-segment PTS resets never rewind the track.
|
|
26772
|
+
*
|
|
26773
|
+
* Video and audio are separate instances SHARING one {@link FeedOrigin} — see
|
|
26774
|
+
* there for what happens when they do not. An instance constructed without one
|
|
26775
|
+
* gets its own, so a lone clock behaves exactly as it always did.
|
|
26730
26776
|
*
|
|
26731
26777
|
* Playback rate: `setRate(r)` divides SOURCE elapsed time by `r` on the output
|
|
26732
26778
|
* timeline (2× → half the output spacing → the receiver plays frames twice as
|
|
@@ -26736,20 +26782,21 @@ function serializeServerMessage(msg) {
|
|
|
26736
26782
|
*/
|
|
26737
26783
|
var MonotonicClock = class {
|
|
26738
26784
|
rateHz;
|
|
26739
|
-
srcAnchorMs = null;
|
|
26740
26785
|
lastSrcMs = null;
|
|
26741
|
-
outBaseMs = 0;
|
|
26742
26786
|
lastOutMs = 0;
|
|
26743
26787
|
rate = 1;
|
|
26744
|
-
|
|
26788
|
+
origin;
|
|
26789
|
+
constructor(rateHz = 9e4, origin) {
|
|
26745
26790
|
this.rateHz = rateHz;
|
|
26791
|
+
this.origin = origin ?? new FeedOrigin();
|
|
26746
26792
|
}
|
|
26747
26793
|
stamp(srcPtsMs) {
|
|
26748
|
-
if (this.srcAnchorMs === null) this.srcAnchorMs = srcPtsMs;
|
|
26794
|
+
if (this.origin.srcAnchorMs === null) this.origin.srcAnchorMs = srcPtsMs;
|
|
26749
26795
|
this.lastSrcMs = srcPtsMs;
|
|
26750
|
-
const elapsed = Math.max(0, (srcPtsMs - this.srcAnchorMs) / this.rate);
|
|
26751
|
-
const outMs = this.outBaseMs + elapsed;
|
|
26796
|
+
const elapsed = Math.max(0, (srcPtsMs - this.origin.srcAnchorMs) / this.rate);
|
|
26797
|
+
const outMs = this.origin.outBaseMs + elapsed;
|
|
26752
26798
|
this.lastOutMs = Math.max(this.lastOutMs, outMs);
|
|
26799
|
+
this.origin.highWaterMs = Math.max(this.origin.highWaterMs, this.lastOutMs);
|
|
26753
26800
|
return Math.round(this.lastOutMs * this.rateHz / 1e3);
|
|
26754
26801
|
}
|
|
26755
26802
|
/**
|
|
@@ -26773,8 +26820,8 @@ var MonotonicClock = class {
|
|
|
26773
26820
|
* rate-scaled.
|
|
26774
26821
|
*/
|
|
26775
26822
|
markDiscontinuity(gapMs) {
|
|
26776
|
-
this.outBaseMs = this.
|
|
26777
|
-
this.srcAnchorMs = null;
|
|
26823
|
+
this.origin.outBaseMs = this.origin.highWaterMs + gapMs;
|
|
26824
|
+
this.origin.srcAnchorMs = null;
|
|
26778
26825
|
this.lastSrcMs = null;
|
|
26779
26826
|
}
|
|
26780
26827
|
/**
|
|
@@ -26786,9 +26833,9 @@ var MonotonicClock = class {
|
|
|
26786
26833
|
*/
|
|
26787
26834
|
setRate(rate) {
|
|
26788
26835
|
if (!(rate > 0) || rate === this.rate) return;
|
|
26789
|
-
if (this.srcAnchorMs !== null && this.lastSrcMs !== null) {
|
|
26790
|
-
this.outBaseMs = this.lastOutMs;
|
|
26791
|
-
this.srcAnchorMs = this.lastSrcMs;
|
|
26836
|
+
if (this.origin.srcAnchorMs !== null && this.lastSrcMs !== null) {
|
|
26837
|
+
this.origin.outBaseMs = this.lastOutMs;
|
|
26838
|
+
this.origin.srcAnchorMs = this.lastSrcMs;
|
|
26792
26839
|
}
|
|
26793
26840
|
this.rate = rate;
|
|
26794
26841
|
}
|
|
@@ -27627,7 +27674,14 @@ function emptyPlayCensus() {
|
|
|
27627
27674
|
}
|
|
27628
27675
|
var RecordedFeeder = class {
|
|
27629
27676
|
deps;
|
|
27630
|
-
|
|
27677
|
+
/**
|
|
27678
|
+
* ONE origin for both tracks. Two independent ones replaced the real A/V
|
|
27679
|
+
* offset with the interleave gap at every seek, in the same direction each
|
|
27680
|
+
* time — measured at 23 ms per seek on the clock alone and 900 ms over
|
|
27681
|
+
* three seeks on a real clip. See `FeedOrigin`.
|
|
27682
|
+
*/
|
|
27683
|
+
feedOrigin = new FeedOrigin();
|
|
27684
|
+
clock = new MonotonicClock(9e4, this.feedOrigin);
|
|
27631
27685
|
/** Audio clock (PCMU 8 kHz / Opus 48 kHz); re-anchored together with video. */
|
|
27632
27686
|
audioClock;
|
|
27633
27687
|
clockHasAdvanced = false;
|
|
@@ -27810,7 +27864,7 @@ var RecordedFeeder = class {
|
|
|
27810
27864
|
lastAnnouncedState = null;
|
|
27811
27865
|
constructor(deps) {
|
|
27812
27866
|
this.deps = deps;
|
|
27813
|
-
this.audioClock = new MonotonicClock(deps.audioClockRateHz ?? 8e3);
|
|
27867
|
+
this.audioClock = new MonotonicClock(deps.audioClockRateHz ?? 8e3, this.feedOrigin);
|
|
27814
27868
|
this.scrubCache = deps.fragmentCache ?? new ScrubFragmentCache();
|
|
27815
27869
|
}
|
|
27816
27870
|
/**
|
|
@@ -30077,9 +30131,46 @@ var TimelineSession = class {
|
|
|
30077
30131
|
this.lastPositionMs = null;
|
|
30078
30132
|
const feeder = this.enterRecorded();
|
|
30079
30133
|
await feeder.seek(offsetMs);
|
|
30134
|
+
this.reportClipTransport(clipId, feeder);
|
|
30080
30135
|
await Promise.all([this.reportClipDuration(clipId, feeder), this.reportClipAudio(clipId, feeder)]);
|
|
30081
30136
|
}
|
|
30082
30137
|
/**
|
|
30138
|
+
* Tell the viewer what this clip can be driven to do.
|
|
30139
|
+
*
|
|
30140
|
+
* A clip served from the provider's stream is forward-only; one fetched as
|
|
30141
|
+
* a file is not. Without the answer the viewer draws the same progress bar
|
|
30142
|
+
* for both, and on the stream a backward drag is refused and the position
|
|
30143
|
+
* re-sent — a control that visibly undoes the operator's gesture, which
|
|
30144
|
+
* reads as broken rather than as unavailable (D62).
|
|
30145
|
+
*
|
|
30146
|
+
* A feeder that does not say sends nothing: silence is "the freedom you
|
|
30147
|
+
* always had", and claiming `free` for a feeder that never answered would
|
|
30148
|
+
* be this surface inventing a capability.
|
|
30149
|
+
*/
|
|
30150
|
+
reportClipTransport(clipId, feeder) {
|
|
30151
|
+
const report = feeder.transport;
|
|
30152
|
+
if (report === void 0) {
|
|
30153
|
+
this.deps.onLog?.("clip playback: transport not reported — this feeder cannot say", {
|
|
30154
|
+
deviceId: this.deps.deviceId,
|
|
30155
|
+
clipId
|
|
30156
|
+
});
|
|
30157
|
+
return;
|
|
30158
|
+
}
|
|
30159
|
+
if (this.clip?.clipId !== clipId) return;
|
|
30160
|
+
this.deps.onLog?.("clip playback: transport reported", {
|
|
30161
|
+
deviceId: this.deps.deviceId,
|
|
30162
|
+
clipId,
|
|
30163
|
+
seek: report.seek,
|
|
30164
|
+
stepBack: report.stepBack
|
|
30165
|
+
});
|
|
30166
|
+
this.deps.session.sendControl(serializeServerMessage({
|
|
30167
|
+
t: "clipTransport",
|
|
30168
|
+
clipId,
|
|
30169
|
+
seek: report.seek,
|
|
30170
|
+
stepBack: report.stepBack
|
|
30171
|
+
}));
|
|
30172
|
+
}
|
|
30173
|
+
/**
|
|
30083
30174
|
* Tell the viewer whether this clip has sound.
|
|
30084
30175
|
*
|
|
30085
30176
|
* Silence has three causes the operator cannot tell apart by listening —
|
|
@@ -31617,6 +31708,16 @@ function createClipStreamFeeder(deps) {
|
|
|
31617
31708
|
}
|
|
31618
31709
|
var ClipStreamFeeder = class {
|
|
31619
31710
|
deps;
|
|
31711
|
+
/**
|
|
31712
|
+
* Forward-only, and no backward frame-step: the bytes behind the head were
|
|
31713
|
+
* never kept, and the camera offers no replay-from-offset. Stated here so
|
|
31714
|
+
* the viewer can DISABLE those verbs rather than offer them and have every
|
|
31715
|
+
* use refused — the whole content of this report.
|
|
31716
|
+
*/
|
|
31717
|
+
transport = {
|
|
31718
|
+
seek: "forward",
|
|
31719
|
+
stepBack: false
|
|
31720
|
+
};
|
|
31620
31721
|
phase = "idle";
|
|
31621
31722
|
connection = null;
|
|
31622
31723
|
demuxer;
|
|
@@ -26688,6 +26688,14 @@ var ServerMessageSchema = discriminatedUnion("t", [
|
|
|
26688
26688
|
clipId: string().min(1),
|
|
26689
26689
|
durationMs: number().positive()
|
|
26690
26690
|
}),
|
|
26691
|
+
object({
|
|
26692
|
+
t: literal("clipTransport"),
|
|
26693
|
+
clipId: string().min(1),
|
|
26694
|
+
/** `forward` = only ahead of the playhead. `free` = anywhere. */
|
|
26695
|
+
seek: _enum(["forward", "free"]),
|
|
26696
|
+
/** Frame-step BACKWARD is meaningful. Forward always is. */
|
|
26697
|
+
stepBack: boolean()
|
|
26698
|
+
}),
|
|
26691
26699
|
object({
|
|
26692
26700
|
t: literal("clipAudio"),
|
|
26693
26701
|
clipId: string().min(1),
|
|
@@ -26718,11 +26726,49 @@ function serializeServerMessage(msg) {
|
|
|
26718
26726
|
//#endregion
|
|
26719
26727
|
//#region src/stream-broker/recorded/feed-clock.ts
|
|
26720
26728
|
/**
|
|
26729
|
+
* The ORIGIN two tracks are measured from — the base and the source anchor,
|
|
26730
|
+
* shared, so the offset between video and audio survives a discontinuity.
|
|
26731
|
+
*
|
|
26732
|
+
* ## Why this exists
|
|
26733
|
+
*
|
|
26734
|
+
* `markDiscontinuity` re-bases on the last output. With one instance per
|
|
26735
|
+
* track, that last output is the TRACK'S own, and the two differ by however
|
|
26736
|
+
* far apart the interleave left them — so every seek replaced the real A/V
|
|
26737
|
+
* offset with that gap, in the same direction each time. Measured on the
|
|
26738
|
+
* clock alone it grows by a fixed step each time and never comes back; how
|
|
26739
|
+
* big that step is, is the interleave's business — 10–23 ms a seek on a
|
|
26740
|
+
* synthetic fixture, **900 ms over three seeks on a real clip**.
|
|
26741
|
+
*
|
|
26742
|
+
* Calling `markSeek()` on both instances "together" did not help and could
|
|
26743
|
+
* not: it is not the CALL that has to be shared, it is the ORIGIN. With one,
|
|
26744
|
+
* `out_video − out_audio` is `(vPts − aPts) / rate` — exactly the source
|
|
26745
|
+
* offset, which is the entire content of lip sync — and there is nothing left
|
|
26746
|
+
* to keep in step.
|
|
26747
|
+
*
|
|
26748
|
+
* `lastOutMs` stays per-track: monotonicity is a promise to ONE receiver
|
|
26749
|
+
* track, and clamping video against audio's last stamp would move video.
|
|
26750
|
+
*/
|
|
26751
|
+
var FeedOrigin = class {
|
|
26752
|
+
/** Output ms the current run is measured from. */
|
|
26753
|
+
outBaseMs = 0;
|
|
26754
|
+
/** Source ms the current run is measured from; `null` until the next stamp. */
|
|
26755
|
+
srcAnchorMs = null;
|
|
26756
|
+
/**
|
|
26757
|
+
* The furthest EITHER track has been stamped. What a discontinuity clears,
|
|
26758
|
+
* so the gap is opened past both — and so two clocks marking the same
|
|
26759
|
+
* discontinuity in a row produce one gap, not two.
|
|
26760
|
+
*/
|
|
26761
|
+
highWaterMs = 0;
|
|
26762
|
+
};
|
|
26763
|
+
/**
|
|
26721
26764
|
* Maps arbitrary, possibly-resetting source PTS (ms) onto a strictly increasing
|
|
26722
26765
|
* output clock at `rateHz` (default 90 kHz video; pass 8000 for PCMU audio). On
|
|
26723
26766
|
* seek the output keeps advancing while the source anchor re-bases, so
|
|
26724
|
-
* per-segment PTS resets never rewind the track.
|
|
26725
|
-
*
|
|
26767
|
+
* per-segment PTS resets never rewind the track.
|
|
26768
|
+
*
|
|
26769
|
+
* Video and audio are separate instances SHARING one {@link FeedOrigin} — see
|
|
26770
|
+
* there for what happens when they do not. An instance constructed without one
|
|
26771
|
+
* gets its own, so a lone clock behaves exactly as it always did.
|
|
26726
26772
|
*
|
|
26727
26773
|
* Playback rate: `setRate(r)` divides SOURCE elapsed time by `r` on the output
|
|
26728
26774
|
* timeline (2× → half the output spacing → the receiver plays frames twice as
|
|
@@ -26732,20 +26778,21 @@ function serializeServerMessage(msg) {
|
|
|
26732
26778
|
*/
|
|
26733
26779
|
var MonotonicClock = class {
|
|
26734
26780
|
rateHz;
|
|
26735
|
-
srcAnchorMs = null;
|
|
26736
26781
|
lastSrcMs = null;
|
|
26737
|
-
outBaseMs = 0;
|
|
26738
26782
|
lastOutMs = 0;
|
|
26739
26783
|
rate = 1;
|
|
26740
|
-
|
|
26784
|
+
origin;
|
|
26785
|
+
constructor(rateHz = 9e4, origin) {
|
|
26741
26786
|
this.rateHz = rateHz;
|
|
26787
|
+
this.origin = origin ?? new FeedOrigin();
|
|
26742
26788
|
}
|
|
26743
26789
|
stamp(srcPtsMs) {
|
|
26744
|
-
if (this.srcAnchorMs === null) this.srcAnchorMs = srcPtsMs;
|
|
26790
|
+
if (this.origin.srcAnchorMs === null) this.origin.srcAnchorMs = srcPtsMs;
|
|
26745
26791
|
this.lastSrcMs = srcPtsMs;
|
|
26746
|
-
const elapsed = Math.max(0, (srcPtsMs - this.srcAnchorMs) / this.rate);
|
|
26747
|
-
const outMs = this.outBaseMs + elapsed;
|
|
26792
|
+
const elapsed = Math.max(0, (srcPtsMs - this.origin.srcAnchorMs) / this.rate);
|
|
26793
|
+
const outMs = this.origin.outBaseMs + elapsed;
|
|
26748
26794
|
this.lastOutMs = Math.max(this.lastOutMs, outMs);
|
|
26795
|
+
this.origin.highWaterMs = Math.max(this.origin.highWaterMs, this.lastOutMs);
|
|
26749
26796
|
return Math.round(this.lastOutMs * this.rateHz / 1e3);
|
|
26750
26797
|
}
|
|
26751
26798
|
/**
|
|
@@ -26769,8 +26816,8 @@ var MonotonicClock = class {
|
|
|
26769
26816
|
* rate-scaled.
|
|
26770
26817
|
*/
|
|
26771
26818
|
markDiscontinuity(gapMs) {
|
|
26772
|
-
this.outBaseMs = this.
|
|
26773
|
-
this.srcAnchorMs = null;
|
|
26819
|
+
this.origin.outBaseMs = this.origin.highWaterMs + gapMs;
|
|
26820
|
+
this.origin.srcAnchorMs = null;
|
|
26774
26821
|
this.lastSrcMs = null;
|
|
26775
26822
|
}
|
|
26776
26823
|
/**
|
|
@@ -26782,9 +26829,9 @@ var MonotonicClock = class {
|
|
|
26782
26829
|
*/
|
|
26783
26830
|
setRate(rate) {
|
|
26784
26831
|
if (!(rate > 0) || rate === this.rate) return;
|
|
26785
|
-
if (this.srcAnchorMs !== null && this.lastSrcMs !== null) {
|
|
26786
|
-
this.outBaseMs = this.lastOutMs;
|
|
26787
|
-
this.srcAnchorMs = this.lastSrcMs;
|
|
26832
|
+
if (this.origin.srcAnchorMs !== null && this.lastSrcMs !== null) {
|
|
26833
|
+
this.origin.outBaseMs = this.lastOutMs;
|
|
26834
|
+
this.origin.srcAnchorMs = this.lastSrcMs;
|
|
26788
26835
|
}
|
|
26789
26836
|
this.rate = rate;
|
|
26790
26837
|
}
|
|
@@ -27623,7 +27670,14 @@ function emptyPlayCensus() {
|
|
|
27623
27670
|
}
|
|
27624
27671
|
var RecordedFeeder = class {
|
|
27625
27672
|
deps;
|
|
27626
|
-
|
|
27673
|
+
/**
|
|
27674
|
+
* ONE origin for both tracks. Two independent ones replaced the real A/V
|
|
27675
|
+
* offset with the interleave gap at every seek, in the same direction each
|
|
27676
|
+
* time — measured at 23 ms per seek on the clock alone and 900 ms over
|
|
27677
|
+
* three seeks on a real clip. See `FeedOrigin`.
|
|
27678
|
+
*/
|
|
27679
|
+
feedOrigin = new FeedOrigin();
|
|
27680
|
+
clock = new MonotonicClock(9e4, this.feedOrigin);
|
|
27627
27681
|
/** Audio clock (PCMU 8 kHz / Opus 48 kHz); re-anchored together with video. */
|
|
27628
27682
|
audioClock;
|
|
27629
27683
|
clockHasAdvanced = false;
|
|
@@ -27806,7 +27860,7 @@ var RecordedFeeder = class {
|
|
|
27806
27860
|
lastAnnouncedState = null;
|
|
27807
27861
|
constructor(deps) {
|
|
27808
27862
|
this.deps = deps;
|
|
27809
|
-
this.audioClock = new MonotonicClock(deps.audioClockRateHz ?? 8e3);
|
|
27863
|
+
this.audioClock = new MonotonicClock(deps.audioClockRateHz ?? 8e3, this.feedOrigin);
|
|
27810
27864
|
this.scrubCache = deps.fragmentCache ?? new ScrubFragmentCache();
|
|
27811
27865
|
}
|
|
27812
27866
|
/**
|
|
@@ -30073,9 +30127,46 @@ var TimelineSession = class {
|
|
|
30073
30127
|
this.lastPositionMs = null;
|
|
30074
30128
|
const feeder = this.enterRecorded();
|
|
30075
30129
|
await feeder.seek(offsetMs);
|
|
30130
|
+
this.reportClipTransport(clipId, feeder);
|
|
30076
30131
|
await Promise.all([this.reportClipDuration(clipId, feeder), this.reportClipAudio(clipId, feeder)]);
|
|
30077
30132
|
}
|
|
30078
30133
|
/**
|
|
30134
|
+
* Tell the viewer what this clip can be driven to do.
|
|
30135
|
+
*
|
|
30136
|
+
* A clip served from the provider's stream is forward-only; one fetched as
|
|
30137
|
+
* a file is not. Without the answer the viewer draws the same progress bar
|
|
30138
|
+
* for both, and on the stream a backward drag is refused and the position
|
|
30139
|
+
* re-sent — a control that visibly undoes the operator's gesture, which
|
|
30140
|
+
* reads as broken rather than as unavailable (D62).
|
|
30141
|
+
*
|
|
30142
|
+
* A feeder that does not say sends nothing: silence is "the freedom you
|
|
30143
|
+
* always had", and claiming `free` for a feeder that never answered would
|
|
30144
|
+
* be this surface inventing a capability.
|
|
30145
|
+
*/
|
|
30146
|
+
reportClipTransport(clipId, feeder) {
|
|
30147
|
+
const report = feeder.transport;
|
|
30148
|
+
if (report === void 0) {
|
|
30149
|
+
this.deps.onLog?.("clip playback: transport not reported — this feeder cannot say", {
|
|
30150
|
+
deviceId: this.deps.deviceId,
|
|
30151
|
+
clipId
|
|
30152
|
+
});
|
|
30153
|
+
return;
|
|
30154
|
+
}
|
|
30155
|
+
if (this.clip?.clipId !== clipId) return;
|
|
30156
|
+
this.deps.onLog?.("clip playback: transport reported", {
|
|
30157
|
+
deviceId: this.deps.deviceId,
|
|
30158
|
+
clipId,
|
|
30159
|
+
seek: report.seek,
|
|
30160
|
+
stepBack: report.stepBack
|
|
30161
|
+
});
|
|
30162
|
+
this.deps.session.sendControl(serializeServerMessage({
|
|
30163
|
+
t: "clipTransport",
|
|
30164
|
+
clipId,
|
|
30165
|
+
seek: report.seek,
|
|
30166
|
+
stepBack: report.stepBack
|
|
30167
|
+
}));
|
|
30168
|
+
}
|
|
30169
|
+
/**
|
|
30079
30170
|
* Tell the viewer whether this clip has sound.
|
|
30080
30171
|
*
|
|
30081
30172
|
* Silence has three causes the operator cannot tell apart by listening —
|
|
@@ -31613,6 +31704,16 @@ function createClipStreamFeeder(deps) {
|
|
|
31613
31704
|
}
|
|
31614
31705
|
var ClipStreamFeeder = class {
|
|
31615
31706
|
deps;
|
|
31707
|
+
/**
|
|
31708
|
+
* Forward-only, and no backward frame-step: the bytes behind the head were
|
|
31709
|
+
* never kept, and the camera offers no replay-from-offset. Stated here so
|
|
31710
|
+
* the viewer can DISABLE those verbs rather than offer them and have every
|
|
31711
|
+
* use refused — the whole content of this report.
|
|
31712
|
+
*/
|
|
31713
|
+
transport = {
|
|
31714
|
+
seek: "forward",
|
|
31715
|
+
stepBack: false
|
|
31716
|
+
};
|
|
31616
31717
|
phase = "idle";
|
|
31617
31718
|
connection = null;
|
|
31618
31719
|
demuxer;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-pipeline",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.286",
|
|
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",
|