77import os
88import typing as T
99
10+ import humanize
11+
1012from . import constants , exceptions , geo , types , utils
1113from .serializer .description import DescriptionJSONSerializer
1214
@@ -215,7 +217,7 @@ def _is_video_stationary(
215217def _check_video_limits (
216218 video_metadatas : T .Iterable [types .VideoMetadata ],
217219 max_sequence_filesize_in_bytes : int | None ,
218- max_avg_speed : float ,
220+ max_capture_speed_kmh : float ,
219221 max_radius_for_stationary_check : float ,
220222) -> tuple [list [types .VideoMetadata ], list [types .ErrorMetadata ]]:
221223 output_video_metadatas : list [types .VideoMetadata ] = []
@@ -238,7 +240,7 @@ def _check_video_limits(
238240 )
239241 if video_filesize > max_sequence_filesize_in_bytes :
240242 raise exceptions .MapillaryFileTooLargeError (
241- f"Video file size exceeds the maximum allowed file size ( { max_sequence_filesize_in_bytes } bytes) " ,
243+ f"Video file size { humanize . naturalsize ( video_filesize ) } exceeds max allowed { humanize . naturalsize ( max_sequence_filesize_in_bytes ) } " ,
242244 )
243245
244246 contains_null_island = any (
@@ -249,15 +251,19 @@ def _check_video_limits(
249251 "GPS coordinates in Null Island (0, 0)"
250252 )
251253
254+ avg_speed_kmh = (
255+ geo .avg_speed (video_metadata .points ) * 3.6
256+ ) # Convert m/s to km/h
252257 too_fast = (
253258 len (video_metadata .points ) >= 2
254- and geo . avg_speed ( video_metadata . points ) > max_avg_speed
259+ and avg_speed_kmh > max_capture_speed_kmh
255260 )
256261 if too_fast :
257262 raise exceptions .MapillaryCaptureSpeedTooFastError (
258- f"Capture speed too fast ( exceeds { round ( max_avg_speed , 3 ) } m/s) " ,
263+ f"Capture speed { avg_speed_kmh :.3f } km/h exceeds max allowed { max_capture_speed_kmh :.3f } km/h " ,
259264 )
260265 except exceptions .MapillaryDescriptionError as ex :
266+ LOG .error (f"{ _video_name (video_metadata )} : { ex } " )
261267 error_metadatas .append (
262268 types .describe_error_metadata (
263269 exc = ex ,
@@ -268,18 +274,17 @@ def _check_video_limits(
268274 else :
269275 output_video_metadatas .append (video_metadata )
270276
271- if error_metadatas :
272- LOG .info (
273- f"Video validation: { len (output_video_metadatas )} valid, { len (error_metadatas )} errors"
274- )
275-
276277 return output_video_metadatas , error_metadatas
277278
278279
280+ def _video_name (video_metadata : types .VideoMetadata ) -> str :
281+ return video_metadata .filename .name
282+
283+
279284def _check_sequences_by_limits (
280285 input_sequences : T .Sequence [PointSequence ],
281286 max_sequence_filesize_in_bytes : int | None ,
282- max_avg_speed : float ,
287+ max_capture_speed_kmh : float ,
283288) -> tuple [list [PointSequence ], list [types .ErrorMetadata ]]:
284289 output_sequences : list [PointSequence ] = []
285290 output_errors : list [types .ErrorMetadata ] = []
@@ -295,7 +300,7 @@ def _check_sequences_by_limits(
295300 )
296301 if sequence_filesize > max_sequence_filesize_in_bytes :
297302 raise exceptions .MapillaryFileTooLargeError (
298- f"Sequence file size exceeds the maximum allowed file size ( { max_sequence_filesize_in_bytes } bytes) " ,
303+ f"Sequence file size { humanize . naturalsize ( sequence_filesize ) } exceeds max allowed { humanize . naturalsize ( max_sequence_filesize_in_bytes ) } " ,
299304 )
300305
301306 contains_null_island = any (
@@ -306,12 +311,14 @@ def _check_sequences_by_limits(
306311 "GPS coordinates in Null Island (0, 0)"
307312 )
308313
309- too_fast = len (sequence ) >= 2 and geo .avg_speed (sequence ) > max_avg_speed
314+ avg_speed_kmh = geo .avg_speed (sequence ) * 3.6 # Convert m/s to km/h
315+ too_fast = len (sequence ) >= 2 and avg_speed_kmh > max_capture_speed_kmh
310316 if too_fast :
311317 raise exceptions .MapillaryCaptureSpeedTooFastError (
312- f"Capture speed too fast ( exceeds { round ( max_avg_speed , 3 ) } m/s) " ,
318+ f"Capture speed { avg_speed_kmh :.3f } km/h exceeds max allowed { max_capture_speed_kmh :.3f } km/h " ,
313319 )
314320 except exceptions .MapillaryDescriptionError as ex :
321+ LOG .error (f"{ _sequence_name (sequence )} : { ex } " )
315322 for image in sequence :
316323 output_errors .append (
317324 types .describe_error_metadata (
@@ -326,14 +333,16 @@ def _check_sequences_by_limits(
326333 len (s ) for s in input_sequences
327334 )
328335
329- if output_errors :
330- LOG .info (
331- f"Sequence validation: { len (output_sequences )} valid, { len (output_errors )} errors"
332- )
333-
334336 return output_sequences , output_errors
335337
336338
339+ def _sequence_name (sequence : T .Sequence [types .ImageMetadata ]) -> str :
340+ if not sequence :
341+ return "N/A"
342+ image = sequence [0 ]
343+ return f"{ image .filename .parent .name } /{ image .filename .name } "
344+
345+
337346def _group_by_folder_and_camera (
338347 image_metadatas : list [types .ImageMetadata ],
339348) -> list [list [types .ImageMetadata ]]:
@@ -594,8 +603,10 @@ def process_sequence_properties(
594603 interpolate_directions : bool = False ,
595604 duplicate_distance : float = constants .DUPLICATE_DISTANCE ,
596605 duplicate_angle : float = constants .DUPLICATE_ANGLE ,
597- max_avg_speed : float = constants .MAX_AVG_SPEED ,
606+ max_capture_speed_kmh : float = constants .MAX_CAPTURE_SPEED_KMH ,
598607) -> list [types .MetadataOrError ]:
608+ LOG .info ("==> Processing sequences..." )
609+
599610 max_sequence_filesize_in_bytes = constants .MAX_SEQUENCE_FILESIZE
600611 max_sequence_pixels = constants .MAX_SEQUENCE_PIXELS
601612
@@ -611,14 +622,14 @@ def process_sequence_properties(
611622 elif isinstance (metadata , types .VideoMetadata ):
612623 video_metadatas .append (metadata )
613624 else :
614- raise RuntimeError (f"invalid metadata type: { metadata } " )
625+ raise ValueError (f"invalid metadata type: { metadata } " )
615626
616627 if video_metadatas :
617628 # Check limits for videos
618629 video_metadatas , video_error_metadatas = _check_video_limits (
619630 video_metadatas ,
620631 max_sequence_filesize_in_bytes = max_sequence_filesize_in_bytes ,
621- max_avg_speed = max_avg_speed ,
632+ max_capture_speed_kmh = max_capture_speed_kmh ,
622633 max_radius_for_stationary_check = 10.0 ,
623634 )
624635 error_metadatas .extend (video_error_metadatas )
@@ -668,7 +679,7 @@ def process_sequence_properties(
668679 sequences , errors = _check_sequences_by_limits (
669680 sequences ,
670681 max_sequence_filesize_in_bytes = max_sequence_filesize_in_bytes ,
671- max_avg_speed = max_avg_speed ,
682+ max_capture_speed_kmh = max_capture_speed_kmh ,
672683 )
673684 error_metadatas .extend (errors )
674685
0 commit comments