pymcap-cli 0.12.0__tar.gz → 0.14.0__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.
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/PKG-INFO +131 -17
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/README.md +122 -15
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/pyproject.toml +12 -2
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cli.py +4 -1
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/_run_processor.py +21 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/bag2mcap_cmd.py +1 -0
- pymcap_cli-0.14.0/src/pymcap_cli/cmd/compress_cmd.py +152 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/convert_cmd.py +1 -0
- pymcap_cli-0.14.0/src/pymcap_cli/cmd/index/__init__.py +45 -0
- pymcap_cli-0.14.0/src/pymcap_cli/cmd/index/_helpers.py +456 -0
- pymcap_cli-0.14.0/src/pymcap_cli/cmd/index/duplicates_cmd.py +152 -0
- pymcap_cli-0.14.0/src/pymcap_cli/cmd/index/errors_cmd.py +163 -0
- pymcap_cli-0.14.0/src/pymcap_cli/cmd/index/info_cmd.py +350 -0
- pymcap_cli-0.14.0/src/pymcap_cli/cmd/index/migrate_cmd.py +73 -0
- pymcap_cli-0.14.0/src/pymcap_cli/cmd/index/query_cmd.py +287 -0
- pymcap_cli-0.14.0/src/pymcap_cli/cmd/index/scan_cmd.py +160 -0
- pymcap_cli-0.14.0/src/pymcap_cli/cmd/index/schemas_cmd.py +190 -0
- pymcap_cli-0.14.0/src/pymcap_cli/cmd/index/serve_cmd.py +195 -0
- pymcap_cli-0.14.0/src/pymcap_cli/cmd/index/sessions_cmd.py +169 -0
- pymcap_cli-0.14.0/src/pymcap_cli/cmd/index/status_cmd.py +267 -0
- pymcap_cli-0.14.0/src/pymcap_cli/cmd/index/timeline_cmd.py +127 -0
- pymcap_cli-0.14.0/src/pymcap_cli/cmd/index/topics_cmd.py +137 -0
- pymcap_cli-0.14.0/src/pymcap_cli/cmd/index/tree_cmd.py +423 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/info_cmd.py +39 -2
- pymcap_cli-0.14.0/src/pymcap_cli/cmd/msg/__init__.py +14 -0
- pymcap_cli-0.14.0/src/pymcap_cli/cmd/msg/def_cmd.py +66 -0
- pymcap_cli-0.14.0/src/pymcap_cli/cmd/msg/list_cmd.py +65 -0
- pymcap_cli-0.14.0/src/pymcap_cli/cmd/msg/serve_cmd.py +507 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/roscompress_cmd.py +3 -3
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/split_cmd.py +5 -2
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/mcap_processor.py +127 -14
- pymcap_cli-0.14.0/src/pymcap_cli/core/msg_resolver.py +719 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/processors/always_decode.py +3 -1
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/processors/attachment_filter.py +4 -1
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/processors/boundary_split.py +6 -1
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/processors/channel_merge.py +5 -1
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/processors/chunk_groupers.py +4 -1
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/processors/dedup.py +5 -1
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/processors/duration_split.py +5 -1
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/processors/expression_split.py +6 -1
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/processors/latching.py +7 -1
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/processors/metadata_filter.py +4 -1
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/processors/nth_message.py +5 -1
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/processors/size_split.py +5 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/processors/time_filter.py +6 -1
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/processors/time_offset.py +5 -1
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/processors/timestamp_split.py +3 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/processors/topic_alias.py +7 -1
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/processors/topic_filter.py +4 -1
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/processors/topic_rewrite.py +4 -1
- pymcap_cli-0.14.0/src/pymcap_cli/core/qos.py +147 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/display/display_utils.py +97 -4
- pymcap_cli-0.14.0/src/pymcap_cli/display/schema_html.py +206 -0
- pymcap_cli-0.14.0/src/pymcap_cli/display/schema_render.py +187 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/doctor.py +76 -1
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/http_utils.py +8 -3
- pymcap_cli-0.14.0/src/pymcap_cli/index/__init__.py +13 -0
- pymcap_cli-0.14.0/src/pymcap_cli/index/datasette/metadata.yaml +724 -0
- pymcap_cli-0.14.0/src/pymcap_cli/index/datasette/plugins/pymcap_render.py +166 -0
- pymcap_cli-0.14.0/src/pymcap_cli/index/datasette/templates/index.html +62 -0
- pymcap_cli-0.14.0/src/pymcap_cli/index/datasette/templates/query-index-timeline.html +26 -0
- pymcap_cli-0.14.0/src/pymcap_cli/index/db.py +130 -0
- pymcap_cli-0.14.0/src/pymcap_cli/index/migrations/0002_normalise_and_drop_chunks.py +247 -0
- pymcap_cli-0.14.0/src/pymcap_cli/index/migrations/0003_intern_channels.py +108 -0
- pymcap_cli-0.14.0/src/pymcap_cli/index/migrations/0004_intern_compress_channel_metadata.py +125 -0
- pymcap_cli-0.14.0/src/pymcap_cli/index/migrations/0005_content_compression.py +43 -0
- pymcap_cli-0.14.0/src/pymcap_cli/index/migrations/0006_channel_statistics.py +35 -0
- pymcap_cli-0.14.0/src/pymcap_cli/index/migrations/0007_consolidate_schema.py +357 -0
- pymcap_cli-0.14.0/src/pymcap_cli/index/migrations/0008_rewrite_current_file_view.py +59 -0
- pymcap_cli-0.14.0/src/pymcap_cli/index/migrations/0009_read_side_covering_indexes.py +25 -0
- pymcap_cli-0.14.0/src/pymcap_cli/index/migrations/__init__.py +96 -0
- pymcap_cli-0.14.0/src/pymcap_cli/index/scanner.py +1368 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/index/summary_fingerprint.py +31 -14
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/rihs01.py +8 -1
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/types/info_data.py +64 -38
- pymcap_cli-0.14.0/src/pymcap_cli/types/qos.py +83 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/types/types_manual.py +24 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/utils.py +11 -2
- pymcap_cli-0.12.0/src/pymcap_cli/cmd/compress_cmd.py +0 -97
- pymcap_cli-0.12.0/src/pymcap_cli/cmd/index_cmd.py +0 -1066
- pymcap_cli-0.12.0/src/pymcap_cli/core/msg_resolver.py +0 -447
- pymcap_cli-0.12.0/src/pymcap_cli/index/db.py +0 -78
- pymcap_cli-0.12.0/src/pymcap_cli/index/migrations/__init__.py +0 -67
- pymcap_cli-0.12.0/src/pymcap_cli/index/scanner.py +0 -687
- pymcap_cli-0.12.0/src/pymcap_cli/types/__init__.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/__init__.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/__init__.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/_rechunk_strategy.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/_run_processor_multi.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/bridge/__init__.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/bridge/_shared.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/bridge/cat.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/bridge/inspect.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/bridge/record.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/cat_cmd.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/diag_cmd.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/diff_cmd.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/doctor_cmd.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/du_cmd.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/duplicates_cmd.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/export_csv_cmd.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/export_geo_cmd.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/export_images_cmd.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/export_json_cmd.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/export_parquet_cmd.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/export_pcd_cmd.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/filter_cmd.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/get_cmd.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/info_json_cmd.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/list_cmd.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/merge_cmd.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/plot_cmd.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/process_cmd.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/rechunk_cmd.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/records_cmd.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/recover_cmd.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/recover_inplace_cmd.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/rosdecompress_cmd.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/tf_export_cmd.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/tf_get_cmd.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/tftree_cmd.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/topic_chunks_cmd.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/cmd/video_cmd.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/constants.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/__init__.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/input_handler.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/input_options.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/input_processor_chain.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/mcap_compare.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/mcap_transform.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/processors/ARCHITECTURE.md +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/processors/__init__.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/processors/base.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/processors/utils.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/tf_findings.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/core/tf_tree.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/debug_wrapper.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/display/__init__.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/display/cat_helpers.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/display/message_render.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/display/osc_utils.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/display/sparkline.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/display/time_ranges.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/encoding/__init__.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/encoding/arrow_schema.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/exporters/__init__.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/exporters/_common.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/exporters/base.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/exporters/csv_exporter.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/exporters/driver.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/exporters/geo_common.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/exporters/geojson_exporter.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/exporters/gpx_exporter.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/exporters/image_exporter.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/exporters/json_exporter.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/exporters/kml_exporter.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/exporters/parquet_exporter.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/exporters/pcd_exporter.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/exporters/plot_exporter.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/exporters/sdf_exporter.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/exporters/urdf_exporter.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/exporters/video_exporter.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/exporters/video_file_writer.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/index/fingerprint.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/index/migrations/0001.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/log_setup.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/py.typed +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/rosbag_reader/__init__.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/rosbag_reader/_reader.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/rosbag_reader/_types.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/rosbag_reader/py.typed +0 -0
- {pymcap_cli-0.12.0/src/pymcap_cli/index → pymcap_cli-0.14.0/src/pymcap_cli/types}/__init__.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/types/duration.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/types/info_link.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/types/info_types.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/types/size.py +0 -0
- {pymcap_cli-0.12.0 → pymcap_cli-0.14.0}/src/pymcap_cli/types/to_plain.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: pymcap-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.14.0
|
|
4
4
|
Summary: High-performance Python CLI for MCAP file processing with advanced recovery, filtering, and optimization capabilities
|
|
5
5
|
Keywords: mcap,cli,robotics,ros,ros2,recovery,filtering,compression
|
|
6
6
|
Author: Marko Bausch
|
|
@@ -29,7 +29,7 @@ Requires-Dist: ros-parser
|
|
|
29
29
|
Requires-Dist: platformdirs>=4.0.0
|
|
30
30
|
Requires-Dist: pyyaml>=6.0
|
|
31
31
|
Requires-Dist: typing-extensions>=4.15.0
|
|
32
|
-
Requires-Dist: pymcap-cli[video,pointcloud,plot,parquet,image,draco,bridge,xxhash] ; extra == 'all'
|
|
32
|
+
Requires-Dist: pymcap-cli[video,pointcloud,plot,parquet,image,draco,bridge,xxhash,serve] ; extra == 'all'
|
|
33
33
|
Requires-Dist: robo-ws-bridge ; extra == 'bridge'
|
|
34
34
|
Requires-Dist: mcap-codec-support[draco] ; extra == 'draco'
|
|
35
35
|
Requires-Dist: pillow>=10.0 ; extra == 'image'
|
|
@@ -39,6 +39,12 @@ Requires-Dist: numpy>=1.24.0 ; extra == 'parquet'
|
|
|
39
39
|
Requires-Dist: mcap-codec-support[pointcloud] ; extra == 'parquet'
|
|
40
40
|
Requires-Dist: plotly>=6.0.0 ; extra == 'plot'
|
|
41
41
|
Requires-Dist: mcap-codec-support[pointcloud] ; extra == 'pointcloud'
|
|
42
|
+
Requires-Dist: datasette>=0.65.2,<1 ; extra == 'serve'
|
|
43
|
+
Requires-Dist: datasette-block-robots>=1.1,<2 ; extra == 'serve'
|
|
44
|
+
Requires-Dist: datasette-copyable>=0.3.2,<1 ; extra == 'serve'
|
|
45
|
+
Requires-Dist: datasette-dashboards>=0.8.0,<1 ; extra == 'serve'
|
|
46
|
+
Requires-Dist: datasette-export-notebook>=1.0.1,<2 ; extra == 'serve'
|
|
47
|
+
Requires-Dist: datasette-vega>=0.6.2,<1 ; extra == 'serve'
|
|
42
48
|
Requires-Dist: mcap-codec-support[video] ; extra == 'video'
|
|
43
49
|
Requires-Dist: xxhash>=3.0.0 ; extra == 'xxhash'
|
|
44
50
|
Requires-Python: >=3.10
|
|
@@ -53,6 +59,7 @@ Provides-Extra: lite
|
|
|
53
59
|
Provides-Extra: parquet
|
|
54
60
|
Provides-Extra: plot
|
|
55
61
|
Provides-Extra: pointcloud
|
|
62
|
+
Provides-Extra: serve
|
|
56
63
|
Provides-Extra: video
|
|
57
64
|
Provides-Extra: xxhash
|
|
58
65
|
Description-Content-Type: text/markdown
|
|
@@ -76,8 +83,14 @@ uvx pymcap-cli info data.mcap
|
|
|
76
83
|
# Or add to your project
|
|
77
84
|
uv add pymcap-cli
|
|
78
85
|
|
|
79
|
-
# With video support (for video and
|
|
80
|
-
uv add pymcap-cli[video]
|
|
86
|
+
# With video support (for video generation and ROS image compression)
|
|
87
|
+
uv add "pymcap-cli[video]"
|
|
88
|
+
|
|
89
|
+
# With ROS image and point-cloud compression support
|
|
90
|
+
uv add "pymcap-cli[video,pointcloud]"
|
|
91
|
+
|
|
92
|
+
# Add Draco point-cloud compression support
|
|
93
|
+
uv add "pymcap-cli[video,pointcloud,draco]"
|
|
81
94
|
```
|
|
82
95
|
|
|
83
96
|
## Why pymcap-cli over the official Go CLI?
|
|
@@ -158,6 +171,16 @@ pymcap-cli cat recording.mcap --bytes base64 # base64-encoded
|
|
|
158
171
|
pymcap-cli cat recording.mcap --bytes skip # omit binary fields
|
|
159
172
|
```
|
|
160
173
|
|
|
174
|
+
### `doctor` — MCAP Container Validation
|
|
175
|
+
|
|
176
|
+
Check an MCAP file structure against the MCAP container specification, with
|
|
177
|
+
summary, index, chunk, message-order, and advisory findings.
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
pymcap-cli doctor data.mcap
|
|
181
|
+
pymcap-cli doctor data.mcap --strict-message-order --show-all
|
|
182
|
+
```
|
|
183
|
+
|
|
161
184
|
### `tftree` — TF Transform Tree
|
|
162
185
|
|
|
163
186
|
Visualize the ROS TF transform tree with colored static/dynamic transforms, translation and rotation values.
|
|
@@ -176,6 +199,16 @@ pymcap-cli tftree data.mcap
|
|
|
176
199
|
pymcap-cli tftree data.mcap --static-only
|
|
177
200
|
```
|
|
178
201
|
|
|
202
|
+
### `tf-get` — TF Transform Lookup
|
|
203
|
+
|
|
204
|
+
Resolve the transform from a source frame into a target frame using `/tf_static`
|
|
205
|
+
and `/tf`. Without `--at`, dynamic edges use their latest sample.
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
pymcap-cli tf-get data.mcap map base_link
|
|
209
|
+
pymcap-cli tf-get data.mcap odom base_link --at 2024-01-01T10:00:00Z
|
|
210
|
+
```
|
|
211
|
+
|
|
179
212
|
### `tf-export` — TF Tree to URDF / SDF / JSON
|
|
180
213
|
|
|
181
214
|
Reconstruct robot description files from `/tf_static` (and optionally `/tf` at a
|
|
@@ -376,7 +409,7 @@ Filter messages by topic patterns (simpler version of `process`).
|
|
|
376
409
|
|
|
377
410
|
```bash
|
|
378
411
|
# Include specific topics
|
|
379
|
-
pymcap-cli filter data.mcap -o filtered.mcap --
|
|
412
|
+
pymcap-cli filter data.mcap -o filtered.mcap --topics "/camera/image" "/lidar/points"
|
|
380
413
|
|
|
381
414
|
# Exclude topics
|
|
382
415
|
pymcap-cli filter data.mcap -o filtered.mcap --exclude-topics "/debug.*" "/test.*"
|
|
@@ -389,6 +422,13 @@ Change MCAP file compression.
|
|
|
389
422
|
```bash
|
|
390
423
|
pymcap-cli compress input.mcap -o output.mcap --compression zstd
|
|
391
424
|
pymcap-cli compress input.mcap -o output.mcap --compression lz4
|
|
425
|
+
|
|
426
|
+
# Compress in place: write to a temp file, validate it, then replace the source
|
|
427
|
+
pymcap-cli compress input.mcap --in-place --compression zstd
|
|
428
|
+
|
|
429
|
+
# Trade a little ratio for throughput: --fast (zstd fast mode), or pick a level
|
|
430
|
+
pymcap-cli compress input.mcap -o output.mcap --fast
|
|
431
|
+
pymcap-cli compress input.mcap -o output.mcap --compression-level -5
|
|
392
432
|
```
|
|
393
433
|
|
|
394
434
|
### `du` — Disk Usage Analysis
|
|
@@ -407,10 +447,32 @@ List various record types in an MCAP file.
|
|
|
407
447
|
pymcap-cli list channels data.mcap
|
|
408
448
|
pymcap-cli list chunks data.mcap
|
|
409
449
|
pymcap-cli list schemas data.mcap
|
|
450
|
+
pymcap-cli list schema data.mcap --name sensor_msgs/msg/Image
|
|
410
451
|
pymcap-cli list attachments data.mcap
|
|
411
452
|
pymcap-cli list metadata data.mcap
|
|
412
453
|
```
|
|
413
454
|
|
|
455
|
+
### `msg` — ROS2 Message Definitions
|
|
456
|
+
|
|
457
|
+
Resolve, list, and browse ROS2 `.msg` definitions. `msg def` prints complete
|
|
458
|
+
definitions including dependencies; `msg list` lists package message types; and
|
|
459
|
+
`msg serve` starts a local browser UI.
|
|
460
|
+
|
|
461
|
+
```bash
|
|
462
|
+
# Resolve a standard ROS2 message
|
|
463
|
+
pymcap-cli msg def sensor_msgs/msg/Image --distro humble
|
|
464
|
+
|
|
465
|
+
# Include custom package roots before AMENT_PREFIX_PATH and the user cache
|
|
466
|
+
pymcap-cli msg def my_robot_msgs/msg/Status -I ./install/share
|
|
467
|
+
|
|
468
|
+
# List messages in a package or browse definitions locally
|
|
469
|
+
pymcap-cli msg list sensor_msgs --distro jazzy
|
|
470
|
+
pymcap-cli msg serve --distro jazzy --no-browser
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
Missing standard packages are resolved from rosdistro/GitHub and cached under
|
|
474
|
+
the `pymcap_cli_msg_def` user cache.
|
|
475
|
+
|
|
414
476
|
### `get` — Extract Attachments and Metadata
|
|
415
477
|
|
|
416
478
|
Extract a single attachment's bytes or a metadata record's key/value map.
|
|
@@ -460,6 +522,38 @@ pymcap-cli duplicates /data/recordings --all
|
|
|
460
522
|
pymcap-cli duplicates /data/recordings --rebuild-missing
|
|
461
523
|
```
|
|
462
524
|
|
|
525
|
+
### `index` — Sidecar Catalog
|
|
526
|
+
|
|
527
|
+
Maintain a sidecar SQLite catalog of MCAP summaries for fast lookup across
|
|
528
|
+
large recording trees. Requires the `xxhash` extra.
|
|
529
|
+
|
|
530
|
+
```bash
|
|
531
|
+
# Scan a tree and skip unchanged files on later runs
|
|
532
|
+
pymcap-cli index scan /data/recordings
|
|
533
|
+
|
|
534
|
+
# Coverage and directory-level rollups
|
|
535
|
+
pymcap-cli index status /data/recordings
|
|
536
|
+
pymcap-cli index tree /data/recordings --max-depth 3
|
|
537
|
+
|
|
538
|
+
# Query by topic/schema/time and inspect catalog-wide topics
|
|
539
|
+
pymcap-cli index query /data/recordings --topic /camera/front --format json
|
|
540
|
+
pymcap-cli index topics /camera --sort-by messages
|
|
541
|
+
|
|
542
|
+
# Apply pending schema migrations to an existing catalog
|
|
543
|
+
pymcap-cli index migrate
|
|
544
|
+
|
|
545
|
+
# Browse the catalog in a local Datasette web UI (dashboards, charts, cross-links)
|
|
546
|
+
pymcap-cli index serve
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
`index serve` launches [Datasette](https://datasette.io/) against the sidecar DB
|
|
550
|
+
with bundled dashboards, canned queries, and a render plugin. It needs the
|
|
551
|
+
`serve` extra (`pip install 'pymcap-cli[serve]'`; in this workspace, use
|
|
552
|
+
`uv run --package pymcap-cli --extra serve pymcap-cli index serve`). Datasette
|
|
553
|
+
runs from the same environment so the plugin resolves. Use `--db` to point at a
|
|
554
|
+
non-default catalog, `--port` to change the port (default 8001), and
|
|
555
|
+
`--no-browser` to skip auto-open.
|
|
556
|
+
|
|
463
557
|
### `records` — Raw Record Dump
|
|
464
558
|
|
|
465
559
|
Print every MCAP record in file order using its `repr`. Useful for inspecting
|
|
@@ -480,22 +574,26 @@ pymcap-cli topic-chunks data.mcap
|
|
|
480
574
|
|
|
481
575
|
### `video` — Video Generation
|
|
482
576
|
|
|
483
|
-
Generate MP4
|
|
577
|
+
Generate one MP4 per image topic using hardware-accelerated encoding. Requires
|
|
578
|
+
the `video` extra.
|
|
484
579
|
|
|
485
580
|
```bash
|
|
486
581
|
# Basic video generation
|
|
487
|
-
pymcap-cli video data.mcap --topic /camera/front --output
|
|
582
|
+
pymcap-cli video data.mcap --topic /camera/front --output ./videos
|
|
488
583
|
|
|
489
584
|
# With quality preset
|
|
490
|
-
pymcap-cli video data.mcap --topic /camera/rear --output
|
|
585
|
+
pymcap-cli video data.mcap --topic /camera/rear --output ./videos --quality high
|
|
491
586
|
|
|
492
587
|
# Use specific codec and encoder
|
|
493
|
-
pymcap-cli video data.mcap --topic /lidar/image --output
|
|
588
|
+
pymcap-cli video data.mcap --topic /lidar/image --output ./videos --codec h265 --encoder videotoolbox
|
|
494
589
|
```
|
|
495
590
|
|
|
496
|
-
### `roscompress` — ROS Image Compression
|
|
591
|
+
### `roscompress` — ROS Image and Point-Cloud Compression
|
|
497
592
|
|
|
498
|
-
Compress ROS MCAP files by converting CompressedImage/Image topics to
|
|
593
|
+
Compress ROS MCAP files by converting CompressedImage/Image topics to
|
|
594
|
+
CompressedVideo format and PointCloud2 topics to Cloudini or Draco compressed
|
|
595
|
+
point clouds. Requires the `video` and `pointcloud` extras; Draco compression
|
|
596
|
+
also requires the `draco` extra.
|
|
499
597
|
|
|
500
598
|
```bash
|
|
501
599
|
# Basic compression
|
|
@@ -510,7 +608,7 @@ pymcap-cli roscompress data.mcap -o compressed.mcap --pc-format draco --pc-schem
|
|
|
510
608
|
|
|
511
609
|
### `rosdecompress` — ROS Decompression
|
|
512
610
|
|
|
513
|
-
Decompress CompressedVideo, CompressedPointCloud2, and Foxglove CompressedPointCloud topics back to standard ROS formats.
|
|
611
|
+
Decompress CompressedVideo, CompressedPointCloud2, and Foxglove CompressedPointCloud topics back to standard ROS formats. Requires the `video` and `pointcloud` extras.
|
|
514
612
|
|
|
515
613
|
```bash
|
|
516
614
|
# Decompress to CompressedImage (JPEG)
|
|
@@ -605,6 +703,22 @@ pymcap-cli export-geo data.mcap -o ./geo --format gpx --mode track --stride 5
|
|
|
605
703
|
pymcap-cli export-geo data.mcap -o ./geo --include-no-fix
|
|
606
704
|
```
|
|
607
705
|
|
|
706
|
+
### `bridge` — Live Foxglove Bridge
|
|
707
|
+
|
|
708
|
+
Inspect, stream, or record live topics from a Foxglove WebSocket bridge. Requires
|
|
709
|
+
the `bridge` extra.
|
|
710
|
+
|
|
711
|
+
```bash
|
|
712
|
+
# Inspect advertised channels
|
|
713
|
+
pymcap-cli bridge localhost:8765
|
|
714
|
+
|
|
715
|
+
# Stream decoded messages
|
|
716
|
+
pymcap-cli bridge cat localhost:8765 --topics /tf --limit 10
|
|
717
|
+
|
|
718
|
+
# Record all advertised topics to MCAP
|
|
719
|
+
pymcap-cli bridge record localhost:8765 --all -o live.mcap
|
|
720
|
+
```
|
|
721
|
+
|
|
608
722
|
### Shell Autocompletion
|
|
609
723
|
|
|
610
724
|
```bash
|
|
@@ -631,9 +745,9 @@ pymcap-cli process full_log.mcap -o camera.mcap \
|
|
|
631
745
|
# Recover corrupt file and compress in one pass
|
|
632
746
|
pymcap-cli process corrupt.mcap -o recovered.mcap --recovery-mode --compression lz4
|
|
633
747
|
|
|
634
|
-
# Fast filtering with chunk copying
|
|
748
|
+
# Fast filtering with automatic chunk copying when possible
|
|
635
749
|
pymcap-cli process 100gb_file.mcap -o filtered.mcap \
|
|
636
|
-
-y "/lidar.*" --
|
|
750
|
+
-y "/lidar.*" --compression zstd
|
|
637
751
|
|
|
638
752
|
# Optimize for topic-specific playback
|
|
639
753
|
pymcap-cli rechunk robot_log.mcap -o optimized.mcap \
|
|
@@ -653,14 +767,14 @@ pymcap-cli rechunk robot_log.mcap -o optimized.mcap \
|
|
|
653
767
|
|
|
654
768
|
```bash
|
|
655
769
|
# Setup development environment
|
|
656
|
-
uv sync
|
|
770
|
+
uv sync --all-groups --all-extras --all-packages
|
|
657
771
|
|
|
658
772
|
# Run locally during development
|
|
659
773
|
uv run pymcap-cli --help
|
|
660
774
|
|
|
661
775
|
# Format and lint code
|
|
662
|
-
|
|
776
|
+
pre-commit run --all-files
|
|
663
777
|
|
|
664
778
|
# Run tests
|
|
665
|
-
uv run pytest pymcap-cli/tests
|
|
779
|
+
uv run pytest pymcap-cli/tests -m "not benchmark" --no-cov -q
|
|
666
780
|
```
|
|
@@ -17,8 +17,14 @@ uvx pymcap-cli info data.mcap
|
|
|
17
17
|
# Or add to your project
|
|
18
18
|
uv add pymcap-cli
|
|
19
19
|
|
|
20
|
-
# With video support (for video and
|
|
21
|
-
uv add pymcap-cli[video]
|
|
20
|
+
# With video support (for video generation and ROS image compression)
|
|
21
|
+
uv add "pymcap-cli[video]"
|
|
22
|
+
|
|
23
|
+
# With ROS image and point-cloud compression support
|
|
24
|
+
uv add "pymcap-cli[video,pointcloud]"
|
|
25
|
+
|
|
26
|
+
# Add Draco point-cloud compression support
|
|
27
|
+
uv add "pymcap-cli[video,pointcloud,draco]"
|
|
22
28
|
```
|
|
23
29
|
|
|
24
30
|
## Why pymcap-cli over the official Go CLI?
|
|
@@ -99,6 +105,16 @@ pymcap-cli cat recording.mcap --bytes base64 # base64-encoded
|
|
|
99
105
|
pymcap-cli cat recording.mcap --bytes skip # omit binary fields
|
|
100
106
|
```
|
|
101
107
|
|
|
108
|
+
### `doctor` — MCAP Container Validation
|
|
109
|
+
|
|
110
|
+
Check an MCAP file structure against the MCAP container specification, with
|
|
111
|
+
summary, index, chunk, message-order, and advisory findings.
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
pymcap-cli doctor data.mcap
|
|
115
|
+
pymcap-cli doctor data.mcap --strict-message-order --show-all
|
|
116
|
+
```
|
|
117
|
+
|
|
102
118
|
### `tftree` — TF Transform Tree
|
|
103
119
|
|
|
104
120
|
Visualize the ROS TF transform tree with colored static/dynamic transforms, translation and rotation values.
|
|
@@ -117,6 +133,16 @@ pymcap-cli tftree data.mcap
|
|
|
117
133
|
pymcap-cli tftree data.mcap --static-only
|
|
118
134
|
```
|
|
119
135
|
|
|
136
|
+
### `tf-get` — TF Transform Lookup
|
|
137
|
+
|
|
138
|
+
Resolve the transform from a source frame into a target frame using `/tf_static`
|
|
139
|
+
and `/tf`. Without `--at`, dynamic edges use their latest sample.
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
pymcap-cli tf-get data.mcap map base_link
|
|
143
|
+
pymcap-cli tf-get data.mcap odom base_link --at 2024-01-01T10:00:00Z
|
|
144
|
+
```
|
|
145
|
+
|
|
120
146
|
### `tf-export` — TF Tree to URDF / SDF / JSON
|
|
121
147
|
|
|
122
148
|
Reconstruct robot description files from `/tf_static` (and optionally `/tf` at a
|
|
@@ -317,7 +343,7 @@ Filter messages by topic patterns (simpler version of `process`).
|
|
|
317
343
|
|
|
318
344
|
```bash
|
|
319
345
|
# Include specific topics
|
|
320
|
-
pymcap-cli filter data.mcap -o filtered.mcap --
|
|
346
|
+
pymcap-cli filter data.mcap -o filtered.mcap --topics "/camera/image" "/lidar/points"
|
|
321
347
|
|
|
322
348
|
# Exclude topics
|
|
323
349
|
pymcap-cli filter data.mcap -o filtered.mcap --exclude-topics "/debug.*" "/test.*"
|
|
@@ -330,6 +356,13 @@ Change MCAP file compression.
|
|
|
330
356
|
```bash
|
|
331
357
|
pymcap-cli compress input.mcap -o output.mcap --compression zstd
|
|
332
358
|
pymcap-cli compress input.mcap -o output.mcap --compression lz4
|
|
359
|
+
|
|
360
|
+
# Compress in place: write to a temp file, validate it, then replace the source
|
|
361
|
+
pymcap-cli compress input.mcap --in-place --compression zstd
|
|
362
|
+
|
|
363
|
+
# Trade a little ratio for throughput: --fast (zstd fast mode), or pick a level
|
|
364
|
+
pymcap-cli compress input.mcap -o output.mcap --fast
|
|
365
|
+
pymcap-cli compress input.mcap -o output.mcap --compression-level -5
|
|
333
366
|
```
|
|
334
367
|
|
|
335
368
|
### `du` — Disk Usage Analysis
|
|
@@ -348,10 +381,32 @@ List various record types in an MCAP file.
|
|
|
348
381
|
pymcap-cli list channels data.mcap
|
|
349
382
|
pymcap-cli list chunks data.mcap
|
|
350
383
|
pymcap-cli list schemas data.mcap
|
|
384
|
+
pymcap-cli list schema data.mcap --name sensor_msgs/msg/Image
|
|
351
385
|
pymcap-cli list attachments data.mcap
|
|
352
386
|
pymcap-cli list metadata data.mcap
|
|
353
387
|
```
|
|
354
388
|
|
|
389
|
+
### `msg` — ROS2 Message Definitions
|
|
390
|
+
|
|
391
|
+
Resolve, list, and browse ROS2 `.msg` definitions. `msg def` prints complete
|
|
392
|
+
definitions including dependencies; `msg list` lists package message types; and
|
|
393
|
+
`msg serve` starts a local browser UI.
|
|
394
|
+
|
|
395
|
+
```bash
|
|
396
|
+
# Resolve a standard ROS2 message
|
|
397
|
+
pymcap-cli msg def sensor_msgs/msg/Image --distro humble
|
|
398
|
+
|
|
399
|
+
# Include custom package roots before AMENT_PREFIX_PATH and the user cache
|
|
400
|
+
pymcap-cli msg def my_robot_msgs/msg/Status -I ./install/share
|
|
401
|
+
|
|
402
|
+
# List messages in a package or browse definitions locally
|
|
403
|
+
pymcap-cli msg list sensor_msgs --distro jazzy
|
|
404
|
+
pymcap-cli msg serve --distro jazzy --no-browser
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
Missing standard packages are resolved from rosdistro/GitHub and cached under
|
|
408
|
+
the `pymcap_cli_msg_def` user cache.
|
|
409
|
+
|
|
355
410
|
### `get` — Extract Attachments and Metadata
|
|
356
411
|
|
|
357
412
|
Extract a single attachment's bytes or a metadata record's key/value map.
|
|
@@ -401,6 +456,38 @@ pymcap-cli duplicates /data/recordings --all
|
|
|
401
456
|
pymcap-cli duplicates /data/recordings --rebuild-missing
|
|
402
457
|
```
|
|
403
458
|
|
|
459
|
+
### `index` — Sidecar Catalog
|
|
460
|
+
|
|
461
|
+
Maintain a sidecar SQLite catalog of MCAP summaries for fast lookup across
|
|
462
|
+
large recording trees. Requires the `xxhash` extra.
|
|
463
|
+
|
|
464
|
+
```bash
|
|
465
|
+
# Scan a tree and skip unchanged files on later runs
|
|
466
|
+
pymcap-cli index scan /data/recordings
|
|
467
|
+
|
|
468
|
+
# Coverage and directory-level rollups
|
|
469
|
+
pymcap-cli index status /data/recordings
|
|
470
|
+
pymcap-cli index tree /data/recordings --max-depth 3
|
|
471
|
+
|
|
472
|
+
# Query by topic/schema/time and inspect catalog-wide topics
|
|
473
|
+
pymcap-cli index query /data/recordings --topic /camera/front --format json
|
|
474
|
+
pymcap-cli index topics /camera --sort-by messages
|
|
475
|
+
|
|
476
|
+
# Apply pending schema migrations to an existing catalog
|
|
477
|
+
pymcap-cli index migrate
|
|
478
|
+
|
|
479
|
+
# Browse the catalog in a local Datasette web UI (dashboards, charts, cross-links)
|
|
480
|
+
pymcap-cli index serve
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
`index serve` launches [Datasette](https://datasette.io/) against the sidecar DB
|
|
484
|
+
with bundled dashboards, canned queries, and a render plugin. It needs the
|
|
485
|
+
`serve` extra (`pip install 'pymcap-cli[serve]'`; in this workspace, use
|
|
486
|
+
`uv run --package pymcap-cli --extra serve pymcap-cli index serve`). Datasette
|
|
487
|
+
runs from the same environment so the plugin resolves. Use `--db` to point at a
|
|
488
|
+
non-default catalog, `--port` to change the port (default 8001), and
|
|
489
|
+
`--no-browser` to skip auto-open.
|
|
490
|
+
|
|
404
491
|
### `records` — Raw Record Dump
|
|
405
492
|
|
|
406
493
|
Print every MCAP record in file order using its `repr`. Useful for inspecting
|
|
@@ -421,22 +508,26 @@ pymcap-cli topic-chunks data.mcap
|
|
|
421
508
|
|
|
422
509
|
### `video` — Video Generation
|
|
423
510
|
|
|
424
|
-
Generate MP4
|
|
511
|
+
Generate one MP4 per image topic using hardware-accelerated encoding. Requires
|
|
512
|
+
the `video` extra.
|
|
425
513
|
|
|
426
514
|
```bash
|
|
427
515
|
# Basic video generation
|
|
428
|
-
pymcap-cli video data.mcap --topic /camera/front --output
|
|
516
|
+
pymcap-cli video data.mcap --topic /camera/front --output ./videos
|
|
429
517
|
|
|
430
518
|
# With quality preset
|
|
431
|
-
pymcap-cli video data.mcap --topic /camera/rear --output
|
|
519
|
+
pymcap-cli video data.mcap --topic /camera/rear --output ./videos --quality high
|
|
432
520
|
|
|
433
521
|
# Use specific codec and encoder
|
|
434
|
-
pymcap-cli video data.mcap --topic /lidar/image --output
|
|
522
|
+
pymcap-cli video data.mcap --topic /lidar/image --output ./videos --codec h265 --encoder videotoolbox
|
|
435
523
|
```
|
|
436
524
|
|
|
437
|
-
### `roscompress` — ROS Image Compression
|
|
525
|
+
### `roscompress` — ROS Image and Point-Cloud Compression
|
|
438
526
|
|
|
439
|
-
Compress ROS MCAP files by converting CompressedImage/Image topics to
|
|
527
|
+
Compress ROS MCAP files by converting CompressedImage/Image topics to
|
|
528
|
+
CompressedVideo format and PointCloud2 topics to Cloudini or Draco compressed
|
|
529
|
+
point clouds. Requires the `video` and `pointcloud` extras; Draco compression
|
|
530
|
+
also requires the `draco` extra.
|
|
440
531
|
|
|
441
532
|
```bash
|
|
442
533
|
# Basic compression
|
|
@@ -451,7 +542,7 @@ pymcap-cli roscompress data.mcap -o compressed.mcap --pc-format draco --pc-schem
|
|
|
451
542
|
|
|
452
543
|
### `rosdecompress` — ROS Decompression
|
|
453
544
|
|
|
454
|
-
Decompress CompressedVideo, CompressedPointCloud2, and Foxglove CompressedPointCloud topics back to standard ROS formats.
|
|
545
|
+
Decompress CompressedVideo, CompressedPointCloud2, and Foxglove CompressedPointCloud topics back to standard ROS formats. Requires the `video` and `pointcloud` extras.
|
|
455
546
|
|
|
456
547
|
```bash
|
|
457
548
|
# Decompress to CompressedImage (JPEG)
|
|
@@ -546,6 +637,22 @@ pymcap-cli export-geo data.mcap -o ./geo --format gpx --mode track --stride 5
|
|
|
546
637
|
pymcap-cli export-geo data.mcap -o ./geo --include-no-fix
|
|
547
638
|
```
|
|
548
639
|
|
|
640
|
+
### `bridge` — Live Foxglove Bridge
|
|
641
|
+
|
|
642
|
+
Inspect, stream, or record live topics from a Foxglove WebSocket bridge. Requires
|
|
643
|
+
the `bridge` extra.
|
|
644
|
+
|
|
645
|
+
```bash
|
|
646
|
+
# Inspect advertised channels
|
|
647
|
+
pymcap-cli bridge localhost:8765
|
|
648
|
+
|
|
649
|
+
# Stream decoded messages
|
|
650
|
+
pymcap-cli bridge cat localhost:8765 --topics /tf --limit 10
|
|
651
|
+
|
|
652
|
+
# Record all advertised topics to MCAP
|
|
653
|
+
pymcap-cli bridge record localhost:8765 --all -o live.mcap
|
|
654
|
+
```
|
|
655
|
+
|
|
549
656
|
### Shell Autocompletion
|
|
550
657
|
|
|
551
658
|
```bash
|
|
@@ -572,9 +679,9 @@ pymcap-cli process full_log.mcap -o camera.mcap \
|
|
|
572
679
|
# Recover corrupt file and compress in one pass
|
|
573
680
|
pymcap-cli process corrupt.mcap -o recovered.mcap --recovery-mode --compression lz4
|
|
574
681
|
|
|
575
|
-
# Fast filtering with chunk copying
|
|
682
|
+
# Fast filtering with automatic chunk copying when possible
|
|
576
683
|
pymcap-cli process 100gb_file.mcap -o filtered.mcap \
|
|
577
|
-
-y "/lidar.*" --
|
|
684
|
+
-y "/lidar.*" --compression zstd
|
|
578
685
|
|
|
579
686
|
# Optimize for topic-specific playback
|
|
580
687
|
pymcap-cli rechunk robot_log.mcap -o optimized.mcap \
|
|
@@ -594,14 +701,14 @@ pymcap-cli rechunk robot_log.mcap -o optimized.mcap \
|
|
|
594
701
|
|
|
595
702
|
```bash
|
|
596
703
|
# Setup development environment
|
|
597
|
-
uv sync
|
|
704
|
+
uv sync --all-groups --all-extras --all-packages
|
|
598
705
|
|
|
599
706
|
# Run locally during development
|
|
600
707
|
uv run pymcap-cli --help
|
|
601
708
|
|
|
602
709
|
# Format and lint code
|
|
603
|
-
|
|
710
|
+
pre-commit run --all-files
|
|
604
711
|
|
|
605
712
|
# Run tests
|
|
606
|
-
uv run pytest pymcap-cli/tests
|
|
713
|
+
uv run pytest pymcap-cli/tests -m "not benchmark" --no-cov -q
|
|
607
714
|
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "pymcap-cli"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.14.0"
|
|
4
4
|
description = "High-performance Python CLI for MCAP file processing with advanced recovery, filtering, and optimization capabilities"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10"
|
|
@@ -46,7 +46,7 @@ dependencies = [
|
|
|
46
46
|
]
|
|
47
47
|
|
|
48
48
|
[project.optional-dependencies]
|
|
49
|
-
all = ["pymcap-cli[video,pointcloud,plot,parquet,image,draco,bridge,xxhash]"]
|
|
49
|
+
all = ["pymcap-cli[video,pointcloud,plot,parquet,image,draco,bridge,xxhash,serve]"]
|
|
50
50
|
lite = ["pymcap-cli[image,draco,bridge,xxhash]"]
|
|
51
51
|
bridge = ["robo-ws-bridge"]
|
|
52
52
|
draco = ["mcap-codec-support[draco]"]
|
|
@@ -56,6 +56,16 @@ plot = ["plotly>=6.0.0"]
|
|
|
56
56
|
pointcloud = ["mcap-codec-support[pointcloud]"]
|
|
57
57
|
video = ["mcap-codec-support[video]"]
|
|
58
58
|
xxhash = ["xxhash>=3.0.0"]
|
|
59
|
+
# `index serve` web UI. datasette<1 pin: datasette-dashboards 500s on the 1.0
|
|
60
|
+
# pre-release. Run from the same env so the bundled pymcap_render plugin imports.
|
|
61
|
+
serve = [
|
|
62
|
+
"datasette>=0.65.2,<1",
|
|
63
|
+
"datasette-block-robots>=1.1,<2",
|
|
64
|
+
"datasette-copyable>=0.3.2,<1",
|
|
65
|
+
"datasette-dashboards>=0.8.0,<1",
|
|
66
|
+
"datasette-export-notebook>=1.0.1,<2",
|
|
67
|
+
"datasette-vega>=0.6.2,<1",
|
|
68
|
+
]
|
|
59
69
|
|
|
60
70
|
|
|
61
71
|
[project.urls]
|
|
@@ -37,6 +37,7 @@ from pymcap_cli.cmd import (
|
|
|
37
37
|
tftree_cmd,
|
|
38
38
|
topic_chunks_cmd,
|
|
39
39
|
)
|
|
40
|
+
from pymcap_cli.cmd import msg as msg_pkg
|
|
40
41
|
from pymcap_cli.log_setup import ERR, setup_logging
|
|
41
42
|
|
|
42
43
|
CommandFunction: TypeAlias = Callable[..., int]
|
|
@@ -194,7 +195,7 @@ rosdecompress = _load_optional_command(
|
|
|
194
195
|
install_command="uv add 'pymcap-cli[video,pointcloud]'",
|
|
195
196
|
)
|
|
196
197
|
index_app = _load_optional_app(
|
|
197
|
-
"pymcap_cli.cmd.
|
|
198
|
+
"pymcap_cli.cmd.index",
|
|
198
199
|
"index_app",
|
|
199
200
|
expected_missing_modules=("xxhash",),
|
|
200
201
|
message="Index command requires the 'xxhash' extra "
|
|
@@ -225,6 +226,8 @@ app.command(name="diff", group=inspect_group)(diff_cmd.diff_cmd)
|
|
|
225
226
|
app.command(name="duplicates", group=inspect_group)(duplicates_cmd.duplicates)
|
|
226
227
|
app.command(name="info", group=inspect_group)(info_cmd.info)
|
|
227
228
|
app.command(name="info-json", group=inspect_group)(info_json_cmd.info_json)
|
|
229
|
+
msg_pkg.msg_app.group = (inspect_group,)
|
|
230
|
+
app.command(msg_pkg.msg_app, name="msg")
|
|
228
231
|
index_app.group = (inspect_group,)
|
|
229
232
|
app.command(index_app, name="index")
|
|
230
233
|
get_cmd.get_app.group = (inspect_group,)
|
|
@@ -126,6 +126,27 @@ def delete_source_files(sources: list[str], outputs: list[Path]) -> None:
|
|
|
126
126
|
logger.exception(f"Failed to delete '{src}'")
|
|
127
127
|
|
|
128
128
|
|
|
129
|
+
def in_place_temp_path(source: Path) -> Path:
|
|
130
|
+
"""Temp output path next to ``source`` so the final rename stays on one filesystem."""
|
|
131
|
+
return source.with_name(source.name + ".tmp")
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def finalize_replace_source(*, source: Path, tmp_output: Path) -> int:
|
|
135
|
+
"""Validate ``tmp_output`` and atomically replace ``source`` with it.
|
|
136
|
+
|
|
137
|
+
Returns 0 on success and 1 if validation failed (source is preserved and
|
|
138
|
+
the temp file is removed).
|
|
139
|
+
"""
|
|
140
|
+
if not validate_mcap_output(tmp_output):
|
|
141
|
+
logger.error(f"[red]Output failed validation: {tmp_output}[/red]")
|
|
142
|
+
logger.error("Source file preserved — output not safe to replace source.")
|
|
143
|
+
tmp_output.unlink(missing_ok=True)
|
|
144
|
+
return 1
|
|
145
|
+
tmp_output.replace(source)
|
|
146
|
+
logger.info(f"Replaced source: {source}")
|
|
147
|
+
return 0
|
|
148
|
+
|
|
149
|
+
|
|
129
150
|
def finalize_delete_source(
|
|
130
151
|
*,
|
|
131
152
|
sources: list[str],
|