Command-Line Interface¶
sleap-io provides a command-line interface (CLI) for inspecting and converting pose tracking data without writing Python code. The CLI is designed for quick exploration, scripting, and integration into data pipelines.
Installation¶
Quick Usage with uvx (No Installation)¶
Run CLI commands instantly using uvx without installing:
# Inspect a labels file
uvx sleap-io show labels.slp
# Convert between formats
uvx sleap-io convert labels.slp -o labels.nwb
# Embed frames in output (video reading works out of the box)
uvx sleap-io convert -i labels.slp -o labels.pkg.slp --embed user
# Export to Ultralytics format
uvx sleap-io convert -i labels.slp -o dataset/ --to ultralytics
# Check version
uvx sleap-io --version
Permanent Installation with uv tool¶
For regular use, install sleap-io as a global tool:
# Basic install (includes video support via imageio-ffmpeg)
uv tool install sleap-io
# Or with faster video backends (OpenCV, PyAV)
uv tool install "sleap-io[all]"
# Now use the short command
sio show labels.slp
sio convert labels.slp -o labels.nwb
The sio command
After installation with uv tool install, you can use either sio or sleap-io as the command name. The short sio form is recommended for convenience.
When do you need the [all] extra?
Video support works out of the box via the bundled imageio-ffmpeg backend.
The [all] extra installs faster video backends (OpenCV, PyAV) for improved performance.
Use [all] when:
- Processing many videos or large files (OpenCV is ~2-3x faster)
- You need specific codec support from PyAV
Quick Reference¶
# Get help
sio --help
sio show --help
sio convert --help
sio export --help
sio split --help
sio unsplit --help
sio merge --help
sio embed --help
sio unembed --help
sio filenames --help
sio download --help
sio fix --help
sio render --help
sio trim --help
sio reencode --help
sio transform --help
sio apply-crops --help
# Check version and installed plugins
sio --version
# Inspect a labels file
sio show labels.slp # Basic summary
sio show labels.slp --skeleton # Detailed skeleton info
sio show labels.slp --video # Detailed video info (all videos)
sio show labels.slp --vi 0 # Show specific video by index
sio show labels.slp --tracks # Track details
sio show labels.slp --provenance # Metadata/provenance
sio show labels.slp --all # Everything
sio show labels.slp --lf 0 # Labeled frame details
sio show labels.slp --json # Machine-readable JSON output
sio show labels.slp --json --frames # JSON with per-frame listing
# Inspect a video file directly
sio show video.mp4 # Video properties and metadata
sio show recording.seq # Norpix .seq file info
# Convert between formats
sio convert labels.slp -o labels.nwb
sio convert labels.slp -o labels.pkg.slp --embed user
sio convert data.json -o labels.slp --from coco
sio convert labels.slp -o dataset/ --to ultralytics
# Split into train/val/test sets
sio split labels.slp -o splits/ # 80/20 train/val
sio split labels.slp -o splits/ --train 0.7 --test 0.15 # 70/15/15 split
sio split labels.slp -o splits/ --remove-predictions # User labels only
sio split labels.slp -o splits/ --seed 42 # Reproducible split
# Merge split files back into one
sio unsplit train.slp val.slp -o merged.slp # Merge individual files
sio unsplit splits/ -o merged.slp # Merge all .slp in directory
# Merge labels files with flexible options
sio merge project.slp predictions.slp -o merged.slp # Merge predictions into project
sio merge base.slp new.slp -o merged.slp --frame replace_predictions
sio merge results/ -o combined.slp --frame keep_both # All .slp in directory
sio merge local.slp remote.slp -o merged.slp --video basename
# Embed video frames into a portable package
sio embed labels.slp -o labels.pkg.slp # User-labeled frames only
sio embed labels.slp -o labels.pkg.slp --predictions # Include prediction frames
sio embed labels.slp -o labels.pkg.slp --suggestions # Include suggested frames
# Remove embedded frames and restore video references
sio unembed labels.pkg.slp -o labels.slp # Restore original video paths
# Inspect and update video filenames
sio filenames labels.slp # List video paths
sio filenames labels.slp -o out.slp --filename /new/video.mp4
sio filenames labels.slp -o out.slp --map old.mp4 /new/video.mp4
sio filenames labels.slp -o out.slp --prefix /old/path /new/path
# Download a remote file to disk (curl/wget replacement)
sio download https://example.com/labels.slp # -> ./labels.slp
sio download s3://my-bucket/run/video.mp4 data/ # Into a directory
sio download https://example.com/a.slp out.slp -f # Exact path, overwrite
# Fix common issues in labels files
sio fix labels.slp # Auto-fix with defaults
sio fix labels.slp --dry-run # Preview without changes
sio fix labels.slp --remove-predictions # Also remove predictions
sio fix labels.slp --remove-untracked-predictions # Surgical pred removal
sio fix labels.slp --consolidate-skeletons # Force single skeleton
sio fix labels.slp --prefix "C:\data" /mnt/data # Fix cross-platform paths
# Render video with pose overlays
sio render predictions.slp # -> predictions.viz.mp4
sio render predictions.slp --preset preview # Fast 0.25x preview
sio render predictions.slp --start 100 --end 200
sio render predictions.slp --lf 0 # Single frame -> PNG
sio render predictions.slp --lf 0 --crop 100,100,300,300 # Crop to region
sio render predictions.slp --color-by track --marker-shape diamond
sio render predictions.slp --trails --trail-length 10 # Motion trails
# Trim video and labels to a frame range
sio trim labels.slp --start 100 --end 1000 # -> labels.trim.slp
sio trim labels.slp --start 100 --end 1000 -o clip.slp
sio trim video.mp4 --start 100 --end 500 # Video-only mode
# Reencode video for reliable seeking (critical for annotation)
sio reencode video.mp4 -o video.seekable.mp4 # Fix seeking issues
sio reencode video.mp4 -o output.mp4 --quality high # Higher quality
sio reencode video.mp4 -o output.mp4 --keyframe-interval 0.5 # Max reliability
sio reencode highspeed.mp4 -o preview.mp4 --fps 30 --quality low # Downsample
sio reencode video.mp4 -o output.mp4 --dry-run # Show ffmpeg command
sio reencode recording.seq -o recording.mp4 # Convert Norpix .seq to MP4
sio reencode project.slp -o project.reencoded.slp # Batch reencode all videos in SLP
# Transform video and adjust landmark coordinates
sio transform labels.slp --scale 0.5 -o scaled.slp # Scale down 50%
sio transform labels.slp --crop 100,100,500,500 -o crop.slp # Crop to region
sio transform labels.slp --rotate 90 -o rotated.slp # Rotate 90 degrees
sio transform labels.slp --flip-horizontal -o flipped.slp # Mirror horizontally
sio transform labels.slp --crop 100,100,500,500 --scale 2.0 -o zoomed.slp
sio transform multi_cam.slp --crop 0:100,100,500,500 -o cropped.slp # Per-video
sio transform labels.slp --scale 0.5 --dry-run # Preview transforms
sio transform labels.slp --scale 0.5 --dry-run-frame 0 # Preview specific frame
sio transform video.mp4 --scale 0.5 -o video_scaled.mp4 # Transform raw video
sio show¶
Display information about a SLEAP labels file or video file with rich formatted output.
Input as positional or flag
All commands accept the input file as a positional argument or with -i/--input.
The positional form (e.g., sio show labels.slp) is simpler; the flag form
(e.g., sio show -i labels.slp) is more explicit.
Basic Usage¶
# View file summary with skeleton and video info
sio show labels.slp
# Inspect a video file directly
sio show video.mp4
Example output:
╭─ sleap-io ─────────────────────────────────────────────────────────────╮
│ labels.slp │
│ /home/user/projects/mouse-tracking │
│ │
│ Type: Labels │
│ Size: 2.4 MB │
│ │
│ 1 video | 100 frames | 200 labeled | 2 tracks │
╰────────────────────────────────────────────────────────────────────────╯
Full: /home/user/projects/mouse-tracking/labels.slp
Skeletons
mouse (7 nodes, 6 edges)
nodes = ["nose", "head", "neck", "body", "tail_base", "tail_mid", "tail_tip"]
edge_inds = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
Videos (1)
[0] video.mp4 1920×1080 5000 frames
Tracks (2)
mouse_1, mouse_2
The default view shows:
- Header panel: File name, path, type, size, and key statistics
- Skeleton: Node and edge definitions as copyable Python code
- Videos: Quick summary of video files and dimensions
- Tracks: List of track names
Options¶
| Option | Short | Description |
|---|---|---|
--input |
-i |
Input file (can also pass as positional argument) |
--skeleton |
-s |
Show detailed skeleton tables (nodes, edges, symmetries) |
--video |
-v |
Show detailed video info (opens backends by default) |
--video-index N |
--vi N |
Show only video at index N (0-based). Implies --video |
--tracks |
-t |
Show track table with instance counts per track |
--provenance |
-p |
Show provenance/metadata from the file |
--all |
-a |
Show all details (combines all flags above) |
--lf N |
Show details for labeled frame at index N | |
--frames |
List all labeled frames (video, frame index, instance counts) | |
--json |
Output as JSON (machine-readable, includes all details) | |
--open-videos |
Force open video backends | |
--no-open-videos |
Don't open video backends (overrides -v default) |
Viewing a specific video
Use --video-index N (or --vi N) to show only a specific video by its index. For example, sio show labels.slp --vi 0 shows only the first video, while sio show labels.slp -v shows all videos.
Detailed Skeleton View¶
Shows tables for nodes, edges, and symmetries:
Skeleton 0: fly (24 nodes, 23 edges, 10 symmetries)
Python code:
nodes = ["head", "neck", "thorax", "abdomen", ...]
edge_inds = [(1, 0), (2, 1), (2, 3), ...]
Nodes:
# | Name
---+----------
0 | head
1 | neck
2 | thorax
...
Edges:
# | Source | | Destination | Indices
---+----------+----+-------------+----------
0 | neck | -> | head | (1, 0)
1 | thorax | -> | neck | (2, 1)
...
Symmetries:
# | Node A | | Node B
---+----------+-----+-----------
0 | wingR | <-> | wingL
1 | legL1 | <-> | legR1
...
Detailed Video View¶
sio show labels.slp --video
# Or show a specific video by index:
sio show labels.slp --video-index 0
# Short form:
sio show labels.slp --vi 0
Shows comprehensive video information including backend status:
Video 0: video.mp4
Type MediaVideo
Path video.mp4
Full /data/videos/video.mp4
Status File exists, backend not loaded
Frames 5000
Size 1920 × 1080 (RGB)
Labeled 100 frames
The "Full" path is shown when it differs from the stored path, making it easy to copy absolute paths.
For embedded package files (.pkg.slp):
Video 0: video.mp4 [embedded]
Type HDF5Video (embedded)
Source original_video.mp4
Dataset video0/video
Format PNG (RGB)
Status Embedded, backend loaded
Frames 50 (indices: 0–49)
Size 1920 × 1080 (RGB)
Labeled 50 frames
Source Video
File original_video.mp4
Type MediaVideo
Frames 5000
Size 1920 × 1080 (RGB)
Track Details¶
Shows a table with instance counts per track:
Labeled Frame Details¶
Shows detailed information for a specific labeled frame:
Labeled Frame 0
Video: video.mp4
Frame: 42
Instances: 2
Instance 0: user, track=mouse_1, visible=7/7
points = [(256.32, 189.45), (245.18, 195.23), (230.45, 210.67), ...]
Instance 1: predicted, track=mouse_2, score=0.94, visible=7/7
points = [(512.18, 302.56), (498.32, 315.89), (475.23, 340.12), ...]
The points list is copyable Python code matching the skeleton node order.
Provenance Information¶
Shows metadata stored in the file:
Provenance
sleap_version: 1.3.3
model_paths: centroid.210505_..., centered_instance.210505_... (2 total)
created_at: 2024-01-15T14:30:00
Show Everything¶
Combines --skeleton, --video, --tracks, and --provenance for a complete view.
JSON Output¶
Emits a single machine-readable JSON document on stdout, designed for scripting and for LLM agents inspecting SLP files. JSON mode always includes all details (full skeleton definitions, per-video info, tracks, identities, categories, frame-spanning events, and provenance), so the individual detail flags are not needed:
{
"path": "/data/labels.slp",
"name": "labels.slp",
"size_bytes": 20120,
"format": "labels",
"stats": {
"n_videos": 1,
"n_labeled_frames": 800,
"n_user_frames": 800,
"n_user_instances": 2376,
"n_predicted_instances": 0,
"n_skeletons": 1,
"n_tracks": 0,
"n_identities": 0,
"n_categories": 0,
"n_masks": 0,
"n_rois": 0,
"n_events": 0,
"n_event_types": 0,
"n_instances_with_identity_embedding": null,
"n_instances_with_category_embedding": null
},
"skeletons": [
{
"index": 0,
"name": "Skeleton-0",
"nodes": ["head", "thorax", "abdomen"],
"edges": [{"source": "head", "destination": "thorax", "indices": [0, 1]}],
"symmetries": []
}
],
"videos": [
{
"index": 0,
"filename": "/data/video.mp4",
"type": "MediaVideo",
"embedded": false,
"exists": true,
"shape": {"frames": 1100, "height": 384, "width": 384, "channels": 1},
"n_labeled_frames": 800,
"source_video": null
}
],
"tracks": [],
"identities": [],
"categories": [],
"event_types": [],
"events": [],
"provenance": {}
}
Combine with the navigation flags for deeper inspection:
# Per-frame listing: which frames are labeled, in which video, with how many
# instances (fast even on large files thanks to lazy loading)
sio show labels.slp --json --frames
# Full detail for one labeled frame, including per-instance points
# (x, y coordinates in skeleton node order; occluded points are [null, null])
sio show labels.slp --json --lf 0
# Standalone video files work too (shape, fps, codec, bitrate, GOP size)
sio show video.mp4 --json
Notes:
- Output is strict JSON: NaN/Infinity are converted to
null, so it parses with any standard JSON library (sio show x.slp --json | jq .stats). stats.n_instances_with_identity_embeddingandstats.n_instances_with_category_embeddingarenullwhen lazy loading is active (counting would require materializing all frames); pass--no-lazyto compute them.- Categories are reported alongside identities:
stats.n_categoriescounts the catalog and eachcategoriesentry is{"index", "name"}(parallel toidentities). - Embedded package details (
embedded,shape,embedded_frames) require open video backends; pass--open-videosto populate them. - Frame-spanning events are reported when present. Each
event_typesentry is{"index", "name"}(plus"description"/"metadata"when set); eacheventsentry is{"index", "type", "video", "start_frame", "end_frame", "subject", "target", "predicted"}, wheresubject/targetarenullor{"kind": "track"|"identity", "name": ...}, and predicted events add"score"and"has_framewise_scores".
Standalone Video Files¶
You can also use sio show to inspect video files directly:
Example output:
╭─ sleap-io ────────────────────────────────────────────────────────────╮
│ video.mp4 │
│ /data/videos │
│ │
│ Type: Video (MediaVideo) │
│ Size: 934.3 KB │
│ │
│ 1100 frames | 384×384 | grayscale │
╰───────────────────────────────────────────────────────────────────────╯
Full /data/videos/video.mp4
Status Backend loaded (opencv)
Plugin opencv
This is useful for quickly checking video properties without needing a labels file.
sio convert¶
Convert pose data between different file formats.
Basic Usage¶
# Convert SLEAP to NWB
sio convert labels.slp -o labels.nwb
# Convert SLEAP to COCO
sio convert labels.slp -o annotations.json --to coco
# Convert COCO to SLEAP
sio convert annotations.json -o labels.slp --from coco
# Convert TrackMate spot data to SLEAP (auto-detected from headers)
sio convert spots.csv -o labels.slp
# Explicit TrackMate import (skips content sniffing)
sio convert spots.csv -o labels.slp --from trackmate
Options¶
| Option | Description |
|---|---|
-i, --input |
Input file path (can also pass as positional argument) |
-o, --output |
Output file path (required) |
--from |
Input format (required for .json and .h5 files) |
--to |
Output format (inferred from extension if not specified) |
--embed |
Embed video frames in output (user, all, suggestions, source) |
--csv-format |
CSV output format: sleap, dlc, points, instances, frames |
--scorer |
Scorer name for DLC CSV output (default: sleap-io) |
--save-metadata |
Save JSON metadata file for CSV round-trip support |
--h5-dim-order |
HDF5 axis ordering: matlab or standard (analysis_h5 only) |
--min-occupancy |
Filter tracks below this occupancy ratio (analysis_h5 only) |
--coco-category-as-track |
Treat each COCO category as a persistent identity track (coco input only) |
--coco-segmentation |
COCO polygon handling: mask (rasterize) or roi (keep as vector ROIs); default mask (coco input only) |
Supported Formats¶
Input formats: slp, nwb, coco, labelstudio, alphatracker, jabs, dlc, dlc_project, csv, trackmate, ultralytics, leap
Output formats: slp, nwb, coco, labelstudio, jabs, ultralytics, csv, analysis_h5
Events are SLP-only
Frame-spanning events and their event-type catalog are
only representable in the slp format. Converting an event-bearing file to any
other output format drops them, and sio convert prints a warning (to stderr)
saying how many events and event types were discarded.
Format Detection¶
The CLI automatically detects formats from file extensions:
| Extension | Input Format | Output Format |
|---|---|---|
.slp |
SLEAP | SLEAP |
.nwb |
NWB | NWB |
.mat |
LEAP | - |
.csv |
TrackMate or DeepLabCut (auto-detected from headers) | CSV |
.h5 / .hdf5 |
(ambiguous) | Analysis HDF5 |
Directory with data.yaml |
Ultralytics | Ultralytics |
Directory with config.yaml + labeled-data/ (or a project config.yaml) |
DeepLabCut project | - |
For .csv inputs, the CLI first sniffs the file header: TrackMate spots exports are detected via their LABEL,ID,TRACK_ID,... schema, otherwise DeepLabCut multi-index headers are matched, and everything else falls back to the generic csv reader. Pass --from trackmate or --from dlc to bypass sniffing.
A whole DeepLabCut project is auto-detected as dlc_project and merged into a single Labels (use --from dlc_project to be explicit). This differs from --from dlc, which reads a single DLC annotation CSV:
# Import an entire DeepLabCut project (config.yaml + labeled-data/)
sio convert my_dlc_project/ -o labels.slp
sio convert my_dlc_project/config.yaml -o labels.slp --from dlc_project
For COCO instance-segmentation datasets, --coco-category-as-track turns each category into a persistent identity track and --coco-segmentation roi preserves polygons as vector ROIs instead of rasterizing them into masks:
# Identity tracks from COCO categories, polygons kept as vector ROIs
sio convert annotations.json -o labels.slp --from coco \
--coco-category-as-track --coco-segmentation roi
Ambiguous extensions (.json, .h5) require explicit --from:
# .json could be COCO, Label Studio, or AlphaTracker
sio convert -i data.json -o labels.slp --from coco
sio convert -i data.json -o labels.slp --from labelstudio
sio convert -i data.json -o labels.slp --from alphatracker
# .h5 is read as JABS
sio convert -i data.h5 -o labels.slp --from jabs
Embedding Frames¶
Create self-contained package files with embedded video frames:
# Embed only user-labeled frames
sio convert labels.slp -o labels.pkg.slp --embed user
# Embed all frames (including predictions)
sio convert labels.slp -o labels.pkg.slp --embed all
# Embed labeled frames plus suggestions
sio convert labels.slp -o labels.pkg.slp --embed suggestions
Embedding options
user: Only frames with manual annotations (smallest file size)suggestions: Manual annotations plus suggested framesall: All frames with any labels including predictionssource: Re-embed from an already embedded source
Export to Ultralytics YOLO¶
This creates a directory structure compatible with Ultralytics YOLO training:
Export to CSV¶
Export pose data to CSV format for use with spreadsheet tools or custom analysis pipelines. See CSV Format for detailed column specifications.
# Export to SLEAP Analysis CSV (default)
sio convert labels.slp -o output.csv
# Export to DeepLabCut CSV format
sio convert labels.slp -o output.csv --csv-format dlc --scorer MyModel
# Export with metadata for round-trip support
sio convert labels.slp -o output.csv --save-metadata
# Creates: output.csv and output.json
CSV Options¶
| Option | Default | Description |
|---|---|---|
--csv-format |
sleap |
CSV format: sleap, dlc, points, instances, frames |
--scorer |
sleap-io |
Scorer name for DLC format |
--save-metadata |
off | Save JSON metadata file for round-trip support |
CSV Formats¶
sleap: SLEAP Analysis CSV format (one row per instance)dlc: DeepLabCut format (multi-header, one row per frame)points: One row per point (most normalized)instances: One row per instance with node coordinates as columnsframes: One row per frame with all instances multiplexed
Export to Analysis HDF5¶
Export pose data to SLEAP Analysis HDF5 format for use with MATLAB or numerical analysis. See Analysis HDF5 Format for dataset layout and usage examples.
# Export to Analysis HDF5 (MATLAB-compatible ordering)
sio convert labels.slp -o analysis.h5
# Export with Python-native axis ordering
sio convert labels.slp -o analysis.h5 --h5-dim-order standard
# Filter tracks by occupancy
sio convert labels.slp -o analysis.h5 --min-occupancy 0.5
HDF5 Options¶
| Option | Default | Description |
|---|---|---|
--h5-dim-order |
matlab |
Axis ordering: matlab (SLEAP-compatible) or standard |
--min-occupancy |
0.0 |
Filter tracks below this occupancy ratio (0-1) |
sio export¶
Export pose data to analysis-ready formats (CSV, Analysis HDF5) with full control over frame padding, video selection, and output structure.
Export vs Convert
Use sio export when you need analysis-ready outputs with control over frame padding and structure. Use sio convert when transforming between label file formats (SLP, NWB, COCO, etc.).
Basic Usage¶
# Export to CSV (includes all frames, pads missing with NaN)
sio export predictions.slp -o analysis.csv
# Export to Analysis HDF5
sio export predictions.slp -o analysis.h5
# Export only frames with instances (sparse, no padding)
sio export predictions.slp -o sparse.csv --no-empty-frames
# Export specific frame range
sio export predictions.slp -o clip.csv --start 100 --end 500
Options¶
| Option | Default | Description |
|---|---|---|
-i, --input |
(required) | Input labels file (can also pass as positional argument) |
-o, --output |
(required) | Output file path (.csv or .h5) |
--format |
(inferred) | Output format: csv or h5. Inferred from extension if not specified |
CSV Options¶
| Option | Default | Description |
|---|---|---|
--csv-format |
frames |
CSV layout: sleap, dlc, points, instances, frames |
--scorer |
sleap-io |
Scorer name for DLC format |
--save-metadata/--no-metadata |
off | Save JSON metadata alongside CSV |
--video-id |
path |
How to identify videos: path, index, name |
--chunk-size |
(none) | Write CSV in chunks of N rows for memory-efficient export |
HDF5 Options¶
| Option | Default | Description |
|---|---|---|
--h5-dim-order |
matlab |
Axis ordering: matlab (SLEAP-compatible) or standard (frame-first) |
--min-occupancy |
0.0 |
Filter tracks below this occupancy ratio (0-1) |
--h5-metadata/--no-h5-metadata |
on | Save extended metadata for round-trip support |
Frame Selection¶
| Option | Default | Description |
|---|---|---|
--empty-frames/--no-empty-frames |
on | Include frames with no instances (padded with NaN) |
--start |
(none) | Start frame index (inclusive) |
--end |
(none) | End frame index (exclusive) |
--include-scores/--no-scores |
on | Include confidence scores in output |
Video Selection¶
| Option | Default | Description |
|---|---|---|
-v, --video |
(none) | Video to export: index (0, 1, ...) or all for batch export |
Multi-Video Files¶
For labels with multiple videos, you must specify which video to export:
# Export specific video by index
sio export multi.slp -o video0.csv -v 0
sio export multi.slp -o video1.csv -v 1
# Export all videos to separate files
sio export multi.slp -o analysis.csv -v all
# Creates: analysis.video0.csv, analysis.video1.csv, ...
Without -v, exporting a multi-video file will show an error with instructions.
CSV Formats¶
The --csv-format option controls the structure of CSV output:
| Format | Description | Rows |
|---|---|---|
frames |
One row per frame, all instances as columns | Frame-centric |
instances |
One row per instance | Instance-centric |
points |
One row per point | Most normalized |
sleap |
SLEAP Analysis CSV format | Instance-centric |
dlc |
DeepLabCut format (multi-header) | Frame-centric |
# Frame-centric (default) - good for time series analysis
sio export labels.slp -o frames.csv --csv-format frames
# Point-centric - good for database imports
sio export labels.slp -o points.csv --csv-format points
# DeepLabCut compatible
sio export labels.slp -o dlc.csv --csv-format dlc --scorer MyModel
HDF5 Axis Ordering¶
The --h5-dim-order option controls the array axis ordering:
| Preset | tracks shape | Description |
|---|---|---|
matlab |
(tracks, 2, nodes, frames) |
SLEAP-compatible, optimized for MATLAB |
standard |
(frames, tracks, nodes, 2) |
Python-native, intuitive indexing |
# MATLAB-compatible (default, matches SLEAP's export)
sio export predictions.slp -o analysis.h5
# Python-native ordering
sio export predictions.slp -o analysis.h5 --h5-dim-order standard
Memory-Efficient Export for Large Datasets¶
For labels with millions of frames, use --chunk-size to write CSV incrementally without loading the entire DataFrame into memory:
# Write in chunks of 10,000 rows
sio export large_predictions.slp -o analysis.csv --chunk-size 10000
# Combine with other options
sio export large_predictions.slp -o sparse.csv \
--csv-format points \
--no-empty-frames \
--chunk-size 50000
Chunked Writing Limitations
- CSV only: HDF5 export currently requires full materialization in memory
- Not supported for DLC format: DLC format's multi-row header structure is not compatible with chunked writing
Examples¶
# Full export with all options
sio export predictions.slp -o analysis.csv \
--csv-format frames \
--empty-frames \
--start 0 --end 1000 \
--include-scores \
--video-id path
# Sparse export (only labeled frames)
sio export predictions.slp -o sparse.csv --no-empty-frames
# HDF5 with track filtering
sio export predictions.slp -o filtered.h5 --min-occupancy 0.5
# Batch export all videos
sio export multi_video.slp -o export.csv -v all
# Memory-efficient export for large files
sio export large.slp -o analysis.csv --chunk-size 10000
sio split¶
Split a labels file into train/validation/test sets for machine learning workflows.
Basic Usage¶
# Default 80/20 train/val split
sio split labels.slp -o splits/
# Three-way 70/15/15 split
sio split labels.slp -o splits/ --train 0.7 --test 0.15
# Reproducible split with seed
sio split labels.slp -o splits/ --seed 42
Example output:
Split 1000 frames from: labels.slp
Output directory: splits/
train.slp: 800 frames
val.slp: 200 frames
Random seed: 42
Options¶
| Option | Description |
|---|---|
-i, --input |
Input labels file (can also pass as positional argument) |
-o, --output |
Output directory for split files (required) |
--train |
Training set fraction, 0.0-1.0 (default: 0.8) |
--val |
Validation set fraction (default: remainder after train and test) |
--test |
Test set fraction (if not specified, no test split is created) |
--remove-predictions |
Remove predicted instances, keep only user labels |
--seed |
Random seed for reproducible splits |
--embed |
Embed frames in output (user, all, suggestions, source) |
Output Files¶
The command creates split files in the output directory:
splits/
├── train.slp # Training set (or train.pkg.slp if --embed)
├── val.slp # Validation set
└── test.slp # Test set (only if --test specified)
Each output file includes provenance metadata:
source_labels: Path to the original input filesplit: Split name (train,val, ortest)split_seed: Random seed used (if specified)
Removing Predictions¶
For training, you typically want only user-labeled (ground truth) data:
# Keep only user-labeled instances, remove predictions
sio split labels.slp -o splits/ --remove-predictions --seed 42
This:
- Removes all
PredictedInstanceobjects - Clears suggestions
- Removes empty frames and unused tracks/skeletons
Predictions-only files
If your file contains only predictions (no user labels), --remove-predictions will result in an empty dataset and the command will fail with an error.
Creating Embedded Packages¶
For portable training datasets with embedded frames:
# Create package files with embedded user-labeled frames
sio split labels.slp -o splits/ --embed user --seed 42
This creates train.pkg.slp, val.pkg.slp, and optionally test.pkg.slp with frames embedded directly in the files.
Video access required
Embedding frames requires video file access. Video reading works out of the box via the bundled imageio-ffmpeg.
Reproducibility¶
Always use --seed for reproducible experiments:
# Same seed = same split every time
sio split labels.slp -o run1/ --train 0.8 --test 0.1 --seed 42
sio split labels.slp -o run2/ --train 0.8 --test 0.1 --seed 42
# run1/ and run2/ will have identical splits
The seed is stored in each output file's provenance for traceability.
Seed sensitivity to preprocessing
The --seed guarantees reproducibility only when all other options are identical. In particular, --remove-predictions changes which frames are available for splitting (frames with only predictions are removed), which changes the frame count and indexing. This means:
# These will produce DIFFERENT splits even with the same seed:
sio split labels.slp -o run1/ --seed 42
sio split labels.slp -o run2/ --seed 42 --remove-predictions
To ensure reproducibility, always use the same combination of options (especially --remove-predictions) with your seed.
Fraction Behavior¶
- Default (no
--valor--test): 80% train, 20% validation - With
--testonly: Train gets--train, test gets--test, val gets remainder - With explicit
--valand--test: Each split gets its specified fraction
Fractions must be between 0 and 1, and their sum cannot exceed 1.0:
# Valid: 0.7 + 0.15 + 0.15 = 1.0
sio split labels.slp -o splits/ --train 0.7 --val 0.15 --test 0.15
# Error: 0.8 + 0.15 + 0.15 = 1.1 > 1.0
sio split labels.slp -o splits/ --train 0.8 --val 0.15 --test 0.15
sio unsplit¶
Merge multiple split files back into a single labels file. This is the inverse of sio split.
Basic Usage¶
# Merge individual split files
sio unsplit train.slp val.slp -o merged.slp
sio unsplit train.slp val.slp test.slp -o merged.slp
# Merge all .slp files in a directory
sio unsplit splits/ -o merged.slp
# Merge embedded package files
sio unsplit train.pkg.slp val.pkg.slp -o merged.slp
Example output:
Loading: train.slp
800 frames, 1 videos
Merging: val.slp
+200 frames -> 1000 total
Saving: merged.slp
Merged 2 files:
1000 frames, 1 videos
Options¶
| Option | Description |
|---|---|
-o, --output |
Output labels file (required) |
--embed |
Embed frames in output (user, all, suggestions, source) |
Video Deduplication¶
When merging split files created with sio split --embed, videos are automatically deduplicated using provenance metadata. The original_video chain ensures that embedded videos from the same source are merged back into a single video reference.
Modern files (with provenance):
# Videos deduplicate automatically
sio unsplit train.pkg.slp val.pkg.slp -o merged.slp
# Result: 1 video (deduplicated via original_video)
Legacy files (without provenance):
# Videos may not deduplicate
sio unsplit old_train.slp old_val.slp -o merged.slp
# Result: May have multiple videos (safe behavior)
Safe behavior for legacy files
For split files created by older versions of SLEAP (without provenance metadata), videos may not deduplicate. This is intentional—the merge uses conservative matching to avoid data corruption. If needed, use sio filenames to fix video paths after merging.
Directory Input¶
When a directory is provided, all .slp files in that directory are merged (sorted alphabetically):
# These are equivalent:
sio unsplit splits/ -o merged.slp
sio unsplit splits/train.slp splits/val.slp -o merged.slp # If only train.slp and val.slp exist
This is convenient for merging all splits created by sio split.
sio merge¶
A flexible merge command for combining annotations from multiple sources with full control over matching strategies. While sio unsplit is optimized for reunifying train/val/test splits, sio merge handles general-purpose merging scenarios.
Basic Usage¶
# Merge predictions into a labeled project (most common)
sio merge project.slp predictions.slp -o merged.slp
# Merge with explicit frame strategy
sio merge base.slp new.slp -o merged.slp --frame replace_predictions
# Merge multiple files
sio merge file1.slp file2.slp file3.slp -o combined.slp
# Merge all .slp files in directory
sio merge results/ -o combined.slp
# Verbose output with detailed statistics
sio merge project.slp predictions.slp -o merged.slp -v
Example output:
Loading: project.slp
500 frames, 1 videos
Merging: predictions.slp
Strategy: auto
+1000 frames, +2500 instances
Saving: merged.slp
Merged 2 files:
1500 frames, 1 videos
2500 instances added
Options¶
| Option | Default | Description |
|---|---|---|
-o, --output |
(required) | Output labels file |
--skeleton |
structure |
Skeleton matching method |
--video |
auto |
Video matching method |
--track |
identity |
Track matching method |
--identity |
name |
Global identity catalog dedup method (name, identity) |
--category |
name |
Global category catalog dedup method (name, identity) |
--frame |
auto |
Frame merge strategy |
--instance |
spatial |
Instance matching method |
--embed |
(none) | Embed frames in output (user, all, suggestions, source) |
-v, --verbose |
off | Show detailed merge information |
Matching Strategies¶
Skeleton Matching (--skeleton)¶
How to match skeletons between files:
| Method | Behavior |
|---|---|
structure |
Same node names, any order (default) |
subset |
Incoming nodes are subset of base |
overlap |
Sufficient overlap between node sets |
exact |
Nodes and edges must be identical |
Video Matching (--video)¶
How to identify same videos across files:
| Method | Behavior |
|---|---|
auto |
Safe cascade: path, basename, provenance (default) |
path |
Exact path match only |
basename |
Match by filename (ignores directory) |
content |
Shape + backend type |
shape |
Match and merge by shape (image lists) |
image_dedup |
Deduplicate image lists |
# Cross-platform merging (different paths, same filename)
sio merge local.slp remote.slp -o merged.slp --video basename
Track Matching (--track)¶
How to match track identities:
| Method | Behavior |
|---|---|
identity |
Match by track object identity (default). Correctness-first: never collapses distinct tracks by arbitrary tracker-assigned names |
name |
Match tracks with identical names. Opt-in for semantically meaningful names (user-assigned identities or identity-classification model outputs) |
Breaking change in 0.8.0
The default changed from name to identity in v0.8.0 — tracks that merely
share an arbitrary name (e.g. track_0) are no longer merged. Pass
--track name to restore the pre-0.8.0 behavior.
Frame Strategy (--frame)¶
How to handle overlapping frames (same video and frame index in both files):
| Strategy | Behavior | Use case |
|---|---|---|
auto |
Smart merge: preserve user labels, update predictions (default) | Human-in-the-loop workflows |
keep_original |
Ignore incoming for overlapping frames | Preserve base annotations |
keep_new |
Replace base with incoming for overlapping frames | Overwrite with new annotations |
keep_both |
Keep all instances (may create duplicates) | Manual deduplication later |
replace_predictions |
Replace predictions, keep user labels | Re-running inference |
update_tracks |
Copy track assignments only, don't modify poses | Update identity labels |
# Update predictions from new model, keep user labels
sio merge project.slp new_predictions.slp -o merged.slp --frame replace_predictions
# Keep everything (for manual deduplication)
sio merge annotator1.slp annotator2.slp -o combined.slp --frame keep_both
Instance Matching (--instance)¶
For frame strategies that pair instances (auto, update_tracks), how to match instances within a frame:
| Method | Behavior |
|---|---|
spatial |
Match by centroid distance (default) |
identity |
Match by track identity |
iou |
Match by bounding box overlap |
Catalog Deduplication (--identity, --category)¶
How to dedupe the global identity and
category catalogs when combining files. Both default to
name (the key that survives serialization and cross-file merges):
| Method | Behavior |
|---|---|
name |
Merge catalog entries with identical name into one (default) |
identity |
Match only by Python object identity (keep same-named entries from different files distinct) |
# Merge two classified files, collapsing same-named categories into one catalog
sio merge a.slp b.slp -o merged.slp --category name
# Keep every file's identities distinct (no name-based dedup)
sio merge a.slp b.slp -o merged.slp --identity identity
Common Scenarios¶
Merging predictions into a labeled project:
# Default auto strategy handles this well
sio merge project.slp predictions.slp -o merged.slp
# What happens:
# - User labels are preserved
# - Predictions are updated if newer
# - New frames from predictions are added
Combining annotations from multiple annotators:
# Keep all instances for later review
sio merge annotator1.slp annotator2.slp -o combined.slp --frame keep_both
Updating predictions with a new model:
# Replace all predictions, keep user labels
sio merge project.slp new_model_output.slp -o updated.slp --frame replace_predictions
Cross-platform project consolidation:
# Match videos by basename when paths differ
sio merge local_project.slp remote_project.slp -o consolidated.slp --video basename
Differences from sio unsplit¶
| Aspect | sio unsplit |
sio merge |
|---|---|---|
| Purpose | Reunify train/val/test splits | General-purpose merging |
| Frame strategy | Fixed keep_both |
Configurable (default auto) |
| Video matching | Fixed auto |
Configurable (default auto) |
| Provenance | Removes split-specific keys | Preserves all provenance |
| Use case | After sio split |
Any merge scenario |
Use sio unsplit when merging files created by sio split. Use sio merge for all other merging scenarios.
sio embed¶
Create portable .pkg.slp files with video frames embedded directly in the file. This allows sharing labels without requiring access to the original video files.
Basic Usage¶
# Embed user-labeled frames only (default)
sio embed labels.slp -o labels.pkg.slp
# Include prediction-only frames
sio embed labels.slp -o labels.pkg.slp --predictions
# Include suggested frames
sio embed labels.slp -o labels.pkg.slp --suggestions
# Combine flags for all frame types
sio embed labels.slp -o labels.pkg.slp --predictions --suggestions
# Embed only suggestions (skip user frames)
sio embed labels.slp -o labels.pkg.slp --no-user --suggestions
Example output:
Options¶
| Option | Default | Description |
|---|---|---|
-i, --input |
(required) | Input SLP file (can also pass as positional argument) |
-o, --output |
(required) | Output .pkg.slp file path |
--user/--no-user |
on | Include frames with user-labeled instances |
--predictions/--no-predictions |
off | Include frames with only predicted instances |
--suggestions/--no-suggestions |
off | Include suggested frames for labeling |
Frame Types¶
- User frames: Frames containing at least one user-labeled (non-predicted) instance. These are your ground truth annotations.
- Prediction frames: Frames containing only predicted instances (no user labels). Useful for sharing inference results.
- Suggestions: Frames marked for labeling in the suggestions list. May or may not have instances.
Choosing what to embed
- For sharing training data: Use default (
--useronly) for smallest file size - For sharing predictions: Add
--predictionsto include inference results - For active learning: Add
--suggestionsto include frames needing annotation
When to Use sio embed vs sio convert --embed¶
Both commands can embed frames, but they serve different purposes:
sio embed: Granular control over which frame types to include. Best for creating packages.sio convert --embed: Part of format conversion workflow. Uses simpler mode-based embedding.
# Equivalent commands:
sio embed labels.slp -o labels.pkg.slp
sio convert labels.slp -o labels.pkg.slp --embed user
# But sio embed allows more control:
sio embed labels.slp -o labels.pkg.slp --predictions --suggestions
sio unembed¶
Convert an embedded .pkg.slp file back to a regular .slp file that references the original video files. This reverses the embedding process.
Basic Usage¶
Example output:
Options¶
| Option | Description |
|---|---|
-i, --input |
Input .pkg.slp file (can also pass as positional argument) |
-o, --output |
Output .slp file path (required) |
Requirements¶
The unembed command requires:
- Embedded videos: The input file must contain embedded video frames
- Source video metadata: The file must have provenance information about the original videos
If either requirement is not met, you'll get a helpful error message:
# No embedded videos
Error: No embedded videos found. This file does not contain embedded frames.
Use 'sio show --video' to inspect video details.
# Missing source metadata (legacy files)
Error: Cannot unembed: 1/1 embedded video(s) have no source video metadata.
This typically happens with legacy .pkg.slp files created before
source video tracking was added.
To inspect video details, run:
sio show 'labels.pkg.slp' --video
Original videos don't need to exist
The unembed command only updates the file references—it doesn't verify that the original video files exist. You can unembed even if the original videos are on a different machine, then use sio filenames to update the paths.
Embed/Unembed Roundtrip¶
The embed and unembed operations are lossless inverses:
# Original file
sio show labels.slp
# -> 1 video, 100 frames
# Embed frames
sio embed labels.slp -o labels.pkg.slp
# Unembed back to original format
sio unembed labels.pkg.slp -o labels_restored.slp
# Verify: identical annotations
sio show labels_restored.slp
# -> 1 video, 100 frames (same as original)
All annotations, skeletons, tracks, and metadata are preserved exactly.
sio filenames¶
List or update video file paths in a labels file. By default, lists all video filenames for quick inspection. With update options, replaces paths and saves to a new file.
Useful for:
- Quickly checking what video paths are in a labels file
- Moving labels to a new machine with different paths
- Fixing broken video references after reorganizing files
- Cross-platform path conversion (Windows ↔ Linux/macOS)
# Inspection mode (default)
sio filenames <input>
sio filenames -i <input>
# Update mode
sio filenames <input> -o <output> [update options]
Inspection Mode¶
By default, without any update flags, the command lists all video filenames:
Example output:
For image sequences:
This is a quick way to check video paths before deciding how to update them.
For machine-readable output (scripting, LLM agents), use --json:
{
"path": "/data/labels.slp",
"name": "labels.slp",
"videos": [
{
"index": 0,
"filename": "/home/user/data/video.mp4",
"source": null,
"original": null
}
]
}
The source and original fields report the embedded source video and the
root of the provenance chain (equivalent to --source/--original in text
mode). --json is only valid in inspection mode, not with update flags.
Update Modes¶
When you provide -o and one of the update flags, the command updates paths and saves:
| Mode | Option | Description |
|---|---|---|
| List | --filename |
Replace all video filenames in order |
| Map | --map OLD NEW |
Replace specific filenames by exact match |
| Prefix | --prefix OLD NEW |
Replace path prefixes (cross-platform aware) |
You must specify exactly one update mode when updating.
Options¶
| Option | Description |
|---|---|
-i, --input |
Input labels file (can also pass as positional argument) |
-o, --output |
Output labels file path (required for update mode) |
--filename |
New filename (repeat for each video in list mode) |
--map OLD NEW |
Replace OLD filename with NEW (repeat for multiple mappings) |
--prefix OLD NEW |
Replace OLD prefix with NEW (repeat for multiple prefixes) |
--json |
Output as JSON (inspection mode only) |
List Mode¶
Replace all video filenames in order. You must provide exactly one --filename for each video in the labels file:
# Single video file
sio filenames labels.slp -o fixed.slp \
--filename /new/path/video.mp4
# Multiple videos (must match video count in file)
sio filenames multiview.slp -o fixed.slp \
--filename /data/cam1.mp4 \
--filename /data/cam2.mp4 \
--filename /data/cam3.mp4
Video count must match
The number of --filename options must exactly match the number of videos in the labels file. Use sio filenames labels.slp to check the video count first.
Map Mode¶
Replace specific filenames using exact matching. Only videos whose paths match will be updated:
# Replace a single video path
sio filenames labels.slp -o fixed.slp \
--map video.mp4 /data/videos/video.mp4
# Replace multiple specific paths
sio filenames labels.slp -o fixed.slp \
--map recording1.mp4 /nas/project/recording1.mp4 \
--map recording2.mp4 /nas/project/recording2.mp4
Map mode is useful when you only need to update some videos or when you have the exact old and new paths.
Prefix Mode¶
Replace path prefixes. This is the most flexible mode for relocating files:
# Move from absolute to relative paths
sio filenames labels.slp -o fixed.slp \
--prefix /home/user/data ./data
# Cross-platform: Windows to Linux
sio filenames labels.slp -o fixed.slp \
--prefix "C:\Users\lab\data" /mnt/data
# Cross-platform: Linux to Windows
sio filenames labels.slp -o fixed.slp \
--prefix /mnt/data "D:\project\data"
# Multiple prefix replacements
sio filenames labels.slp -o fixed.slp \
--prefix /old/videos /new/videos \
--prefix /old/images /new/images
Cross-platform path handling
Prefix mode automatically normalizes path separators. You can match Windows paths (C:\data) with Linux-style prefixes (C:/data) and vice versa.
Examples¶
Scenario: Moving to a new machine
Your labels file references /home/alice/project/videos/mouse.mp4, but on the new machine the path is /data/experiments/videos/mouse.mp4:
# First, check current paths
sio filenames labels.slp
# Update with new prefix
sio filenames labels.slp -o labels_new.slp \
--prefix /home/alice/project /data/experiments
Scenario: Sharing with a collaborator
Make paths relative so the labels work from any base directory:
Scenario: Windows to Linux server
Labels created on Windows need to work on a Linux cluster:
sio filenames labels.slp -o labels_linux.slp \
--prefix "C:\Users\lab\experiment" /home/lab/experiment
Scenario: Image sequences
The command also works with image sequence videos (where filename is a list of image paths):
# Update prefix for all images in the sequence
sio filenames labels.slp -o fixed.slp \
--prefix /old/frames /new/frames
sio fix¶
Automatically detect and fix common problems in SLEAP labels files, including duplicate videos, unused skeletons, and predictions.
Basic Usage¶
# Auto-detect and fix with safe defaults
sio fix labels.slp
# Preview changes without modifying
sio fix labels.slp --dry-run
# Explicit output path
sio fix labels.slp -o fixed.slp
# Verbose output showing details
sio fix labels.slp -v
Example output:
Loading: labels.slp
26 videos, 715 frames, 2 skeletons, 27 tracks
Analyzing...
⚠ Videos: Found 2 duplicate group(s)
⚠ Skeletons:
'fly_13pt': 1245 user, 500 pred (most frequent)
'fly_copy': 0 user, 0 pred (unused)
✓ Video Color: All videos consistent
ℹ Predictions: 2274 predicted instances (150 untracked)
Actions:
→ Merge 2 duplicate video group(s)
→ Remove 1 unused skeleton(s)
→ Remove unused tracks
→ Remove empty frames
Saved: labels.fixed.slp
25 videos, 715 frames, 1 skeleton, 27 tracks
What Gets Fixed by Default¶
With default options, sio fix automatically:
- Merges duplicate videos: Videos pointing to the same file are consolidated
- Removes unused skeletons: Skeletons with no instances are removed
- Removes prediction-only skeletons: Skeletons used only by predictions (not user labels) are removed along with their predictions
- Cleans up metadata: Unused tracks are removed
- Removes empty frames: Frames with no instances are removed
Options Reference¶
Input/Output Options¶
| Option | Default | Description |
|---|---|---|
-i, --input |
(required) | Input labels file (can also pass as positional argument) |
-o, --output |
{input}.fixed.slp |
Output file. For .pkg.slp files: {input}.fixed.pkg.slp |
--dry-run |
False | Analyze and show what would be done without making changes |
-v, --verbose |
False | Show detailed analysis with per-video and per-skeleton breakdowns |
Video Options¶
| Option | Default | Description |
|---|---|---|
--deduplicate-videos |
True | Merge duplicate video entries pointing to the same file |
--no-deduplicate-videos |
Skip video deduplication | |
--video-color |
Set video color mode: grayscale, rgb, or auto |
Skeleton Options¶
| Option | Default | Description |
|---|---|---|
--remove-unused-skeletons |
True | Remove skeletons with no instances, or only predictions |
--no-remove-unused-skeletons |
Keep all skeletons | |
--consolidate-skeletons |
False | DESTRUCTIVE: Keep most frequent skeleton, delete instances from other skeletons |
Skeleton consolidation is destructive
The --consolidate-skeletons flag will permanently delete user-labeled instances that use non-primary skeletons. Use --dry-run first to review what will be deleted.
Prediction Options¶
| Option | Default | Description |
|---|---|---|
--remove-predictions |
False | Remove ALL predicted instances |
--remove-untracked-predictions |
False | Remove only predictions with no track assignment |
Cleanup Options¶
| Option | Default | Description |
|---|---|---|
--remove-unused-tracks |
True | Remove tracks not used by any instance |
--remove-empty-frames |
True | Remove frames with no instances |
--remove-empty-instances |
False | Remove instances with no visible points |
--remove-unlabeled-videos |
False | Remove videos with no labeled frames |
Path Fixing Options¶
| Option | Description |
|---|---|
--prefix OLD NEW |
Replace OLD path prefix with NEW (repeatable) |
--map OLD NEW |
Replace exact filename OLD with NEW (repeatable) |
Common Scenarios¶
Scenario: Fixing duplicate video entries
SLEAP can sometimes create duplicate video entries pointing to the same file. This causes issues when trying to delete labels:
# Fix automatically (enabled by default)
sio fix labels.slp
# Skip if you want to preserve duplicates
sio fix labels.slp --no-deduplicate-videos
Scenario: Removing all predictions
After manual review, remove all predictions to keep only user labels:
Scenario: Surgical prediction cleanup
Remove only untracked predictions (keeping tracked predictions intact):
Scenario: Multiple skeletons with user labels
When a file has multiple skeletons that both have user-labeled instances, sio fix will warn you:
⚠ WARNING: Multiple skeletons have user instances!
Use --consolidate-skeletons to keep 'fly_13pt' and remove 23 instances.
This is irreversible - review carefully before proceeding.
To force consolidation (keeping the most frequently used skeleton):
# Preview first!
sio fix labels.slp --consolidate-skeletons --dry-run
# Then apply
sio fix labels.slp --consolidate-skeletons
Scenario: Cross-platform path fixing
Fix Windows paths for use on Linux:
Scenario: Aggressive cleanup
Remove everything not essential (predictions, unlabeled videos, empty instances):
Scenario: Minimal cleanup (disable defaults)
Only fix paths without any other cleanup:
sio fix labels.slp \
--no-deduplicate-videos \
--no-remove-unused-skeletons \
--no-remove-unused-tracks \
--no-remove-empty-frames \
--prefix /old/path /new/path
Scenario: Video color mode issues
If videos are being incorrectly detected as grayscale or RGB (e.g., due to compression artifacts or very similar color channels), you can force the color mode:
# Force all videos to grayscale (single channel output)
sio fix labels.slp --video-color grayscale
# Force all videos to RGB (three channel output)
sio fix labels.slp --video-color rgb
# Reset to auto-detection
sio fix labels.slp --video-color auto
This is particularly useful when training models that expect a specific number of input channels.
sio render¶
Create video files or single images with pose annotations overlaid on video frames.
# Video mode (default)
sio render <input> [-o <output>] [options]
# Image mode (single frame)
sio render <input> --lf <index> [-o <output>] [options]
Input argument
Like sio show, the input can be passed as a positional argument or with -i:
Render Modes¶
Video mode (default): Renders all labeled frames to a video file.
Image mode: Renders a single frame to a PNG image. Use --lf or --frame.
Overlay-only mode: Render segmentation overlays on external images without a labels file. Pass --images with a TIFF stack or directory of TIFFs plus --overlay to drop straight into rendering, bypassing the labels requirement. See Segmentation Overlays below.
Basic Usage¶
# Render video with automatic output filename
sio render predictions.slp # -> predictions.viz.mp4
# Render with explicit output path
sio render predictions.slp -o output.mp4
# Fast preview (0.25x resolution)
sio render predictions.slp --preset preview
# Render a specific clip
sio render predictions.slp --start 100 --end 200
# Render a single frame to PNG
sio render predictions.slp --lf 0 # -> predictions.lf=0.png
# Render without source video (solid background)
sio render predictions.slp --background black
sio render predictions.slp --background "#333"
# Segmentation predictions are drawn automatically (no --overlay needed):
# label_images take precedence, falling back to SegmentationMask annotations.
# Works on RGB and single-channel grayscale video.
sio render predictions.slp -o out.mp4
# Overlay a segmentation mask on rendered poses (explicit overlay overrides auto)
sio render predictions.slp --overlay masks.tif --overlay-alpha 0.4
# Overlay-only mode: render masks on images without a labels file
sio render --images frames/ --overlay masks.tif -o output.mp4
Options Reference¶
Input/Output Options¶
| Option | Default | Description |
|---|---|---|
-i, --input |
(required in video/image mode) | Input labels file (can also pass as positional argument). Not required when --images + --overlay are used (overlay-only mode). |
-o, --output |
auto | Output path. Default: {input}.viz.mp4 for video, {input}.lf={N}.png for image |
--background |
video | Background mode: video (load frames) or a color (e.g., black, #333) |
--images |
none | Image source for overlay-only mode (no labels file needed): TIFF stack or directory of TIFFs |
--images-stack / --no-images-stack |
auto | Force 3-D TIFF interpretation: --images-stack treats the file as a frame stack, --no-images-stack as a single image. Default auto-detects based on last dim (3 or 4 → single image, otherwise → stack). |
Frame Selection Options¶
| Option | Default | Description |
|---|---|---|
--lf |
none | Render single labeled frame by index. Outputs PNG. |
--frame |
none | Render single frame by video frame index (use with --video). Outputs PNG. |
--start |
first labeled | Start frame index for video (0-based, inclusive) |
--end |
last labeled | End frame index for video (0-based, exclusive) |
--video |
0 | Video index for multi-video labels |
--all-frames / --labeled-only |
auto | Render all frames or only labeled. Default: --all-frames for single-video files. |
Quality Options¶
| Option | Default | Description |
|---|---|---|
--preset |
none (1.0x) | Quality preset: preview (0.25x), draft (0.5x), final (1.0x) |
--scale |
1.0 | Scale factor (overrides --preset) |
--fps |
source FPS | Output video FPS. Change to slow down or speed up playback. |
--crf |
25 | Video quality (2-32, lower=better quality, larger file) |
--x264-preset |
superfast | H.264 encoding speed trade-off (ultrafast to slow) |
--progress / --no-progress |
on | Show a progress bar during video rendering |
Appearance Options¶
| Option | Default | Description |
|---|---|---|
--color-by |
auto | Color scheme: auto, track, instance, node, identity, category |
--palette |
standard | Color palette (standard, tableau10, distinct, glasbey, rainbow, etc.) |
--marker-shape |
circle | Node marker: circle, square, diamond, triangle, cross |
--marker-size |
4.0 | Node marker radius in pixels |
--line-width |
2.0 | Edge line width in pixels |
--alpha |
1.0 | Pose overlay transparency (0.0-1.0) |
--no-nodes |
false | Hide node markers |
--no-edges |
false | Hide skeleton edges |
Coloring by identity or category
--color-by identity colors each detection by its global
Identity, and --color-by category colors it by its
Category — each gets one palette color per its index in
Labels.identities / Labels.categories order (the same plumbing as
--color-by track). Detections with no identity/category fall back to the first
palette color. Both are explicit-only (never chosen by auto).
Overlay Options¶
See Segmentation Overlays for end-to-end examples.
| Option | Default | Description |
|---|---|---|
--overlay |
none | Segmentation overlay: TIFF file (2-D label image or 3-D stack) or directory of TIFF label images |
--overlay-alpha |
0.3 | Overlay opacity (0.0–1.0) |
--overlay-palette |
distinct | Color palette for overlay labels |
--overlay-outline / --no-overlay-outline |
off | Draw outlines around segmented regions |
--overlay-outline-width |
1 | Outline width in pixels |
--overlay-outline-color |
(darkened fill) | Outline color (e.g., white, #ff0000, 255,0,0) |
Motion Trail Options¶
Trace each animal's path over the last N frames behind the current frame.
Only takes effect when rendering a video (a single labeled frame has no
temporal context).
| Option | Default | Description |
|---|---|---|
--trails |
off | Enable motion-trail overlay drawn beneath poses and centroids. |
--trail-length |
10 | Number of past frames to include in each trail. |
--trail-node |
centroid |
Point to trail. Either centroid, a single node name, or a comma-separated list of node names (one trail per node). |
--trail-width |
2.0 | Trail line width in pixels. |
--trail-fade / --no-trail-fade |
--trail-fade |
Fade trails from faint (oldest) to opaque (newest). |
--trail-alpha |
1.0 | Global opacity multiplier for trails (0.0–1.0). Combines with fade. |
--trail-color |
(match poses) | Uniform color for all trails (e.g., white, #ff0000, 255,0,0). Default matches the pose color (by track or instance). |
Discovery Options¶
| Option | Description |
|---|---|
--list-colors |
Print available named colors and exit |
--list-palettes |
Print available color palettes and exit |
Crop Options (Single Image Only)¶
| Option | Default | Description |
|---|---|---|
--crop |
none | Crop region: x1,y1,x2,y2 (pixels or normalized 0.0-1.0) |
Single Image Rendering¶
Render individual frames to PNG files for figures, thumbnails, or quick inspection:
# Render labeled frame by index (0-based)
sio render predictions.slp --lf 0 # -> predictions.lf=0.png
sio render predictions.slp --lf 42 # -> predictions.lf=42.png
# Render specific video frame by index
sio render predictions.slp --frame 100 # -> predictions.video=0.frame=100.png
sio render predictions.slp --frame 100 --video 1
# Explicit output path
sio render predictions.slp --lf 5 -o frame.png
Labeled frame vs frame index
--lf Nrenders the Nth labeled frame in the file (regardless of video frame number)--frame Nrenders video frame N (must have predictions at that frame)
Cropping (Single Image Only)¶
Crop the output image to focus on specific regions:
# Pixel coordinates (x1, y1, x2, y2)
sio render predictions.slp --lf 0 --crop 100,100,300,300
# Normalized coordinates (center 50% of frame)
sio render predictions.slp --lf 0 --crop 0.25,0.25,0.75,0.75
The crop modes:
- Pixel coordinates:
x1,y1,x2,y2as integers. Use for precise cropping when you know exact pixel locations. - Normalized coordinates:
x1,y1,x2,y2as floats between 0.0-1.0. Use for relative cropping that works across different video resolutions.
Video cropping
--crop applies to video rendering as well as single-image mode. A static x1,y1,x2,y2 region (pixel coordinates or normalized 0.0-1.0) is applied uniformly to every frame.
Video Frame Ranges¶
Render specific portions of the video:
# Frames 100 to 200 (0-based, end is exclusive)
sio render predictions.slp --start 100 --end 200
# From frame 500 to end
sio render predictions.slp --start 500
# First 100 frames
sio render predictions.slp --end 100
Adjusting Playback Speed¶
Use --fps to control playback speed:
# Slow motion (half speed if source is 30fps)
sio render predictions.slp --fps 15
# Speed up (double speed if source is 30fps)
sio render predictions.slp --fps 60
# Fixed frame rate output
sio render predictions.slp --fps 24
Quality Presets¶
Use presets for quick quality/speed trade-offs:
# Fast preview for checking results (0.25x resolution)
sio render predictions.slp --preset preview # -> predictions.viz.mp4
# Draft quality for review (0.5x resolution)
sio render predictions.slp --preset draft
# Full quality for publication (1.0x resolution)
sio render predictions.slp --preset final
# Or specify exact scale
sio render predictions.slp --scale 0.75
Color Schemes¶
Control how poses are colored:
# Auto-select based on data (default)
sio render predictions.slp --color-by auto
# Color by track identity (consistent across frames)
sio render predictions.slp --color-by track
# Color by instance (each animal in frame gets different color)
sio render predictions.slp --color-by instance
# Color by node type (each body part gets different color)
sio render predictions.slp --color-by node
The auto mode uses smart defaults:
- If tracks available → color by track
- If single frame → color by instance
- If video (multiple frames) → color by node
Color Palettes¶
Choose from built-in or colorcet palettes:
# Built-in palettes
sio render predictions.slp --palette distinct
sio render predictions.slp --palette rainbow
sio render predictions.slp --palette tableau10
# Colorcet palettes
sio render predictions.slp --palette glasbey # 256 distinct colors
sio render predictions.slp --palette glasbey_warm
Available built-in palettes: standard (default), distinct, rainbow, warm, cool, pastel, seaborn, tableau10, viridis
Discover available options
Use the discovery flags to see all available colors and palettes:
Marker Shapes and Styles¶
Customize the appearance of pose overlays:
# Different marker shapes
sio render predictions.slp --marker-shape circle
sio render predictions.slp --marker-shape square
sio render predictions.slp --marker-shape diamond
sio render predictions.slp --marker-shape triangle
sio render predictions.slp --marker-shape cross
# Adjust sizes
sio render predictions.slp --marker-size 6 --line-width 3
# Semi-transparent overlays
sio render predictions.slp --alpha 0.7
# Show only edges (no node markers)
sio render predictions.slp --no-nodes
# Show only nodes (no skeleton edges)
sio render predictions.slp --no-edges
Segmentation Overlays¶
sio render can composite segmentation masks over poses or over bare images. Overlays accept a TIFF stack (one frame per plane) or a directory of per-frame TIFF label images, and each integer label is colored via --overlay-palette.
# Segmentation overlay from a TIFF stack on top of pose predictions
sio render predictions.slp --overlay masks.tif --overlay-alpha 0.4
# Overlay from a directory of per-frame TIFFs
sio render predictions.slp --overlay masks/
# Single-frame PNG with overlay and outlines
sio render predictions.slp --lf 0 --overlay masks.tif \
--overlay-outline --overlay-outline-color white
# Overlay-only mode: no labels file, just images + masks
sio render --images frames/ --overlay masks.tif -o output.mp4
# Overlay-only with a TIFF stack of images
sio render --images frames.tif --overlay masks/ --overlay-outline -o output.mp4
# Tweak outline thickness and palette
sio render predictions.slp --overlay masks.tif \
--overlay-palette tableau10 \
--overlay-outline --overlay-outline-width 2
Discovering palettes
Use sio render --list-palettes to print all supported palette names (for both pose and overlay coloring) or sio render --list-colors for the named-color table used by --background, --overlay-outline-color, and similar options.
See Rendering → Segmentation Overlays for Python API equivalents.
Multi-Video Labels¶
For labels with multiple videos, select which video to render:
Example Workflow¶
# 1. Quick preview to check predictions
sio render predictions.slp --preset preview
# 2. Check a specific section
sio render predictions.slp --start 500 --end 600 --preset draft
# 3. Render a single interesting frame
sio render predictions.slp --lf 42 -o highlight.png
# 4. Final render with custom styling
sio render predictions.slp -o final.mp4 \
--color-by track \
--palette tableau10 \
--marker-shape diamond \
--marker-size 5 \
--line-width 2.5
sio trim¶
Trim a video and labels file to a specific frame range, adjusting frame indices accordingly.
# Labels mode: trim labels and video together
sio trim <labels> [--start <frame>] [--end <frame>] [-o <output>] [options]
# Video mode: trim standalone video
sio trim <video> [--start <frame>] [--end <frame>] [-o <output>] [options]
Two modes
Labels mode: Trims both the labels file and associated video, adjusting frame indices.
Video mode: Trims a standalone video file (no labels).
Basic Usage¶
# Trim labels and video to frames 100-1000
sio trim labels.slp --start 100 --end 1000 # -> labels.trim.slp + labels.trim.mp4
# Explicit output path
sio trim labels.slp --start 100 --end 1000 -o clip.slp
# Trim just a video file
sio trim video.mp4 --start 100 --end 500 # -> video.trim.mp4
# Trim from start to frame 1000
sio trim labels.slp --end 1000
# Trim from frame 100 to end of video
sio trim labels.slp --start 100
Options Reference¶
| Option | Default | Description |
|---|---|---|
-i, --input |
(required) | Input labels file or video (can also pass as positional arg) |
-o, --output |
auto | Output path. Default: {input}.trim.slp (labels) or {input}.trim.mp4 (video) |
--start |
0 | Start frame index (0-based, inclusive) |
--end |
last frame + 1 | End frame index (0-based, exclusive) |
--video |
auto | Video index for multi-video labels. Default: 0 if single video |
--fps |
source FPS | Output video FPS. Change to adjust playback speed. |
--crf |
25 | Video quality (2-32, lower=better quality, larger file) |
--x264-preset |
superfast | H.264 encoding speed trade-off (ultrafast to slow) |
Video Encoding Options¶
# Higher quality output (larger file)
sio trim labels.slp --start 100 --end 500 --crf 18
# Slow motion (half speed)
sio trim labels.slp --start 100 --end 500 --fps 15
# Fast, lower compression
sio trim labels.slp --start 100 --end 500 --x264-preset ultrafast
Multi-Video Labels¶
For labels with multiple videos, select which video to trim:
Multi-video requirement
When trimming labels with multiple videos, you must specify --video to select which video to trim. The command will error if multiple videos are present and --video is not provided.
Frame Index Adjustment¶
When trimming labels, frame indices are automatically adjusted to match the new video:
- Original frames 100-500 become frames 0-400 in the trimmed output
- Labeled frames outside the trim range are removed
- Suggestions are filtered and adjusted similarly
sio reencode¶
Reencode videos with frequent keyframes for reliable and fast random access during annotation and playback. This command addresses two critical issues that can cause problems in annotation and computer vision workflows:
-
Unreliable seeking: Some video formats, codecs, or encoding settings cause frame-inaccurate seeking, where requesting frame N returns frame N-1 or N+1. This leads to misaligned annotations that don't match the actual image content.
-
Slow seeking: Videos with sparse keyframes require decoding many intermediate frames to reach a target frame, causing sluggish navigation during annotation.
Why seeking reliability matters
In pose estimation and annotation workflows, even single-frame seeking errors can corrupt your dataset. If you label "frame 100" but your video library actually returns frame 99, your ground truth annotations will be permanently misaligned with the images used during training. This is especially problematic because the errors are often inconsistent and hard to detect.
Common sources of unreliable seeking:
- Variable frame rate (VFR) videos from screen recordings or phones
- Videos with B-frames and complex GOP structures
- AVI files with missing or corrupt index
- Some MP4s encoded with certain camera firmware
- Seeking behavior differences between OpenCV, PyAV, and imageio-ffmpeg
Basic Usage¶
# Reencode with default settings (medium quality, 1 keyframe/second)
sio reencode video.mp4 -o video.seekable.mp4
# Higher quality encoding
sio reencode video.mp4 -o output.mp4 --quality high
# More frequent keyframes for faster seeking
sio reencode video.mp4 -o output.mp4 --keyframe-interval 0.5
# Downsample high-speed video for preview
sio reencode highspeed.mp4 -o preview.mp4 --fps 30 --quality low
# Preview the ffmpeg command without executing
sio reencode video.mp4 -o output.mp4 --dry-run
# Force Python path (for HDF5-embedded sources or when ffmpeg unavailable)
sio reencode video.mp4 -o output.mp4 --no-ffmpeg
# Default output (no -o) is always {stem}.reencoded.mp4
sio reencode video.mov # -> video.reencoded.mp4
# Reencode in place: replace the input with {stem}.mp4 and delete the original
sio reencode video.mov --replace # -> video.mp4 (deletes video.mov)
Output is always MP4
Reencoding always produces an H.264/MP4 file. The default output therefore
uses a .mp4 extension regardless of the input container, and the
.reencoded infix keeps it distinct from the source (even for .mp4
inputs). --replace drops the infix and writes {stem}.mp4 in place,
deleting the original when the extension changes (e.g. .mov → .mp4).
--replace cannot be combined with -o/--output and is not supported for
SLP inputs.
SLP Batch Processing¶
When given an .slp file as input, the reencode command processes all videos in the SLEAP project:
# Reencode all videos in an SLP project
sio reencode project.slp -o project.reencoded.slp
# With quality option
sio reencode project.slp -o project.reencoded.slp --quality high
# Preview what would be done
sio reencode project.slp -o project.reencoded.slp --dry-run
This creates:
- A new SLP file with updated video paths
- A
{output_name}.videos/directory containing the reencoded videos
Behavior by video type:
- MediaVideo (
.mp4,.avi,.mov, etc.): Reencoded using ffmpeg (fast) - HDF5Video (embedded videos in
.slpfiles): Reencoded using Python path - ImageVideo (image sequences): Skipped (cannot be reencoded to video)
- TiffVideo (TIFF stacks): Skipped (cannot be reencoded to video)
- SeqVideo (Norpix
.seqfiles): Reencoded using the Python path (falls back when ffmpeg cannot open the source)
This is particularly useful for:
- Fixing seeking issues in all videos before starting annotation
- Standardizing video formats across a multi-video project
- Extracting embedded videos from
.pkg.slpfiles to standalone MP4s
Options Reference¶
Input/Output Options¶
| Option | Default | Description |
|---|---|---|
-i, --input |
(required) | Input video or SLP file (can also pass as positional argument) |
-o, --output |
{input}.reencoded.mp4 or .slp |
Output video/SLP path (always .mp4 for the video default) |
--replace |
False | Reencode in place: replace the input with {stem}.mp4 and delete the original. Mutually exclusive with -o/--output; not supported for SLP inputs |
--overwrite |
False | Overwrite existing output file |
--dry-run |
False | Show ffmpeg command without executing |
Quality Options¶
| Option | Default | Description |
|---|---|---|
--quality |
medium | Quality level: lossless, high, medium, low |
--crf |
(from quality) | Direct CRF control (0-51, lower=better). Overrides --quality |
Quality level mapping:
| Level | CRF | Description |
|---|---|---|
lossless |
0 | Mathematically identical (huge files) |
high |
18 | Visually lossless |
medium |
25 | Good quality, reasonable size (default) |
low |
32 | Smaller files, some quality loss |
Keyframe Options¶
| Option | Default | Description |
|---|---|---|
--keyframe-interval |
1.0 | Keyframe interval in seconds. Lower = better seekability, larger files |
--gop |
(from interval) | GOP size in frames. Overrides --keyframe-interval |
Choosing keyframe interval
More frequent keyframes improve both seeking speed and reliability:
- 0.5 seconds: 2 keyframes/second - most reliable, fastest seeking, ~50% larger files
- 1.0 second: 1 keyframe/second - good balance (default)
- 2.0 seconds: Smaller files, slightly slower seeking
For maximum reliability in annotation workflows, prefer shorter intervals (0.5-1.0s).
Frame Rate Options¶
| Option | Default | Description |
|---|---|---|
--fps |
source FPS | Output frame rate. Useful for downsampling high-speed video |
Encoding Options¶
| Option | Default | Description |
|---|---|---|
--encoding |
superfast | x264 encoding preset. Slower = better compression |
--use-ffmpeg/--no-ffmpeg |
auto | Force ffmpeg fast path or Python fallback |
Available encoding presets (fastest to slowest): ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow
FFmpeg vs Python path
- FFmpeg path (default): ~10x faster, uses direct ffmpeg subprocess
- Python path (
--no-ffmpeg): Frame-by-frame processing, works with any video source including HDF5-embedded videos
How Reencoding Improves Seeking¶
The reencoded video has several properties that ensure reliable, frame-accurate seeking:
- Regular keyframe intervals: Keyframes (I-frames) can be decoded independently. With keyframes every 1 second at 30fps, the decoder never needs to process more than 30 frames to reach any target.
- No B-frames: The output uses only I-frames and P-frames, eliminating bidirectional dependencies that can confuse some decoders.
- Constant frame rate: Variable frame rate is converted to constant, ensuring frame indices map predictably to timestamps.
- Clean GOP structure: Each group of pictures has a consistent, predictable structure.
- Standard H.264 encoding: Widely supported codec with consistent behavior across video libraries.
Common Scenarios¶
Fixing unreliable seeking for annotation:
# Videos from phones/screen recordings often have VFR issues
sio reencode phone_recording.mp4 -o reliable.mp4
# Camera videos with seeking problems
sio reencode problematic_camera.avi -o reliable.mp4
# Maximum reliability for critical annotation projects
sio reencode raw.mp4 -o reliable.mp4 --keyframe-interval 0.5 --quality high
Fixing slow-seeking videos:
# Basic reencoding with more frequent keyframes
sio reencode slow_video.mp4 -o fast_video.mp4
# Maximum seekability (keyframe every 0.5 seconds)
sio reencode slow_video.mp4 -o fast_video.mp4 --keyframe-interval 0.5
Standardizing video format before annotation:
# Convert and normalize any video before starting annotation
# This prevents seeking issues from corrupting your labels later
sio reencode experiment_video.mov -o experiment_video.mp4
Creating preview videos from high-speed recordings:
# Downsample 250fps to 30fps with lower quality
sio reencode highspeed_250fps.mp4 -o preview.mp4 --fps 30 --quality low
High-quality archival encoding:
# Visually lossless with slow compression for smaller files
sio reencode raw.mp4 -o archival.mp4 --quality high --encoding slow
Processing HDF5-embedded videos:
# Force Python path for embedded video sources
sio reencode embedded_video.h5 -o extracted.mp4 --no-ffmpeg
Output¶
The command displays progress and file size comparison:
Reencoding: video.mp4
Output: video.seekable.mp4
Quality: CRF 25, Preset: superfast, Keyframes: 1.0s
[████████████████████████████████] 100% • 1000/1000 frames
Saved: video.seekable.mp4
Size: 45.2 MB -> 52.1 MB (+15.3%)
File size vs reliability trade-off
More frequent keyframes typically increase file size by 10-50% depending on video content. This trade-off is almost always worthwhile for annotation workflows—the cost of misaligned annotations due to seeking errors far exceeds the cost of additional storage.
sio transform¶
Apply geometric transformations (crop, scale, rotate, pad, flip) to videos while automatically adjusting all landmark coordinates to maintain alignment.
Full Tutorial
For detailed examples with visual galleries, config file specifications, and Python API usage, see the Transforms Guide.
Basic Usage¶
# Scale down 50%
sio transform labels.slp --scale 0.5 -o scaled.slp
# Crop to region (x1,y1,x2,y2)
sio transform labels.slp --crop 100,100,500,500 -o cropped.slp
# Rotate 90 degrees clockwise
sio transform labels.slp --rotate 90 -o rotated.slp
# Flip horizontally
sio transform labels.slp --flip-horizontal -o flipped.slp
# Combined transforms (applied in order: crop -> scale -> rotate -> pad -> flip)
sio transform labels.slp --crop 100,100,500,500 --scale 2.0 -o zoomed.slp
# Preview without processing
sio transform labels.slp --scale 0.5 --dry-run
# Transform raw video (no labels)
sio transform video.mp4 --scale 0.5 -o video_scaled.mp4
Transform Pipeline¶
Transforms are always applied in a fixed order: crop → scale → rotate → pad → flip
All landmark coordinates are automatically transformed using affine matrices to maintain alignment.
Options Reference¶
Input/Output¶
| Option | Description |
|---|---|
-i, --input |
Input SLP file or video |
-o, --output |
Output path (default: {input}.transformed.slp) |
--config |
YAML config file with per-video transforms |
--output-transforms |
Export transform metadata to YAML |
--embed-provenance |
Store transform metadata in output SLP |
--overwrite, -y |
Overwrite existing output files |
Transforms¶
| Option | Format | Description |
|---|---|---|
--crop |
[idx:]x1,y1,x2,y2 |
Crop region (pixels or normalized 0.0-1.0) |
--scale |
[idx:]value or [idx:]w,h |
Scale factor or target dimensions |
--rotate |
[idx:]degrees |
Rotation angle (clockwise positive) |
--clip-rotation |
flag | Keep original dimensions when rotating |
--pad |
[idx:]t,r,b,l |
Padding in pixels |
--flip-horizontal |
flag | Mirror left-right |
--flip-vertical |
flag | Mirror top-bottom |
Quality & Encoding¶
| Option | Default | Description |
|---|---|---|
--quality |
bilinear |
Interpolation: nearest, bilinear, bicubic |
--fill |
0 |
Fill value (0-255 or R,G,B) |
--crf |
25 |
Video quality (0-51, lower = better) |
--x264-preset |
superfast |
Encoding speed |
--fps |
(source) | Output frame rate |
--keyframe-interval |
(none) | Keyframe interval in seconds |
--no-audio |
off | Strip audio |
Execution¶
| Option | Description |
|---|---|
--dry-run |
Preview transforms without executing |
--dry-run-frame N |
Render specific frame in preview |
Per-Video Parameters¶
For multi-video files, use the idx: prefix to target specific videos:
sio transform multi_cam.slp \
--crop 0:100,100,500,500 \
--crop 1:200,200,600,600 \
--scale 0.5 \
-o processed.slp
Config File¶
For complex scenarios, use a YAML config file:
See the Transforms Guide for config file format and examples.
sio download¶
Download a remote file to local disk — a drop-in replacement for curl/wget.
Accepts the same URL schemes as the loaders: http/https, cloud storage
(s3/gs/gcs/az/abfs, needs the [cloud] extra), and Google Drive share
links. HTTP and cloud files are streamed straight to disk with a progress bar;
Google Drive files are buffered in memory first and have no byte progress bar.
Basic Usage¶
# Into the current directory (filename taken from the URL)
sio download https://example.com/labels.slp
# Into a directory, or to an exact path
sio download s3://my-bucket/run/video.mp4 data/
sio download https://example.com/a.slp out.slp
# Authenticated source, forcing a fresh download
sio download https://example.com/a.slp -H 'Authorization: Bearer <token>' -f
If the destination already exists it is returned without re-downloading (pass
-f/--overwrite to refetch).
Options¶
| Option | Description |
|---|---|
-o, --output PATH |
Destination path or directory (alternative to the positional DEST). |
-f, --overwrite |
Re-download even if the destination already exists. |
--progress / --no-progress |
Show a download progress bar (default: on). |
-H, --header 'NAME: VALUE' |
Extra HTTP header (repeatable), e.g. -H 'Authorization: Bearer <token>'. |
--retries N |
Retries for transient HTTP errors (429/5xx). Default: 3. |
See the Remote loading guide for the
Python sio.download equivalent, authentication, and
supported schemes.
Apply Crops¶
sio apply-crops materializes virtual crops (created via Video.crop and
stored in a .slp's /video_crops) into real video files, updating the labels to point at
the baked files. Unlike sio transform --crop (which applies a new crop and adjusts
coordinates), this bakes an existing virtual crop and is coordinate-neutral.
# Bake every virtually-cropped video; baked files go next to the output SLP.
sio apply-crops mosaic.slp -o baked.slp
# Choose the output video directory and filename suffix.
sio apply-crops mosaic.slp -o baked.slp --video-dir baked_videos/ --suffix _crop
Each baked video keeps source_video provenance to the uncropped original; uncropped videos
are left untouched. See the Virtual cropping guide.
Use Cases¶
Inspecting an Unknown Labels File¶
When you receive a .slp file and want to understand its contents:
Checking Video Status Before Processing¶
Before running inference or embedding, verify videos are accessible:
Look for [not found] tags indicating missing videos.
Fixing Broken Video Paths¶
If videos show [not found], update the paths:
# Check current video paths
sio filenames labels.slp
# Update with new location
sio filenames labels.slp -o labels_fixed.slp \
--prefix /old/location /new/location
# Verify fix
sio filenames labels_fixed.slp
Extracting Skeleton Definition¶
Get copyable Python code for the skeleton:
Copy the nodes = [...] and edge_inds = [...] lines directly into your code.
Converting for Sharing¶
Create a portable package with embedded frames:
# Embed user-labeled frames for sharing training data
sio embed project.slp -o project.pkg.slp
# Include predictions and suggestions for complete sharing
sio embed project.slp -o project.pkg.slp --predictions --suggestions
# Later, restore to reference original videos
sio unembed project.pkg.slp -o project_restored.slp
Batch Conversion with Shell Scripts¶
Convert multiple files using shell loops:
Importing from Other Tools¶
Import pose data from other annotation and analysis tools:
# From COCO format (e.g., mmpose, CVAT exports)
sio convert annotations.json -o labels.slp --from coco
# From Label Studio export
sio convert annotations.json -o labels.slp --from labelstudio
# From DeepLabCut analysis (CSV format)
sio convert video_DLC_results.csv -o labels.slp --from dlc
Exporting for Training¶
Export to formats used by other frameworks:
# For Ultralytics YOLO
sio convert labels.slp -o yolo_data/ --to ultralytics
# For tools expecting COCO format
sio convert labels.slp -o annotations.json --to coco
# For NWB-based pipelines (auto-detects annotations vs predictions)
sio convert labels.slp -o data.nwb --to nwb
Rendering Pose Videos¶
Create video visualizations of your pose predictions:
# Quick preview to check predictions
sio render predictions.slp -o preview.mp4 --preset preview
# Final render with custom styling for publication
sio render predictions.slp -o final.mp4 \
--color-by track \
--palette tableau10 \
--marker-shape diamond
Creating Training Splits¶
Prepare datasets for machine learning with reproducible splits:
# Standard 80/10/10 split for training
sio split labels.slp -o experiment1/ --train 0.8 --test 0.1 --seed 42
# Remove predictions and embed frames for portable training data
sio split labels.slp -o training_data/ --remove-predictions --embed user --seed 42
The --seed option ensures you can recreate the exact same split later, which is essential for reproducible experiments. Note that the seed is sensitive to --remove-predictions since it changes the frame count—use the same options consistently.
NWB training annotations
The CLI uses auto-detection for NWB format. For explicit control over NWB format (e.g., annotations vs predictions vs annotations_export with embedded video), use the Python API:
import sleap_io as sio
labels = sio.load_slp("labels.slp")
sio.save_nwb(labels, "training.nwb", nwb_format="annotations")
See NWB Format for details.
Merging Training Splits¶
After training experiments, you may want to recombine split files:
# Merge all splits back into a single file
sio unsplit experiment1/ -o combined.slp
# Or specify files explicitly
sio unsplit train.slp val.slp test.slp -o combined.slp
This is useful for:
- Combining results after separate processing of train/val/test sets
- Reconstructing the original dataset from archived splits
- Merging predictions made on different splits
Videos are automatically deduplicated if the splits were created with sio split --embed.
CI/CD Integration¶
Use uvx in CI pipelines without installation overhead:
# GitHub Actions example
- name: Validate labels file
run: uvx sleap-io show labels.slp
- name: Convert to NWB
run: uvx sleap-io convert -i labels.slp -o labels.nwb
- name: Create package with embedded frames
run: uvx sleap-io convert -i labels.slp -o labels.pkg.slp --embed user
Version and Plugin Info¶
Check installed version and available backends:
Example output:
sleap-io 0.8.0
python 3.12.11
Core:
numpy: 2.4.0
h5py: 3.15.1
imageio: 2.37.2
skia-python: 138.0
colorcet: 3.1.0
Video plugins:
opencv: 4.8.1
pyav: 12.0.0
imageio-ffmpeg: 0.6.0
Optional:
pymatreader: 0.0.32
Troubleshooting video issues
If video-related operations fail, check sio --version to verify video plugins are installed. Look for not installed next to any video plugin.