mapillary-downloader 0.4.0__tar.gz → 0.4.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_downloader-0.4.0 → mapillary_downloader-0.4.2}/PKG-INFO +9 -15
- {mapillary_downloader-0.4.0 → mapillary_downloader-0.4.2}/README.md +8 -14
- {mapillary_downloader-0.4.0 → mapillary_downloader-0.4.2}/pyproject.toml +1 -1
- {mapillary_downloader-0.4.0 → mapillary_downloader-0.4.2}/src/mapillary_downloader/__main__.py +12 -0
- {mapillary_downloader-0.4.0 → mapillary_downloader-0.4.2}/src/mapillary_downloader/client.py +2 -0
- {mapillary_downloader-0.4.0 → mapillary_downloader-0.4.2}/src/mapillary_downloader/downloader.py +3 -2
- {mapillary_downloader-0.4.0 → mapillary_downloader-0.4.2}/src/mapillary_downloader/exif_writer.py +15 -3
- {mapillary_downloader-0.4.0 → mapillary_downloader-0.4.2}/src/mapillary_downloader/ia_meta.py +26 -5
- {mapillary_downloader-0.4.0 → mapillary_downloader-0.4.2}/LICENSE.md +0 -0
- {mapillary_downloader-0.4.0 → mapillary_downloader-0.4.2}/src/mapillary_downloader/__init__.py +0 -0
- {mapillary_downloader-0.4.0 → mapillary_downloader-0.4.2}/src/mapillary_downloader/ia_check.py +0 -0
- {mapillary_downloader-0.4.0 → mapillary_downloader-0.4.2}/src/mapillary_downloader/logging_config.py +0 -0
- {mapillary_downloader-0.4.0 → mapillary_downloader-0.4.2}/src/mapillary_downloader/tar_sequences.py +0 -0
- {mapillary_downloader-0.4.0 → mapillary_downloader-0.4.2}/src/mapillary_downloader/utils.py +0 -0
- {mapillary_downloader-0.4.0 → mapillary_downloader-0.4.2}/src/mapillary_downloader/webp_converter.py +0 -0
- {mapillary_downloader-0.4.0 → mapillary_downloader-0.4.2}/src/mapillary_downloader/worker.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mapillary_downloader
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.2
|
|
4
4
|
Summary: Download your Mapillary data before it's gone
|
|
5
5
|
Author-email: Gareth Davidson <gaz@bitplane.net>
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -72,18 +72,17 @@ mapillary-downloader --output ./downloads USERNAME1
|
|
|
72
72
|
|
|
73
73
|
The downloader will:
|
|
74
74
|
|
|
75
|
+
* 🏛️ Check Internet Archive to avoid duplicate downloads
|
|
75
76
|
* 📷 Download multiple users' images organized by sequence
|
|
76
77
|
* 📜 Inject EXIF metadata (GPS coordinates, camera info, timestamps,
|
|
77
78
|
compass direction)
|
|
79
|
+
* 🗜️ Convert to WebP (by default) to save ~70% disk space
|
|
78
80
|
* 🛟 Save progress so you can safely resume if interrupted
|
|
79
|
-
*
|
|
80
|
-
* 📦 Tar sequence directories for faster uploads
|
|
81
|
-
* 🏛️ Check Internet Archive to avoid duplicate downloads
|
|
82
|
-
* 💾 Stage downloads in cache, move atomically when complete
|
|
81
|
+
* 📦 Tar sequence directories (by default) for faster uploads to Internet Archive
|
|
83
82
|
|
|
84
83
|
## WebP Conversion
|
|
85
84
|
|
|
86
|
-
|
|
85
|
+
You'll need the `cwebp` binary installed:
|
|
87
86
|
|
|
88
87
|
```bash
|
|
89
88
|
# Debian/Ubuntu
|
|
@@ -105,18 +104,13 @@ By default, sequence directories are automatically tarred after download because
|
|
|
105
104
|
if they weren't, you'd spend more time setting up upload metadata than actually
|
|
106
105
|
uploading files to IA.
|
|
107
106
|
|
|
108
|
-
To keep individual files instead of creating tars, use the `--no-tar` flag
|
|
109
|
-
|
|
110
|
-
```bash
|
|
111
|
-
mapillary-downloader --no-tar USERNAME
|
|
112
|
-
```
|
|
107
|
+
To keep individual files instead of creating tars, use the `--no-tar` flag.
|
|
113
108
|
|
|
114
109
|
## Internet Archive upload
|
|
115
110
|
|
|
116
111
|
I've written a bash tool to rip media then tag, queue, and upload to The
|
|
117
|
-
Internet Archive. The metadata is in the same format. If you
|
|
118
|
-
|
|
119
|
-
appropriately named item.
|
|
112
|
+
Internet Archive. The metadata is in the same format. If you symlink your
|
|
113
|
+
`./mapillary_data` dir to `rip`'s `4.ship` dir, they'll be queued for upload.
|
|
120
114
|
|
|
121
115
|
See inlay for details:
|
|
122
116
|
|
|
@@ -138,7 +132,7 @@ make help # See other make options
|
|
|
138
132
|
* [📖 pydoc](https://bitplane.net/dev/python/mapillary_downloader/pydoc)
|
|
139
133
|
* [🐍 pypi](https://pypi.org/project/mapillary-downloader)
|
|
140
134
|
* [🐱 github](https://github.com/bitplane/mapillary_downloader)
|
|
141
|
-
* [📀 rip](https://bitplane.net/dev/sh/rip
|
|
135
|
+
* [📀 rip](https://bitplane.net/dev/sh/rip)
|
|
142
136
|
|
|
143
137
|
## License
|
|
144
138
|
|
|
@@ -42,18 +42,17 @@ mapillary-downloader --output ./downloads USERNAME1
|
|
|
42
42
|
|
|
43
43
|
The downloader will:
|
|
44
44
|
|
|
45
|
+
* 🏛️ Check Internet Archive to avoid duplicate downloads
|
|
45
46
|
* 📷 Download multiple users' images organized by sequence
|
|
46
47
|
* 📜 Inject EXIF metadata (GPS coordinates, camera info, timestamps,
|
|
47
48
|
compass direction)
|
|
49
|
+
* 🗜️ Convert to WebP (by default) to save ~70% disk space
|
|
48
50
|
* 🛟 Save progress so you can safely resume if interrupted
|
|
49
|
-
*
|
|
50
|
-
* 📦 Tar sequence directories for faster uploads
|
|
51
|
-
* 🏛️ Check Internet Archive to avoid duplicate downloads
|
|
52
|
-
* 💾 Stage downloads in cache, move atomically when complete
|
|
51
|
+
* 📦 Tar sequence directories (by default) for faster uploads to Internet Archive
|
|
53
52
|
|
|
54
53
|
## WebP Conversion
|
|
55
54
|
|
|
56
|
-
|
|
55
|
+
You'll need the `cwebp` binary installed:
|
|
57
56
|
|
|
58
57
|
```bash
|
|
59
58
|
# Debian/Ubuntu
|
|
@@ -75,18 +74,13 @@ By default, sequence directories are automatically tarred after download because
|
|
|
75
74
|
if they weren't, you'd spend more time setting up upload metadata than actually
|
|
76
75
|
uploading files to IA.
|
|
77
76
|
|
|
78
|
-
To keep individual files instead of creating tars, use the `--no-tar` flag
|
|
79
|
-
|
|
80
|
-
```bash
|
|
81
|
-
mapillary-downloader --no-tar USERNAME
|
|
82
|
-
```
|
|
77
|
+
To keep individual files instead of creating tars, use the `--no-tar` flag.
|
|
83
78
|
|
|
84
79
|
## Internet Archive upload
|
|
85
80
|
|
|
86
81
|
I've written a bash tool to rip media then tag, queue, and upload to The
|
|
87
|
-
Internet Archive. The metadata is in the same format. If you
|
|
88
|
-
|
|
89
|
-
appropriately named item.
|
|
82
|
+
Internet Archive. The metadata is in the same format. If you symlink your
|
|
83
|
+
`./mapillary_data` dir to `rip`'s `4.ship` dir, they'll be queued for upload.
|
|
90
84
|
|
|
91
85
|
See inlay for details:
|
|
92
86
|
|
|
@@ -108,7 +102,7 @@ make help # See other make options
|
|
|
108
102
|
* [📖 pydoc](https://bitplane.net/dev/python/mapillary_downloader/pydoc)
|
|
109
103
|
* [🐍 pypi](https://pypi.org/project/mapillary-downloader)
|
|
110
104
|
* [🐱 github](https://github.com/bitplane/mapillary_downloader)
|
|
111
|
-
* [📀 rip](https://bitplane.net/dev/sh/rip
|
|
105
|
+
* [📀 rip](https://bitplane.net/dev/sh/rip)
|
|
112
106
|
|
|
113
107
|
## License
|
|
114
108
|
|
{mapillary_downloader-0.4.0 → mapillary_downloader-0.4.2}/src/mapillary_downloader/__main__.py
RENAMED
|
@@ -56,9 +56,21 @@ def main():
|
|
|
56
56
|
action="store_true",
|
|
57
57
|
help="Don't check if collection exists on Internet Archive before downloading",
|
|
58
58
|
)
|
|
59
|
+
parser.add_argument(
|
|
60
|
+
"--debug",
|
|
61
|
+
action="store_true",
|
|
62
|
+
help="Enable debug logging (EXIF data, API responses, etc.)",
|
|
63
|
+
)
|
|
59
64
|
|
|
60
65
|
args = parser.parse_args()
|
|
61
66
|
|
|
67
|
+
# Set debug logging level if requested
|
|
68
|
+
if args.debug:
|
|
69
|
+
import logging
|
|
70
|
+
|
|
71
|
+
logging.getLogger("mapillary_downloader").setLevel(logging.DEBUG)
|
|
72
|
+
logger.debug("Debug logging enabled")
|
|
73
|
+
|
|
62
74
|
# Check for token
|
|
63
75
|
if not args.token:
|
|
64
76
|
logger.error("Error: Mapillary API token required. Use --token or set MAPILLARY_TOKEN environment variable")
|
{mapillary_downloader-0.4.0 → mapillary_downloader-0.4.2}/src/mapillary_downloader/client.py
RENAMED
|
@@ -92,8 +92,10 @@ class MapillaryClient:
|
|
|
92
92
|
images = data.get("data", [])
|
|
93
93
|
total_fetched += len(images)
|
|
94
94
|
logger.info(f"Fetched metadata for {total_fetched:,} images...")
|
|
95
|
+
logger.debug(f"API response paging: {data.get('paging', {})}")
|
|
95
96
|
|
|
96
97
|
for image in images:
|
|
98
|
+
logger.debug(f"Image metadata: {image}")
|
|
97
99
|
yield image
|
|
98
100
|
|
|
99
101
|
# Get next page URL
|
{mapillary_downloader-0.4.0 → mapillary_downloader-0.4.2}/src/mapillary_downloader/downloader.py
RENAMED
|
@@ -95,8 +95,9 @@ class MapillaryDownloader:
|
|
|
95
95
|
logger.info(f"Staging directory: {self.staging_dir}")
|
|
96
96
|
logger.info(f"Final destination: {self.final_dir}")
|
|
97
97
|
|
|
98
|
-
# Set up file logging for archival
|
|
99
|
-
|
|
98
|
+
# Set up file logging for archival with timestamp for incremental runs
|
|
99
|
+
timestamp = time.strftime("%Y%m%d-%H%M%S")
|
|
100
|
+
log_file = self.output_dir / f"download.log.{timestamp}"
|
|
100
101
|
add_file_handler(log_file)
|
|
101
102
|
logger.info(f"Logging to: {log_file}")
|
|
102
103
|
|
{mapillary_downloader-0.4.0 → mapillary_downloader-0.4.2}/src/mapillary_downloader/exif_writer.py
RENAMED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
"""EXIF metadata writer for Mapillary images."""
|
|
2
2
|
|
|
3
|
+
import logging
|
|
3
4
|
import piexif
|
|
4
5
|
from datetime import datetime
|
|
5
6
|
|
|
7
|
+
logger = logging.getLogger("mapillary_downloader")
|
|
8
|
+
|
|
6
9
|
|
|
7
10
|
def decimal_to_dms(decimal):
|
|
8
11
|
"""Convert decimal degrees to degrees, minutes, seconds format for EXIF.
|
|
@@ -47,6 +50,9 @@ def write_exif_to_image(image_path, metadata):
|
|
|
47
50
|
True if successful, False otherwise
|
|
48
51
|
"""
|
|
49
52
|
try:
|
|
53
|
+
logger.debug(f"Writing EXIF to {image_path}")
|
|
54
|
+
logger.debug(f"Metadata: {metadata}")
|
|
55
|
+
|
|
50
56
|
# Load existing EXIF data if any
|
|
51
57
|
try:
|
|
52
58
|
exif_dict = piexif.load(str(image_path))
|
|
@@ -99,13 +105,17 @@ def write_exif_to_image(image_path, metadata):
|
|
|
99
105
|
# GPS Altitude - prefer computed_altitude over altitude
|
|
100
106
|
altitude = metadata.get("computed_altitude") or metadata.get("altitude")
|
|
101
107
|
if altitude is not None:
|
|
102
|
-
|
|
108
|
+
altitude_val = int(abs(altitude) * 100)
|
|
109
|
+
logger.debug(f"Raw altitude value: {altitude}, calculated: {altitude_val}")
|
|
110
|
+
exif_dict["GPS"][piexif.GPSIFD.GPSAltitude] = (altitude_val, 100)
|
|
103
111
|
exif_dict["GPS"][piexif.GPSIFD.GPSAltitudeRef] = 1 if altitude < 0 else 0
|
|
104
112
|
|
|
105
113
|
# GPS Compass direction
|
|
106
114
|
compass = metadata.get("computed_compass_angle") or metadata.get("compass_angle")
|
|
107
115
|
if compass is not None:
|
|
108
|
-
|
|
116
|
+
# Normalize compass to 0-360 range
|
|
117
|
+
compass_val = int((compass % 360) * 100)
|
|
118
|
+
exif_dict["GPS"][piexif.GPSIFD.GPSImgDirection] = (compass_val, 100)
|
|
109
119
|
exif_dict["GPS"][piexif.GPSIFD.GPSImgDirectionRef] = b"T" # True north
|
|
110
120
|
|
|
111
121
|
# GPS Version
|
|
@@ -115,8 +125,10 @@ def write_exif_to_image(image_path, metadata):
|
|
|
115
125
|
exif_bytes = piexif.dump(exif_dict)
|
|
116
126
|
piexif.insert(exif_bytes, str(image_path))
|
|
117
127
|
|
|
128
|
+
logger.debug(f"Successfully wrote EXIF to {image_path}")
|
|
118
129
|
return True
|
|
119
130
|
|
|
120
131
|
except Exception as e:
|
|
121
|
-
|
|
132
|
+
logger.warning(f"Failed to write EXIF data to {image_path}: {e}")
|
|
133
|
+
logger.debug(f"Full metadata: {metadata}")
|
|
122
134
|
return False
|
{mapillary_downloader-0.4.0 → mapillary_downloader-0.4.2}/src/mapillary_downloader/ia_meta.py
RENAMED
|
@@ -128,6 +128,10 @@ def generate_ia_metadata(collection_dir):
|
|
|
128
128
|
logger.warning("Could not determine date range from metadata")
|
|
129
129
|
first_date = last_date = "unknown"
|
|
130
130
|
|
|
131
|
+
# Detect WebP conversion and tarring
|
|
132
|
+
is_webp = "-webp" in collection_dir.name
|
|
133
|
+
has_tars = len(list(collection_dir.glob("*.tar"))) > 0
|
|
134
|
+
|
|
131
135
|
# Create .meta directory
|
|
132
136
|
meta_dir = collection_dir / ".meta"
|
|
133
137
|
meta_dir.mkdir(exist_ok=True)
|
|
@@ -139,14 +143,31 @@ def generate_ia_metadata(collection_dir):
|
|
|
139
143
|
f"Mapillary images by {username}",
|
|
140
144
|
)
|
|
141
145
|
|
|
146
|
+
# Build resolution string
|
|
147
|
+
if quality == "original":
|
|
148
|
+
resolution_str = "original resolution"
|
|
149
|
+
else:
|
|
150
|
+
resolution_str = f"{quality}px resolution"
|
|
151
|
+
|
|
152
|
+
# Build description with processing details
|
|
142
153
|
description = (
|
|
143
154
|
f"Street-level imagery from Mapillary user '{username}'. "
|
|
144
|
-
f"Contains {image_count:,} images captured between {first_date} and {last_date}.
|
|
145
|
-
f"Images are organized by sequence ID and include EXIF metadata with GPS coordinates, "
|
|
146
|
-
f"camera information, and compass direction.\n\n"
|
|
147
|
-
f"Downloaded using mapillary_downloader (https://bitplane.net/dev/python/mapillary_downloader/). "
|
|
148
|
-
f"Uploaded using rip (https://bitplane.net/dev/sh/rip)."
|
|
155
|
+
f"Contains {image_count:,} images in {resolution_str} captured between {first_date} and {last_date}."
|
|
149
156
|
)
|
|
157
|
+
|
|
158
|
+
if has_tars:
|
|
159
|
+
description += " Sequences have been individually tarred."
|
|
160
|
+
|
|
161
|
+
if is_webp:
|
|
162
|
+
description += " Images were recompressed with WebP."
|
|
163
|
+
|
|
164
|
+
description += (
|
|
165
|
+
" Images are organized by sequence ID and include EXIF metadata with GPS coordinates, "
|
|
166
|
+
"camera information, and compass direction.\n\n"
|
|
167
|
+
"Downloaded using mapillary_downloader (https://bitplane.net/dev/python/mapillary_downloader/). "
|
|
168
|
+
"Uploaded using rip (https://bitplane.net/dev/sh/rip)."
|
|
169
|
+
)
|
|
170
|
+
|
|
150
171
|
write_meta_tag(meta_dir, "description", description)
|
|
151
172
|
|
|
152
173
|
# Subject tags
|
|
File without changes
|
{mapillary_downloader-0.4.0 → mapillary_downloader-0.4.2}/src/mapillary_downloader/__init__.py
RENAMED
|
File without changes
|
{mapillary_downloader-0.4.0 → mapillary_downloader-0.4.2}/src/mapillary_downloader/ia_check.py
RENAMED
|
File without changes
|
{mapillary_downloader-0.4.0 → mapillary_downloader-0.4.2}/src/mapillary_downloader/logging_config.py
RENAMED
|
File without changes
|
{mapillary_downloader-0.4.0 → mapillary_downloader-0.4.2}/src/mapillary_downloader/tar_sequences.py
RENAMED
|
File without changes
|
|
File without changes
|
{mapillary_downloader-0.4.0 → mapillary_downloader-0.4.2}/src/mapillary_downloader/webp_converter.py
RENAMED
|
File without changes
|
{mapillary_downloader-0.4.0 → mapillary_downloader-0.4.2}/src/mapillary_downloader/worker.py
RENAMED
|
File without changes
|