@camstack/system 1.2.261 → 1.2.262

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.
@@ -1587,16 +1587,58 @@ var PIXEL_FORMAT = "yuv420p";
1587
1587
  */
1588
1588
  var GOP_SECONDS = 1;
1589
1589
  /**
1590
- * `-analyzeduration` / `-probesize`, well under ffmpeg's 5 s / 5 MB defaults.
1590
+ * `-analyzeduration` / `-probesize`, as small as ffmpeg allows.
1591
1591
  *
1592
- * Safe on RTSP specifically: the SDP already declares the codec, so the probe
1593
- * has nothing to discover. It matters more here than anywhere else in the repo
1594
- * because the probes are PARALLEL inputs of one child — the composite emits
1595
- * nothing until the LAST of them has finished, so the default budget is paid
1596
- * once per grid, at the slowest source's pace.
1592
+ * ## The probes are SEQUENTIAL, and this is what the tile skew was
1593
+ *
1594
+ * The sentence that used to be here said the probes are "PARALLEL inputs of one
1595
+ * child". They are not. ffmpeg opens its inputs one after another and each open
1596
+ * BLOCKS in `avformat_find_stream_info` until its budget is spent — so input 0
1597
+ * is already connected and receiving while ffmpeg is still opening input 1, its
1598
+ * frames pile up, and `overlay` (which pairs inputs BY PTS) marries input 0's
1599
+ * oldest frame to input 1's newest. The lag is fixed for the life of the child:
1600
+ * both tiles then advance one frame per output frame, so nothing ever closes it.
1601
+ * The FIRST cell is the most behind; the last is live.
1602
+ *
1603
+ * Reproduced in one command on 2026-09-18 — two sources hstacked, one frame,
1604
+ * reading the cameras' own burnt-in clocks out of the composed picture:
1605
+ *
1606
+ * ```
1607
+ * 13:11:21 | 13:11:23 two seconds, and the earlier input is the late one
1608
+ * ```
1609
+ *
1610
+ * ## Why the old numbers cost seconds
1611
+ *
1612
+ * `-probesize` is a BYTE budget, and 1 MB of a 640x360 sub-stream is tens of
1613
+ * seconds of video — so `-analyzeduration 1s` never got the chance to stop it
1614
+ * and each open ran until the byte budget filled. Zero and 32 make the probe
1615
+ * return from the SDP, which already declares the codec, without reading media.
1616
+ *
1617
+ * Measured on this hub, the two sources of the live grid, three runs each,
1618
+ * production input args otherwise identical — time to the first composed frame,
1619
+ * and the skew read off the two burnt-in clocks in that frame:
1620
+ *
1621
+ * ```
1622
+ * 1 s / 1 MB 8986, 9728, 9712 ms skew 5 s, 5 s, 4 s
1623
+ * 0 / 32 2281, 2270, 2304 ms skew 1 s, 1 s, 0 s
1624
+ * ```
1625
+ *
1626
+ * The same numbers are the ~9 s cold start the operator had accepted: it was a
1627
+ * SUM of the opens, never the wait for the slowest source.
1628
+ *
1629
+ * Checked before shipping, because a probe that reads nothing has to survive
1630
+ * what it is not told: h264, h265 and a derived (`mid-to-low`) source all open
1631
+ * with `rc=0`, a 20 s run produces 200 frames of 200 either way (so the pacing
1632
+ * this file already lost once is untouched), and the skew is still 0 at 25 s
1633
+ * into a run — it is set at start-up and does not drift.
1634
+ *
1635
+ * What remains is the spread in when each source's first key frame arrives, and
1636
+ * a `/muted` dial waits for the next IDR. That spread is small here; if it ever
1637
+ * is not, the answer is to start the inputs from a join point we hold, NOT to
1638
+ * re-time the inputs (see `useWallclockTimestamps` below).
1597
1639
  */
1598
- var ANALYZE_DURATION_US = 1e6;
1599
- var PROBE_SIZE_BYTES = 1e6;
1640
+ var ANALYZE_DURATION_US = 0;
1641
+ var PROBE_SIZE_BYTES = 32;
1600
1642
  function inputPlanFor(source) {
1601
1643
  return {
1602
1644
  url: source.url,
@@ -1582,16 +1582,58 @@ var PIXEL_FORMAT = "yuv420p";
1582
1582
  */
1583
1583
  var GOP_SECONDS = 1;
1584
1584
  /**
1585
- * `-analyzeduration` / `-probesize`, well under ffmpeg's 5 s / 5 MB defaults.
1585
+ * `-analyzeduration` / `-probesize`, as small as ffmpeg allows.
1586
1586
  *
1587
- * Safe on RTSP specifically: the SDP already declares the codec, so the probe
1588
- * has nothing to discover. It matters more here than anywhere else in the repo
1589
- * because the probes are PARALLEL inputs of one child — the composite emits
1590
- * nothing until the LAST of them has finished, so the default budget is paid
1591
- * once per grid, at the slowest source's pace.
1587
+ * ## The probes are SEQUENTIAL, and this is what the tile skew was
1588
+ *
1589
+ * The sentence that used to be here said the probes are "PARALLEL inputs of one
1590
+ * child". They are not. ffmpeg opens its inputs one after another and each open
1591
+ * BLOCKS in `avformat_find_stream_info` until its budget is spent — so input 0
1592
+ * is already connected and receiving while ffmpeg is still opening input 1, its
1593
+ * frames pile up, and `overlay` (which pairs inputs BY PTS) marries input 0's
1594
+ * oldest frame to input 1's newest. The lag is fixed for the life of the child:
1595
+ * both tiles then advance one frame per output frame, so nothing ever closes it.
1596
+ * The FIRST cell is the most behind; the last is live.
1597
+ *
1598
+ * Reproduced in one command on 2026-09-18 — two sources hstacked, one frame,
1599
+ * reading the cameras' own burnt-in clocks out of the composed picture:
1600
+ *
1601
+ * ```
1602
+ * 13:11:21 | 13:11:23 two seconds, and the earlier input is the late one
1603
+ * ```
1604
+ *
1605
+ * ## Why the old numbers cost seconds
1606
+ *
1607
+ * `-probesize` is a BYTE budget, and 1 MB of a 640x360 sub-stream is tens of
1608
+ * seconds of video — so `-analyzeduration 1s` never got the chance to stop it
1609
+ * and each open ran until the byte budget filled. Zero and 32 make the probe
1610
+ * return from the SDP, which already declares the codec, without reading media.
1611
+ *
1612
+ * Measured on this hub, the two sources of the live grid, three runs each,
1613
+ * production input args otherwise identical — time to the first composed frame,
1614
+ * and the skew read off the two burnt-in clocks in that frame:
1615
+ *
1616
+ * ```
1617
+ * 1 s / 1 MB 8986, 9728, 9712 ms skew 5 s, 5 s, 4 s
1618
+ * 0 / 32 2281, 2270, 2304 ms skew 1 s, 1 s, 0 s
1619
+ * ```
1620
+ *
1621
+ * The same numbers are the ~9 s cold start the operator had accepted: it was a
1622
+ * SUM of the opens, never the wait for the slowest source.
1623
+ *
1624
+ * Checked before shipping, because a probe that reads nothing has to survive
1625
+ * what it is not told: h264, h265 and a derived (`mid-to-low`) source all open
1626
+ * with `rc=0`, a 20 s run produces 200 frames of 200 either way (so the pacing
1627
+ * this file already lost once is untouched), and the skew is still 0 at 25 s
1628
+ * into a run — it is set at start-up and does not drift.
1629
+ *
1630
+ * What remains is the spread in when each source's first key frame arrives, and
1631
+ * a `/muted` dial waits for the next IDR. That spread is small here; if it ever
1632
+ * is not, the answer is to start the inputs from a join point we hold, NOT to
1633
+ * re-time the inputs (see `useWallclockTimestamps` below).
1592
1634
  */
1593
- var ANALYZE_DURATION_US = 1e6;
1594
- var PROBE_SIZE_BYTES = 1e6;
1635
+ var ANALYZE_DURATION_US = 0;
1636
+ var PROBE_SIZE_BYTES = 32;
1595
1637
  function inputPlanFor(source) {
1596
1638
  return {
1597
1639
  url: source.url,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/system",
3
- "version": "1.2.261",
3
+ "version": "1.2.262",
4
4
  "description": "Core addon for CamStack — builtins, pipeline, process management, auth, logging, events",
5
5
  "keywords": [
6
6
  "camstack",