Deploy b852318
Browse files- route/gps_extractor.py +16 -3
- templates/ts-gps.js +2 -0
route/gps_extractor.py
CHANGED
|
@@ -10,7 +10,7 @@ import subprocess
|
|
| 10 |
_ISO6709 = re.compile(rb"([+-]\d{1,2}(?:\.\d+)?)([+-]\d{1,3}(?:\.\d+)?)([+-]\d+(?:\.\d+)?)?(?:CRS[^/]*)?/")
|
| 11 |
|
| 12 |
|
| 13 |
-
def _result(lat, lon, alt=None, source=""):
|
| 14 |
try:
|
| 15 |
lat, lon = float(lat), float(lon)
|
| 16 |
except (TypeError, ValueError):
|
|
@@ -24,6 +24,13 @@ def _result(lat, lon, alt=None, source=""):
|
|
| 24 |
out["alt"] = round(float(alt), 1)
|
| 25 |
except (TypeError, ValueError):
|
| 26 |
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
return out
|
| 28 |
|
| 29 |
|
|
@@ -59,7 +66,8 @@ def from_image(path):
|
|
| 59 |
alt = None
|
| 60 |
if 6 in gps:
|
| 61 |
alt = _ratio(gps[6]) * (-1 if gps.get(5) in (1, b"\x01") else 1)
|
| 62 |
-
|
|
|
|
| 63 |
except Exception:
|
| 64 |
return {"found": False}
|
| 65 |
|
|
@@ -80,12 +88,17 @@ def from_video(path):
|
|
| 80 |
capture_output=True, timeout=30).stdout
|
| 81 |
info = json.loads(out or b"{}")
|
| 82 |
tag_sets = [info.get("format", {}).get("tags", {})] + [s.get("tags", {}) for s in info.get("streams", [])]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 83 |
for tags in tag_sets:
|
| 84 |
for k, v in (tags or {}).items():
|
| 85 |
if "location" in k.lower() or k.lower().endswith("xyz"):
|
| 86 |
p = _parse_iso6709(str(v))
|
| 87 |
if p:
|
| 88 |
-
return _result(*p, source="video-tag")
|
| 89 |
except Exception:
|
| 90 |
pass
|
| 91 |
# Fallback: scan the start and end of the file for the location atom.
|
|
|
|
| 10 |
_ISO6709 = re.compile(rb"([+-]\d{1,2}(?:\.\d+)?)([+-]\d{1,3}(?:\.\d+)?)([+-]\d+(?:\.\d+)?)?(?:CRS[^/]*)?/")
|
| 11 |
|
| 12 |
|
| 13 |
+
def _result(lat, lon, alt=None, source="", accuracy=None):
|
| 14 |
try:
|
| 15 |
lat, lon = float(lat), float(lon)
|
| 16 |
except (TypeError, ValueError):
|
|
|
|
| 24 |
out["alt"] = round(float(alt), 1)
|
| 25 |
except (TypeError, ValueError):
|
| 26 |
pass
|
| 27 |
+
if accuracy is not None:
|
| 28 |
+
try:
|
| 29 |
+
a = float(accuracy)
|
| 30 |
+
if 0 < a < 100000:
|
| 31 |
+
out["accuracy_m"] = round(a, 1)
|
| 32 |
+
except (TypeError, ValueError):
|
| 33 |
+
pass
|
| 34 |
return out
|
| 35 |
|
| 36 |
|
|
|
|
| 66 |
alt = None
|
| 67 |
if 6 in gps:
|
| 68 |
alt = _ratio(gps[6]) * (-1 if gps.get(5) in (1, b"\x01") else 1)
|
| 69 |
+
acc = _ratio(gps[31]) if 31 in gps else None # GPSHPositioningError (metres)
|
| 70 |
+
return _result(lat, lon, alt, "exif", acc)
|
| 71 |
except Exception:
|
| 72 |
return {"found": False}
|
| 73 |
|
|
|
|
| 88 |
capture_output=True, timeout=30).stdout
|
| 89 |
info = json.loads(out or b"{}")
|
| 90 |
tag_sets = [info.get("format", {}).get("tags", {})] + [s.get("tags", {}) for s in info.get("streams", [])]
|
| 91 |
+
acc = None
|
| 92 |
+
for tags in tag_sets:
|
| 93 |
+
for k, v in (tags or {}).items():
|
| 94 |
+
if "location.accuracy.horizontal" in k.lower():
|
| 95 |
+
acc = v
|
| 96 |
for tags in tag_sets:
|
| 97 |
for k, v in (tags or {}).items():
|
| 98 |
if "location" in k.lower() or k.lower().endswith("xyz"):
|
| 99 |
p = _parse_iso6709(str(v))
|
| 100 |
if p:
|
| 101 |
+
return _result(*p, source="video-tag", accuracy=acc)
|
| 102 |
except Exception:
|
| 103 |
pass
|
| 104 |
# Fallback: scan the start and end of the file for the location atom.
|
templates/ts-gps.js
CHANGED
|
@@ -108,6 +108,8 @@
|
|
| 108 |
pop.innerHTML =
|
| 109 |
'<div style="font-weight:700;margin-bottom:2px">' + T('الموقع المضمَّن في الملف', 'Location embedded in the file') + '</div>' +
|
| 110 |
'<div class="coords">' + g.lat.toFixed(6) + ', ' + g.lon.toFixed(6) + '</div>' +
|
|
|
|
|
|
|
| 111 |
(g.alt != null ? '<div style="text-align:center;opacity:.75">' + T('الارتفاع: ', 'Altitude: ') + '<span dir="ltr">' + g.alt + ' m</span></div>' : '') +
|
| 112 |
'<a class="primary" target="_blank" rel="noopener" href="' + g.maps_url + '">' + T('فتح في خرائط Google', 'Open in Google Maps') + '</a>' +
|
| 113 |
'<a target="_blank" rel="noopener" href="https://maps.apple.com/?ll=' + g.lat + ',' + g.lon + '&q=' + g.lat + ',' + g.lon + '">' + T('فتح في خرائط Apple', 'Open in Apple Maps') + '</a>' +
|
|
|
|
| 108 |
pop.innerHTML =
|
| 109 |
'<div style="font-weight:700;margin-bottom:2px">' + T('الموقع المضمَّن في الملف', 'Location embedded in the file') + '</div>' +
|
| 110 |
'<div class="coords">' + g.lat.toFixed(6) + ', ' + g.lon.toFixed(6) + '</div>' +
|
| 111 |
+
(g.accuracy_m != null ? '<div style="text-align:center;font-weight:700;color:#86efac">' + T('دقة الموقع: ', 'Accuracy: ') + '<span dir="ltr">± ' + g.accuracy_m + ' m</span></div>' :
|
| 112 |
+
'<div style="text-align:center;opacity:.6;font-size:11px">' + T('لم يحفظ الجهاز نصف قطر الدقة', 'The device did not store an accuracy radius') + '</div>') +
|
| 113 |
(g.alt != null ? '<div style="text-align:center;opacity:.75">' + T('الارتفاع: ', 'Altitude: ') + '<span dir="ltr">' + g.alt + ' m</span></div>' : '') +
|
| 114 |
'<a class="primary" target="_blank" rel="noopener" href="' + g.maps_url + '">' + T('فتح في خرائط Google', 'Open in Google Maps') + '</a>' +
|
| 115 |
'<a target="_blank" rel="noopener" href="https://maps.apple.com/?ll=' + g.lat + ',' + g.lon + '&q=' + g.lat + ',' + g.lon + '">' + T('فتح في خرائط Apple', 'Open in Apple Maps') + '</a>' +
|