@apocaliss92/scrypted-reolink-native 0.5.15 → 0.5.21

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.
@@ -0,0 +1,4 @@
1
+ # Memory Index
2
+
3
+ - [camstack Reolink probe-gated cap registration](camstack_probe_gated_cap_registration.md) — probe-gated native caps (PTZ/autotrack/doorbell/intercom) MUST be re-registered retroactively in `probeAndPersistFeatures`; constructor pass runs before the feature-probe slice is populated.
4
+ - [Baichuan talk sequence + ADPCM framing](baichuan_talk_sequence.md) — canonical two-way-audio command order, block framing math, and fine-tuning knobs (shared by scrypted-reolink-native + camstack).
@@ -0,0 +1,62 @@
1
+ ---
2
+ name: baichuan-talk-sequence
3
+ description: Canonical Baichuan two-way-audio (talk) command order, IMA ADPCM block framing math, and the three intercom fine-tuning settings.
4
+ metadata:
5
+ type: reference
6
+ ---
7
+
8
+ # Baichuan talk (two-way audio) — canonical sequence & framing
9
+
10
+ Source of truth: `reolink-baichuan-js` (`@apocaliss92/nodelink-js`).
11
+ - `src/reolink/baichuan/utils/talkConfig.ts` — build session info + TalkConfig.
12
+ - `src/reolink/baichuan/utils/talkSession.ts` — buffered send pump + stop.
13
+ - `src/reolink/baichuan/utils/talk.ts` — TalkConfig XML + `encodeBcMediaAdpcmBlock`.
14
+ - `ReolinkBaichuanApi.createDedicatedTalkSession` (recommended; own pooled socket).
15
+
16
+ ## Command order
17
+ 1. `getTalkAbility(channel)` — cmd `BC_CMD_ID_TALK_ABILITY`. Returns
18
+ `duplexList`, `audioStreamModeList`, `audioConfigList`.
19
+ 2. Pick `audioConfig`: prefer entry with `audioType === 'adpcm'`, else first.
20
+ 3. `sendTalkConfigWithReset` — cmd `BC_CMD_ID_TALK_CONFIG` (201), class
21
+ `BC_CLASS_MODERN_24`. On responseCode **422**, send `BC_CMD_ID_TALK_RESET`
22
+ (11) then retry config once; must end 200.
23
+ 4. Stream audio: cmd `BC_CMD_ID_TALK` (binary payload, no reply) per payload
24
+ of 1..N ADPCM blocks. Paced by `expectedStreamEndMs` (playLengthMs =
25
+ samples/sampleRate).
26
+ 5. Stop: flush remaining (pad last block with 0xff to `fullBlockSize`),
27
+ wait out the remaining play time, then `BC_CMD_ID_TALK_RESET` (must be 200).
28
+
29
+ UDP/battery: `channelIdOverride = channel` (0-based header channelId).
30
+
31
+ ## Block framing (the load-bearing math)
32
+ - `blockSize = floor(audioConfig.lengthPerEncoder / 2)` (a.k.a. halfBlockSize)
33
+ - `fullBlockSize = blockSize + 4` (4-byte IMA block header: int16 predictor +
34
+ uint8 index + uint8 reserved)
35
+ - `samplesPerBlock = blockSize * 2 + 1` (the +1 is the header predictor sample)
36
+ - PCM bytes needed per block = `samplesPerBlock * 2` (s16le)
37
+ - Wire wrapper per block (`encodeBcMediaAdpcmBlock`): magic `0x62773130` ("bw10")
38
+ + payload_size(u16)×2 + `0x0100`(u16) + halfBlockSize(u16) + block, padded to
39
+ 8-byte multiple.
40
+
41
+ Validate at session open: `fullBlockSize === blockSize + 4` and
42
+ `sampleRate > 0` (Reolink typical 16000 Hz; block ≈ 64 ms).
43
+
44
+ ## Input pipeline
45
+ Incoming WebRTC/mic audio is Opus → decode to **PCM s16le @ camera sampleRate,
46
+ mono** BEFORE IMA ADPCM encoding. `sampleRate` comes from
47
+ `session.info.audioConfig.sampleRate` (read AFTER start, not assumed).
48
+ Critical: if the decoder defaults to f32le, the talk session reads it as
49
+ Int16Array → pure noise. Pin s16le explicitly.
50
+
51
+ ## Fine-tuning settings (Scrypted `intercom-mixin.ts` ⇄ camstack schema parity)
52
+ Same names, same ranges in both projects:
53
+ - `intercomBlocksPerPayload` — int [1,8], default 1. Lower = lower latency, more
54
+ packets/sec. Clamped by lib to [1,8].
55
+ - `intercomMaxBacklogMs` — int [20,5000], default 120. PCM backlog cap; drops
56
+ OLDEST samples (aligned to 16-bit) when exceeded → "backlog clamped" warning.
57
+ `maxBacklogBytes = floor(ms/1000 * sampleRate * 2)`, floored at one block.
58
+ - `intercomGain` — number [0.1,10], default 1.0. Output gain applied to s16le
59
+ PCM (hard-clipped) BEFORE encode (post-encode would corrupt ADPCM predictor).
60
+ In Scrypted it's an ffmpeg `-filter:a volume=N`; in camstack a JS Int16 multiply.
61
+
62
+ Related: [[camstack-probe-gated-cap-registration]].
@@ -0,0 +1,38 @@
1
+ ---
2
+ name: camstack-probe-gated-cap-registration
3
+ description: In camstack's addon-provider-reolink, probe-gated native caps must be re-registered retroactively after the feature probe; constructor registration runs too early.
4
+ metadata:
5
+ type: project
6
+ ---
7
+
8
+ # Reolink probe-gated native-cap registration (camstack)
9
+
10
+ In `packages/addon-provider-reolink/src/reolink-camera.ts`, the constructor calls
11
+ `registerNativeCapabilities()` **synchronously**, but the `feature-probe`
12
+ runtime-state slice (`hasPtz` / `hasIntercom` / `hasDoorbell` / `hasAutotrack`)
13
+ is populated **later**, in the kernel-driven `onProbe()` lifecycle hook →
14
+ `probeAndPersistFeatures()`.
15
+
16
+ **Consequence:** any `registerXIfSupported()` helper that gates on
17
+ `getProbeFlags<ReolinkProbeFlags>().hasX === true` is a NO-OP during the
18
+ constructor pass on a fresh boot (empty slice). It MUST be re-invoked
19
+ retroactively at the end of `probeAndPersistFeatures()`, alongside its siblings:
20
+ `registerPtzIfSupported()`, `registerPtzAutotrackIfSupported()`,
21
+ `registerDoorbellIfSupported()`, `registerIntercomIfSupported()`.
22
+
23
+ Each helper is idempotent (guards on its own `private xRegistered` flag), so a
24
+ warm-rehydrate boot that registered in the constructor just no-ops on the
25
+ retroactive call.
26
+
27
+ **Why this matters:** if a probe-gated cap is never registered, the cap router
28
+ finds no provider for the device and the call fails at the **routing layer**
29
+ before any provider code runs — producing ZERO provider-side logs. This is how
30
+ the "Reolink intercom closes immediately" bug hid: the diagnostic was the
31
+ ABSENCE of the `intercom cap registered (...)` log line for Reolink devices,
32
+ while Hikvision logged it. Compare provider registration log lines across
33
+ vendors when a cap silently does nothing.
34
+
35
+ **Detection tip:** `grep -c "intercom cap registered"` per provider in the log.
36
+ Hikvision logged it 87×; Reolink logged it 0× → cap never registered.
37
+
38
+ Related: [[baichuan-talk-sequence]].