mapillary-tools 0.11.0b4__tar.gz → 0.11.2__tar.gz
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.
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/PKG-INFO +3 -3
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/README.md +1 -1
- mapillary_tools-0.11.2/mapillary_tools/__init__.py +1 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/api_v4.py +7 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/authenticate.py +5 -1
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/exif_read.py +3 -3
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/exiftool_read.py +2 -2
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/ffmpeg.py +8 -2
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/process_geotag_properties.py +1 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/process_sequence_properties.py +5 -3
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/sample_video.py +17 -15
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/types.py +5 -10
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/upload.py +13 -6
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/upload_api_v4.py +7 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/uploader.py +8 -2
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/video_data_extraction/cli_options.py +1 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/video_data_extraction/extract_video_data.py +9 -5
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/video_data_extraction/extractors/exiftool_runtime_parser.py +13 -4
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools.egg-info/PKG-INFO +4 -4
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools.egg-info/requires.txt +1 -1
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/requirements.txt +1 -1
- mapillary_tools-0.11.0b4/mapillary_tools/__init__.py +0 -1
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/LICENSE +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/MANIFEST.in +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/commands/__init__.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/commands/__main__.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/commands/authenticate.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/commands/process.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/commands/process_and_upload.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/commands/sample_video.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/commands/upload.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/commands/upload_blackvue.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/commands/upload_camm.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/commands/upload_zip.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/commands/video_process.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/commands/video_process_and_upload.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/commands/zip.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/config.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/constants.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/exceptions.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/exif_write.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/exiftool_read_video.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geo.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/__init__.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/blackvue_parser.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/camm_builder.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/camm_parser.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/construct_mp4_parser.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/geotag_from_generic.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/geotag_images_from_exif.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/geotag_images_from_exiftool.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/geotag_images_from_exiftool_both_image_and_video.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/geotag_images_from_gpx.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/geotag_images_from_gpx_file.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/geotag_images_from_nmea_file.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/geotag_images_from_video.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/geotag_videos_from_exiftool_video.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/geotag_videos_from_video.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/gpmf_gps_filter.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/gpmf_parser.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/gps_filter.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/io_utils.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/mp4_sample_parser.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/simple_mp4_builder.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/simple_mp4_parser.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/utils.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/history.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/ipc.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/process_import_meta_properties.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/utils.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/video_data_extraction/extractors/base_parser.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/video_data_extraction/extractors/blackvue_parser.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/video_data_extraction/extractors/camm_parser.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/video_data_extraction/extractors/exiftool_xml_parser.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/video_data_extraction/extractors/generic_video_parser.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/video_data_extraction/extractors/gopro_parser.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/video_data_extraction/extractors/gpx_parser.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/video_data_extraction/extractors/nmea_parser.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/video_data_extraction/video_data_parser_factory.py +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools.egg-info/SOURCES.txt +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools.egg-info/dependency_links.txt +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools.egg-info/entry_points.txt +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools.egg-info/top_level.txt +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/schema/image_description_schema.json +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/setup.cfg +0 -0
- {mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: mapillary_tools
|
|
3
|
-
Version: 0.11.
|
|
3
|
+
Version: 0.11.2
|
|
4
4
|
Summary: Mapillary Image/Video Import Pipeline
|
|
5
5
|
Home-page: https://github.com/mapillary/mapillary_tools
|
|
6
6
|
Author: Mapillary
|
|
@@ -13,7 +13,7 @@ Requires-Dist: construct<3.0.0,>=2.10.0
|
|
|
13
13
|
Requires-Dist: exifread==2.3.2
|
|
14
14
|
Requires-Dist: piexif==1.1.3
|
|
15
15
|
Requires-Dist: gpxpy<1.6.0,>=1.5.0
|
|
16
|
-
Requires-Dist: pynmea2
|
|
16
|
+
Requires-Dist: pynmea2<2.0.0,>=1.12.0
|
|
17
17
|
Requires-Dist: requests<3.0.0,>=2.20.0
|
|
18
18
|
Requires-Dist: tqdm<5.0,>=4.0
|
|
19
19
|
Requires-Dist: typing_extensions
|
|
@@ -130,7 +130,7 @@ A command line program such as Termux is required. Installation can be done with
|
|
|
130
130
|
commands will install Python 3, pip3, git, and all required libraries for mapillary_tools on Termux:
|
|
131
131
|
|
|
132
132
|
```sh
|
|
133
|
-
pkg install python git build-essential libgeos openssl libjpeg-turbo
|
|
133
|
+
pkg install python git build-essential libgeos openssl libjpeg-turbo libexpat libexpat-static
|
|
134
134
|
pip install --upgrade pip wheel
|
|
135
135
|
pip install --upgrade mapillary_tools
|
|
136
136
|
```
|
|
@@ -108,7 +108,7 @@ A command line program such as Termux is required. Installation can be done with
|
|
|
108
108
|
commands will install Python 3, pip3, git, and all required libraries for mapillary_tools on Termux:
|
|
109
109
|
|
|
110
110
|
```sh
|
|
111
|
-
pkg install python git build-essential libgeos openssl libjpeg-turbo
|
|
111
|
+
pkg install python git build-essential libgeos openssl libjpeg-turbo libexpat libexpat-static
|
|
112
112
|
pip install --upgrade pip wheel
|
|
113
113
|
pip install --upgrade mapillary_tools
|
|
114
114
|
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
VERSION = "0.11.2"
|
|
@@ -9,6 +9,10 @@ MAPILLARY_CLIENT_TOKEN = os.getenv(
|
|
|
9
9
|
MAPILLARY_GRAPH_API_ENDPOINT = os.getenv(
|
|
10
10
|
"MAPILLARY_GRAPH_API_ENDPOINT", "https://graph.mapillary.com"
|
|
11
11
|
)
|
|
12
|
+
# https://requests.readthedocs.io/en/latest/user/advanced/#ssl-cert-verification
|
|
13
|
+
MAPILLARY__DISABLE_VERIFYING_SSL = (
|
|
14
|
+
os.getenv("MAPILLARY__DISABLE_VERIFYING_SSL") == "TRUE"
|
|
15
|
+
)
|
|
12
16
|
REQUESTS_TIMEOUT = 60 # 1 minutes
|
|
13
17
|
|
|
14
18
|
|
|
@@ -18,6 +22,7 @@ def get_upload_token(email: str, password: str) -> requests.Response:
|
|
|
18
22
|
params={"access_token": MAPILLARY_CLIENT_TOKEN},
|
|
19
23
|
json={"email": email, "password": password, "locale": "en_US"},
|
|
20
24
|
timeout=REQUESTS_TIMEOUT,
|
|
25
|
+
verify=not MAPILLARY__DISABLE_VERIFYING_SSL,
|
|
21
26
|
)
|
|
22
27
|
resp.raise_for_status()
|
|
23
28
|
return resp
|
|
@@ -35,6 +40,7 @@ def fetch_organization(
|
|
|
35
40
|
"Authorization": f"OAuth {user_access_token}",
|
|
36
41
|
},
|
|
37
42
|
timeout=REQUESTS_TIMEOUT,
|
|
43
|
+
verify=not MAPILLARY__DISABLE_VERIFYING_SSL,
|
|
38
44
|
)
|
|
39
45
|
resp.raise_for_status()
|
|
40
46
|
return resp
|
|
@@ -56,6 +62,7 @@ def logging(action_type: ActionType, properties: T.Dict) -> requests.Response:
|
|
|
56
62
|
"Authorization": f"OAuth {MAPILLARY_CLIENT_TOKEN}",
|
|
57
63
|
},
|
|
58
64
|
timeout=REQUESTS_TIMEOUT,
|
|
65
|
+
verify=not MAPILLARY__DISABLE_VERIFYING_SSL,
|
|
59
66
|
)
|
|
60
67
|
resp.raise_for_status()
|
|
61
68
|
return resp
|
|
@@ -51,7 +51,11 @@ def prompt_user_for_user_items(user_name: str) -> types.UserItem:
|
|
|
51
51
|
try:
|
|
52
52
|
resp = api_v4.get_upload_token(user_email, user_password)
|
|
53
53
|
except requests.HTTPError as ex:
|
|
54
|
-
if
|
|
54
|
+
if (
|
|
55
|
+
isinstance(ex, requests.HTTPError)
|
|
56
|
+
and isinstance(ex.response, requests.Response)
|
|
57
|
+
and 400 <= ex.response.status_code < 500
|
|
58
|
+
):
|
|
55
59
|
r = ex.response.json()
|
|
56
60
|
subcode = r.get("error", {}).get("error_subcode")
|
|
57
61
|
if subcode in [1348028, 1348092, 3404005, 1348131]:
|
|
@@ -399,7 +399,7 @@ class ExifReadFromXMP(ExifReadABC):
|
|
|
399
399
|
|
|
400
400
|
def extract_capture_time(self) -> T.Optional[datetime.datetime]:
|
|
401
401
|
dt = self.extract_gps_datetime()
|
|
402
|
-
if dt is not None:
|
|
402
|
+
if dt is not None and dt.date() != datetime.date(1970, 1, 1):
|
|
403
403
|
return dt
|
|
404
404
|
|
|
405
405
|
dt = self.extract_exif_datetime()
|
|
@@ -554,7 +554,7 @@ class ExifReadFromEXIF(ExifReadABC):
|
|
|
554
554
|
return None
|
|
555
555
|
|
|
556
556
|
dt = strptime_alternative_formats(gpsdate, ["%Y:%m:%d", "%Y-%m-%d"])
|
|
557
|
-
if dt is None:
|
|
557
|
+
if dt is None or dt == datetime.date(1970, 1, 1):
|
|
558
558
|
return None
|
|
559
559
|
|
|
560
560
|
gpstimestamp = self.tags.get("GPS GPSTimeStamp")
|
|
@@ -632,7 +632,7 @@ class ExifReadFromEXIF(ExifReadABC):
|
|
|
632
632
|
gps_dt = self.extract_gps_datetime()
|
|
633
633
|
except (ValueError, TypeError, ZeroDivisionError):
|
|
634
634
|
gps_dt = None
|
|
635
|
-
if gps_dt is not None:
|
|
635
|
+
if gps_dt is not None and gps_dt.date() != datetime.date(1970, 1, 1):
|
|
636
636
|
return gps_dt
|
|
637
637
|
|
|
638
638
|
dt = self.extract_exif_datetime()
|
|
@@ -266,14 +266,14 @@ class ExifToolRead(exif_read.ExifReadABC):
|
|
|
266
266
|
dt = self.extract_gps_datetime()
|
|
267
267
|
except (ValueError, TypeError, ZeroDivisionError):
|
|
268
268
|
dt = None
|
|
269
|
-
if dt is not None:
|
|
269
|
+
if dt is not None and dt.date() != datetime.date(1970, 1, 1):
|
|
270
270
|
return dt
|
|
271
271
|
|
|
272
272
|
try:
|
|
273
273
|
dt = self.extract_gps_datetime_from_xmp()
|
|
274
274
|
except (ValueError, TypeError, ZeroDivisionError):
|
|
275
275
|
dt = None
|
|
276
|
-
if dt is not None:
|
|
276
|
+
if dt is not None and dt.date() != datetime.date(1970, 1, 1):
|
|
277
277
|
return dt
|
|
278
278
|
|
|
279
279
|
dt = self.extract_exif_datetime()
|
|
@@ -252,12 +252,18 @@ class FFMPEG:
|
|
|
252
252
|
*[
|
|
253
253
|
*["-filter_script:v", select_file.name],
|
|
254
254
|
# Each frame is passed with its timestamp from the demuxer to the muxer
|
|
255
|
-
# vsync is deprecated but -fps_mode is not avaliable on some versions ;(
|
|
256
255
|
*["-vsync", "0"],
|
|
256
|
+
# vsync is deprecated by fps_mode,
|
|
257
|
+
# but fps_mode is not avaliable on some older versions ;(
|
|
257
258
|
# *[f"-fps_mode:{stream_specifier}", "passthrough"],
|
|
258
259
|
# Set the number of video frames to output
|
|
259
260
|
*[f"-frames:{stream_specifier}", str(len(frame_indices))],
|
|
260
|
-
|
|
261
|
+
# Disabled because it doesn't always name the sample images as expected
|
|
262
|
+
# For example "select(n\,1)" we expected the first sample to be IMG_001.JPG
|
|
263
|
+
# but it could be IMG_005.JPG
|
|
264
|
+
# https://www.ffmpeg.org/ffmpeg-formats.html#Options-21
|
|
265
|
+
# If set to 1, expand the filename with pts from pkt->pts. Default value is 0.
|
|
266
|
+
# *["-frame_pts", "1"],
|
|
261
267
|
],
|
|
262
268
|
# video quality level (or the alias -q:v)
|
|
263
269
|
*[f"-qscale:{stream_specifier}", "2"],
|
{mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/process_geotag_properties.py
RENAMED
|
@@ -289,6 +289,7 @@ def _process_videos_beta(vars_args: T.Dict):
|
|
|
289
289
|
"num_processes": vars_args["num_processes"],
|
|
290
290
|
"device_make": vars_args["device_make"],
|
|
291
291
|
"device_model": vars_args["device_model"],
|
|
292
|
+
"check_file_suffix": len(vars_args["filetypes"]) > 1,
|
|
292
293
|
}
|
|
293
294
|
extractor = VideoDataExtractor(options)
|
|
294
295
|
return extractor.process()
|
{mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/process_sequence_properties.py
RENAMED
|
@@ -195,9 +195,11 @@ def _interpolate_subsecs_for_sorting(sequence: PointSequence) -> None:
|
|
|
195
195
|
|
|
196
196
|
t = sequence[gidx].time
|
|
197
197
|
nt = min(
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
198
|
+
(
|
|
199
|
+
sequence[gidx + len(group)].time
|
|
200
|
+
if gidx + len(group) < len(sequence)
|
|
201
|
+
else math.floor(t + 1.0)
|
|
202
|
+
),
|
|
201
203
|
math.floor(t + 1.0),
|
|
202
204
|
)
|
|
203
205
|
assert t <= nt, f"expect sorted but got {t} > {nt}"
|
|
@@ -320,35 +320,37 @@ def _sample_single_video_by_distance(
|
|
|
320
320
|
sample_points_by_frame_idx = _sample_video_stream_by_distance(
|
|
321
321
|
video_metadata.points, video_track_parser, sample_distance
|
|
322
322
|
)
|
|
323
|
+
sorted_sample_indices = sorted(sample_points_by_frame_idx.keys())
|
|
323
324
|
|
|
324
325
|
with wip_dir_context(wip_sample_dir(sample_dir), sample_dir) as wip_dir:
|
|
325
326
|
ffmpeg.extract_specified_frames(
|
|
326
327
|
video_path,
|
|
327
328
|
wip_dir,
|
|
328
|
-
frame_indices=set(
|
|
329
|
+
frame_indices=set(sorted_sample_indices),
|
|
329
330
|
stream_idx=video_stream_idx,
|
|
330
331
|
)
|
|
331
332
|
|
|
332
333
|
frame_samples = ffmpeglib.sort_selected_samples(
|
|
333
334
|
wip_dir, video_path, [video_stream_idx]
|
|
334
335
|
)
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
"
|
|
346
|
-
frame_idx_0based,
|
|
347
|
-
video_stream_idx,
|
|
336
|
+
if len(frame_samples) != len(sorted_sample_indices):
|
|
337
|
+
raise exceptions.MapillaryVideoError(
|
|
338
|
+
f"Expect {len(sorted_sample_indices)} samples but extracted {len(frame_samples)} samples"
|
|
339
|
+
)
|
|
340
|
+
for idx, (frame_idx_1based, sample_paths) in enumerate(frame_samples):
|
|
341
|
+
assert (
|
|
342
|
+
len(sample_paths) == 1
|
|
343
|
+
), "Expect 1 sample path at {frame_idx_1based} but got {sample_paths}"
|
|
344
|
+
if idx + 1 != frame_idx_1based:
|
|
345
|
+
raise exceptions.MapillaryVideoError(
|
|
346
|
+
f"Expect {sample_paths[0]} to be {idx + 1}th sample but got {frame_idx_1based}"
|
|
348
347
|
)
|
|
348
|
+
|
|
349
|
+
for (_, sample_paths), sample_idx in zip(frame_samples, sorted_sample_indices):
|
|
350
|
+
if sample_paths[0] is None:
|
|
349
351
|
continue
|
|
350
352
|
|
|
351
|
-
video_sample, interp =
|
|
353
|
+
video_sample, interp = sample_points_by_frame_idx[sample_idx]
|
|
352
354
|
assert (
|
|
353
355
|
interp.time == video_sample.composition_time_offset
|
|
354
356
|
), f"interpolated time {interp.time} should match the video sample time {video_sample.composition_time_offset}"
|
|
@@ -456,18 +456,15 @@ def map_capture_time_to_datetime(time: str) -> datetime.datetime:
|
|
|
456
456
|
|
|
457
457
|
|
|
458
458
|
@T.overload
|
|
459
|
-
def as_desc(metadata: ImageMetadata) -> ImageDescription:
|
|
460
|
-
...
|
|
459
|
+
def as_desc(metadata: ImageMetadata) -> ImageDescription: ...
|
|
461
460
|
|
|
462
461
|
|
|
463
462
|
@T.overload
|
|
464
|
-
def as_desc(metadata: ErrorMetadata) -> ImageDescriptionError:
|
|
465
|
-
...
|
|
463
|
+
def as_desc(metadata: ErrorMetadata) -> ImageDescriptionError: ...
|
|
466
464
|
|
|
467
465
|
|
|
468
466
|
@T.overload
|
|
469
|
-
def as_desc(metadata: VideoMetadata) -> VideoDescription:
|
|
470
|
-
...
|
|
467
|
+
def as_desc(metadata: VideoMetadata) -> VideoDescription: ...
|
|
471
468
|
|
|
472
469
|
|
|
473
470
|
def as_desc(metadata):
|
|
@@ -524,13 +521,11 @@ def _as_image_desc(metadata: ImageMetadata) -> ImageDescription:
|
|
|
524
521
|
|
|
525
522
|
|
|
526
523
|
@T.overload
|
|
527
|
-
def from_desc(metadata: ImageDescription) -> ImageMetadata:
|
|
528
|
-
...
|
|
524
|
+
def from_desc(metadata: ImageDescription) -> ImageMetadata: ...
|
|
529
525
|
|
|
530
526
|
|
|
531
527
|
@T.overload
|
|
532
|
-
def from_desc(metadata: VideoDescription) -> VideoMetadata:
|
|
533
|
-
...
|
|
528
|
+
def from_desc(metadata: VideoDescription) -> VideoMetadata: ...
|
|
534
529
|
|
|
535
530
|
|
|
536
531
|
def from_desc(desc):
|
|
@@ -62,12 +62,17 @@ class DirectUploadFileType(enum.Enum):
|
|
|
62
62
|
|
|
63
63
|
|
|
64
64
|
def wrap_http_exception(ex: requests.HTTPError):
|
|
65
|
+
req = ex.request
|
|
65
66
|
resp = ex.response
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
if isinstance(resp, requests.Response) and isinstance(req, requests.Request):
|
|
68
|
+
lines = [
|
|
69
|
+
f"{req.method} {resp.url}",
|
|
70
|
+
f"> HTTP Status: {resp.status_code}",
|
|
71
|
+
str(resp.content),
|
|
72
|
+
]
|
|
73
|
+
else:
|
|
74
|
+
lines = []
|
|
75
|
+
|
|
71
76
|
return UploadHTTPError("\n".join(lines))
|
|
72
77
|
|
|
73
78
|
|
|
@@ -713,7 +718,9 @@ def upload(
|
|
|
713
718
|
if isinstance(inner_ex, requests.Timeout):
|
|
714
719
|
raise exceptions.MapillaryUploadTimeoutError(str(inner_ex)) from inner_ex
|
|
715
720
|
|
|
716
|
-
if isinstance(inner_ex, requests.HTTPError)
|
|
721
|
+
if isinstance(inner_ex, requests.HTTPError) and isinstance(
|
|
722
|
+
inner_ex.response, requests.Response
|
|
723
|
+
):
|
|
717
724
|
if inner_ex.response.status_code in [400, 401]:
|
|
718
725
|
try:
|
|
719
726
|
error_body = inner_ex.response.json()
|
|
@@ -15,6 +15,10 @@ MAPILLARY_UPLOAD_ENDPOINT = os.getenv(
|
|
|
15
15
|
MAPILLARY_GRAPH_API_ENDPOINT = os.getenv(
|
|
16
16
|
"MAPILLARY_GRAPH_API_ENDPOINT", "https://graph.mapillary.com"
|
|
17
17
|
)
|
|
18
|
+
# https://requests.readthedocs.io/en/latest/user/advanced/#ssl-cert-verification
|
|
19
|
+
MAPILLARY__DISABLE_VERIFYING_SSL = (
|
|
20
|
+
os.getenv("MAPILLARY__DISABLE_VERIFYING_SSL") == "TRUE"
|
|
21
|
+
)
|
|
18
22
|
DEFAULT_CHUNK_SIZE = 1024 * 1024 * 16 # 16MB
|
|
19
23
|
# According to the docs, UPLOAD_REQUESTS_TIMEOUT can be a tuple of
|
|
20
24
|
# (connection_timeout, read_timeout): https://requests.readthedocs.io/en/latest/user/advanced/#timeouts
|
|
@@ -97,6 +101,7 @@ class UploadService:
|
|
|
97
101
|
url,
|
|
98
102
|
headers=headers,
|
|
99
103
|
timeout=REQUESTS_TIMEOUT,
|
|
104
|
+
verify=not MAPILLARY__DISABLE_VERIFYING_SSL,
|
|
100
105
|
)
|
|
101
106
|
LOG.debug("HTTP response %s: %s", resp.status_code, resp.content)
|
|
102
107
|
resp.raise_for_status()
|
|
@@ -139,6 +144,7 @@ class UploadService:
|
|
|
139
144
|
headers=headers,
|
|
140
145
|
data=chunk,
|
|
141
146
|
timeout=UPLOAD_REQUESTS_TIMEOUT,
|
|
147
|
+
verify=not MAPILLARY__DISABLE_VERIFYING_SSL,
|
|
142
148
|
)
|
|
143
149
|
LOG.debug(
|
|
144
150
|
"HTTP response %s: %s", resp.status_code, _truncate_end(resp.content)
|
|
@@ -185,6 +191,7 @@ class UploadService:
|
|
|
185
191
|
headers=headers,
|
|
186
192
|
json=data,
|
|
187
193
|
timeout=REQUESTS_TIMEOUT,
|
|
194
|
+
verify=not MAPILLARY__DISABLE_VERIFYING_SSL,
|
|
188
195
|
)
|
|
189
196
|
LOG.debug("HTTP response %s: %s", resp.status_code, _truncate_end(resp.content))
|
|
190
197
|
|
|
@@ -321,7 +321,11 @@ def _extract_upload_md5sum(fp: T.IO[bytes]) -> T.Optional[str]:
|
|
|
321
321
|
|
|
322
322
|
|
|
323
323
|
def _is_immediate_retry(ex: Exception):
|
|
324
|
-
if
|
|
324
|
+
if (
|
|
325
|
+
isinstance(ex, requests.HTTPError)
|
|
326
|
+
and isinstance(ex.response, requests.Response)
|
|
327
|
+
and ex.response.status_code == 412
|
|
328
|
+
):
|
|
325
329
|
try:
|
|
326
330
|
resp = ex.response.json()
|
|
327
331
|
except json.JSONDecodeError:
|
|
@@ -334,7 +338,9 @@ def _is_retriable_exception(ex: Exception):
|
|
|
334
338
|
if isinstance(ex, (requests.ConnectionError, requests.Timeout)):
|
|
335
339
|
return True
|
|
336
340
|
|
|
337
|
-
if isinstance(ex, requests.HTTPError)
|
|
341
|
+
if isinstance(ex, requests.HTTPError) and isinstance(
|
|
342
|
+
ex.response, requests.Response
|
|
343
|
+
):
|
|
338
344
|
if 400 <= ex.response.status_code < 500:
|
|
339
345
|
try:
|
|
340
346
|
resp = ex.response.json()
|
|
@@ -33,7 +33,9 @@ class VideoDataExtractor:
|
|
|
33
33
|
def process(self) -> T.List[MetadataOrError]:
|
|
34
34
|
paths = self.options["paths"]
|
|
35
35
|
self._check_paths(paths)
|
|
36
|
-
video_files = utils.find_videos(
|
|
36
|
+
video_files = utils.find_videos(
|
|
37
|
+
paths, check_file_suffix=self.options["check_file_suffix"]
|
|
38
|
+
)
|
|
37
39
|
self._check_sources_cardinality(video_files)
|
|
38
40
|
|
|
39
41
|
num_processes = self.options["num_processes"] or None
|
|
@@ -102,10 +104,12 @@ class VideoDataExtractor:
|
|
|
102
104
|
else:
|
|
103
105
|
return ErrorMetadata(
|
|
104
106
|
filename=file,
|
|
105
|
-
error=
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
error=(
|
|
108
|
+
ex
|
|
109
|
+
if ex
|
|
110
|
+
else exceptions.MapillaryVideoGPSNotFoundError(
|
|
111
|
+
"No GPS data found from the video"
|
|
112
|
+
)
|
|
109
113
|
),
|
|
110
114
|
filetype=FileType.VIDEO,
|
|
111
115
|
)
|
|
@@ -30,13 +30,17 @@ class ExiftoolRuntimeParser(BaseParser):
|
|
|
30
30
|
):
|
|
31
31
|
super().__init__(video_path, options, parser_options)
|
|
32
32
|
exiftool_path = shutil.which(constants.EXIFTOOL_PATH)
|
|
33
|
+
|
|
33
34
|
if not exiftool_path:
|
|
34
35
|
raise exceptions.MapillaryExiftoolNotFoundError(
|
|
35
36
|
"Cannot execute exiftool. Please install it from https://exiftool.org/ or you package manager, or set the environment variable MAPILLARY_TOOLS_EXIFTOOL_PATH"
|
|
36
37
|
)
|
|
37
|
-
|
|
38
38
|
if not self.geotag_source_path:
|
|
39
39
|
return
|
|
40
|
+
|
|
41
|
+
# To handle non-latin1 filenames under Windows, we pass the path
|
|
42
|
+
# via stdin. See https://exiftool.org/faq.html#Q18
|
|
43
|
+
stdin = str(self.geotag_source_path)
|
|
40
44
|
args = [
|
|
41
45
|
exiftool_path,
|
|
42
46
|
"-q",
|
|
@@ -46,13 +50,18 @@ class ExiftoolRuntimeParser(BaseParser):
|
|
|
46
50
|
"-api",
|
|
47
51
|
"LargeFileSupport=1",
|
|
48
52
|
"-X",
|
|
49
|
-
|
|
53
|
+
"-charset",
|
|
54
|
+
"filename=utf8",
|
|
55
|
+
"-@",
|
|
56
|
+
"-",
|
|
50
57
|
]
|
|
51
58
|
|
|
52
|
-
|
|
59
|
+
process = subprocess.run(
|
|
60
|
+
args, capture_output=True, text=True, input=stdin, encoding="utf-8"
|
|
61
|
+
)
|
|
53
62
|
|
|
54
63
|
self.exiftoolXmlParser = ExiftoolXmlParser(
|
|
55
|
-
video_path, options, parser_options,
|
|
64
|
+
video_path, options, parser_options, process.stdout
|
|
56
65
|
)
|
|
57
66
|
|
|
58
67
|
def extract_points(self) -> T.Sequence[geo.Point]:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
|
-
Name:
|
|
3
|
-
Version: 0.11.
|
|
2
|
+
Name: mapillary_tools
|
|
3
|
+
Version: 0.11.2
|
|
4
4
|
Summary: Mapillary Image/Video Import Pipeline
|
|
5
5
|
Home-page: https://github.com/mapillary/mapillary_tools
|
|
6
6
|
Author: Mapillary
|
|
@@ -13,7 +13,7 @@ Requires-Dist: construct<3.0.0,>=2.10.0
|
|
|
13
13
|
Requires-Dist: exifread==2.3.2
|
|
14
14
|
Requires-Dist: piexif==1.1.3
|
|
15
15
|
Requires-Dist: gpxpy<1.6.0,>=1.5.0
|
|
16
|
-
Requires-Dist: pynmea2
|
|
16
|
+
Requires-Dist: pynmea2<2.0.0,>=1.12.0
|
|
17
17
|
Requires-Dist: requests<3.0.0,>=2.20.0
|
|
18
18
|
Requires-Dist: tqdm<5.0,>=4.0
|
|
19
19
|
Requires-Dist: typing_extensions
|
|
@@ -130,7 +130,7 @@ A command line program such as Termux is required. Installation can be done with
|
|
|
130
130
|
commands will install Python 3, pip3, git, and all required libraries for mapillary_tools on Termux:
|
|
131
131
|
|
|
132
132
|
```sh
|
|
133
|
-
pkg install python git build-essential libgeos openssl libjpeg-turbo
|
|
133
|
+
pkg install python git build-essential libgeos openssl libjpeg-turbo libexpat libexpat-static
|
|
134
134
|
pip install --upgrade pip wheel
|
|
135
135
|
pip install --upgrade mapillary_tools
|
|
136
136
|
```
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
VERSION = "0.11.0b4"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/commands/authenticate.py
RENAMED
|
File without changes
|
|
File without changes
|
{mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/commands/process_and_upload.py
RENAMED
|
File without changes
|
{mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/commands/sample_video.py
RENAMED
|
File without changes
|
|
File without changes
|
{mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/commands/upload_blackvue.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/commands/video_process.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/blackvue_parser.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/construct_mp4_parser.py
RENAMED
|
File without changes
|
{mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/geotag_from_generic.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/geotag_images_from_gpx.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/gpmf_gps_filter.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/mp4_sample_parser.py
RENAMED
|
File without changes
|
{mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/simple_mp4_builder.py
RENAMED
|
File without changes
|
{mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools/geotag/simple_mp4_parser.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{mapillary_tools-0.11.0b4 → mapillary_tools-0.11.2}/mapillary_tools.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|