gpx-from-gopro 0.7.0 → 0.8.0
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/package.json +2 -2
- package/src/telemetry.js +25 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gpx-from-gopro",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Extract a GoPro video's GPS telemetry as GPX or render-agnostic TrackPoints (points + meta + timezone + UTC anchor).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"gopro",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"directory": "packages/gopro"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"gpx-stabilizer": "^0.
|
|
35
|
+
"gpx-stabilizer": "^0.8.0",
|
|
36
36
|
"egm96-universal": "^1.1.1",
|
|
37
37
|
"gopro-telemetry": "^1.2.11",
|
|
38
38
|
"gpmf-extract": "^0.3.3",
|
package/src/telemetry.js
CHANGED
|
@@ -69,21 +69,37 @@ const MIN_REG_SPAN_MS = 5000; // <5 s of media offset → extrapolating to 0 is
|
|
|
69
69
|
const SLOPE_TOL = 0.05; // |slope−1| must be within this (UTC ms vs media ms ⇒ ≈1)
|
|
70
70
|
|
|
71
71
|
/**
|
|
72
|
-
* True recording-start instant (UTC) by **linear regression** of each
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
72
|
+
* True recording-start instant (UTC) by **linear regression** of each sample's
|
|
73
|
+
* UTC `time` against its media offset `cts`: `time ≈ intercept + slope·cts`. The
|
|
74
|
+
* recording starts at `cts = 0`, so the intercept is the wall-clock instant of
|
|
75
|
+
* the first video frame — *before* GPS lock, recovering the pre-lock delay that
|
|
76
|
+
* the first-good-fix anchor ignores. `slope` should be ≈ 1 (both axes are
|
|
77
|
+
* milliseconds); a slope far from 1 means the GPS UTC and media clocks disagree,
|
|
78
|
+
* so the extrapolation is not trustworthy.
|
|
79
79
|
*
|
|
80
|
-
*
|
|
80
|
+
* Deliberately **not** gated on `fix` (unlike {@link firstGoodFix}): some chips
|
|
81
|
+
* (observed on a HERO10) sync UTC `time` well before ever reporting a `2d`/`3d`
|
|
82
|
+
* fix, so a `time`+`cts` pair can already be trustworthy while `fix` stays
|
|
83
|
+
* `"none"` for the whole clip — the slope-≈1 check below is what actually
|
|
84
|
+
* verifies trust, not the fix label. Only a non-finite/null-island `lat`/`lon`
|
|
85
|
+
* is excluded, since that's this format's own sentinel for "no sample yet" (an
|
|
86
|
+
* unsynced point's `time` is a firmware boot-time constant, not real UTC, and
|
|
87
|
+
* would corrupt the fit) — position accuracy itself is irrelevant here, `lat`/
|
|
88
|
+
* `lon` are used only to detect that sentinel.
|
|
89
|
+
*
|
|
90
|
+
* @param {import("gpx-stabilizer").TrackPoint[]} points raw points (need `cts` + `time` + `lat`/`lon`)
|
|
81
91
|
* @returns {{ startUtc: number, slope: number, n: number } | null} null when too
|
|
82
92
|
* few points, too short a media span, or `cts` is unavailable
|
|
83
93
|
*/
|
|
84
94
|
export function regressStartUtc(points) {
|
|
85
95
|
const pts = (points ?? []).filter(
|
|
86
|
-
(p) =>
|
|
96
|
+
(p) =>
|
|
97
|
+
p &&
|
|
98
|
+
isFiniteNum(p.time) &&
|
|
99
|
+
isFiniteNum(p.cts) &&
|
|
100
|
+
isFiniteNum(p.lat) &&
|
|
101
|
+
isFiniteNum(p.lon) &&
|
|
102
|
+
!(p.lat === 0 && p.lon === 0),
|
|
87
103
|
);
|
|
88
104
|
const n = pts.length;
|
|
89
105
|
if (n < MIN_REG_POINTS) return null;
|