ScanSeq - High-Performance File Sequence Detection
Fast, Rust-powered library and Python extension for detecting numbered file sequences in VFX, animation, and media production pipelines.
Features
- Parallel Scanning: Uses jwalk for fast directory traversal
- Memory Efficient: Pre-computed digit groups, mask-based grouping
- Smart Detection: Automatically picks longest sequence when files have multiple number groups
- Missing Frame Tracking: Identifies gaps in sequences automatically
- Single File Lookup: Find sequence from any file path in O(n) time
- Builder Pattern: Fluent API for scanner configuration
- Frame Path Resolution: Get file paths for any frame number
- File Scanner: Scan files by extensions with glob patterns (
jp*,tif?)
Quick Start
Rust API
use ;
Add to Cargo.toml:
[]
= "0.1"
Python API
# Create scanner (runs automatically on construction)
=
# Access results via scanner.result
# Get specific frame path
=
# Check completeness
# Static methods
=
=
# Find sequence from a single file
=
# Convert Seq to dict
= # or seq.to_dict()
# Expand to all frame paths
= # ["/renders/shot_0001.exr", ...]
# Rescan with same settings
CLI
# Show help
# Scan paths and print results
# Recursive scan
# With mask filter
# JSON output
# Scan files by extensions (not sequences)
# With glob patterns
# JSON file list
API Reference
Rust
Scanner
Stateful scanner with configuration and results:
ScannerBuilder
Fluent builder for scanner configuration:
ScanResult
get_seqs
Low-level sequence scanning function:
scan_files
Scan files by extensions (returns file paths, not sequences):
Examples:
// Exact extensions
let videos = scan_files?;
// Glob patterns
let images = scan_files?; // jpg, jpeg, jp2, tiff
// All files (empty extensions)
let all = scan_files?;
Seq
Sequence struct with frame operations:
// Implements Display: "Seq("img_####.exr", range: 1-100)"
// Implements Serialize (serde)
Constants
pub const VFX_IMAGE_EXTS: &; // ["exr", "dpx", "tif", "tiff", "png", "jpg", "jpeg", "tga", "hdr"]
pub const VIDEO_EXTS: &; // ["mp4", "mov", "avi", "mkv", "webm", "m4v", "mxf"]
Python
Scanner
Stateful scanner class that runs on construction:
=
Attributes:
# list[str] - directories scanned
# bool
# str | None
# int
# ScanResult - scan results
Static Methods:
# Single path
# Multiple paths
# Find seq from file
Instance Methods:
# Re-scan with current settings
# Number of sequences
# Iterate over sequences
...
ScanResult
# list[Seq] - detected sequences
# float - scan duration in ms
# list[str] - errors encountered
# Number of sequences
# Iterate over sequences
...
Seq
Sequence object with frame information:
# Attributes
# "shot_####.exr" (#### = padded, @ = unpadded)
# First frame number
# Last frame number
# Padding width (4 for 0001)
# list[int] - actual frames present
# list[int] - missing frames
# Frame operations
# Get path for specific frame (None if missing)
# True if no missing frames
# All frame paths in range (including missing)
# Conversion
# Convert to dictionary
# Also works via Mapping protocol
# Item access via Mapping protocol
# Magic methods
# Number of files
# String representation
# Detailed representation
CLI
)
)
)
)
)
Installation
From crates.io
[]
= "0.1"
From Source
# Build CLI
# Install Python module
Architecture
Algorithm
- Scan: Parallel directory traversal with jwalk
- Parse: Extract digit groups from filenames, create masks
- Group: Hash by mask (e.g.,
render_@.exr), sub-group by anchors - Detect: Find frame numbers, compute padding, identify gaps
Pattern Notation
####- Padded sequences (e.g.,0001,0002)@- Unpadded sequences (e.g.,1,2,100)
Examples:
render_####.exr->render_0001.exr,render_0002.exrshot_@.png->shot_1.png,shot_2.png
Examples
Find Missing Frames
let scanner = path.vfx_images.scan;
for seq in scanner.iter
Generate Contact Sheet
let seq = from_file.unwrap;
// Get evenly spaced frames for thumbnail generation
let step = seq.frame_count / 10;
for in seq.indices.iter.step_by.enumerate
Validate Sequence Completeness
=
=
Development
# Run tests
# Build with Python
# Python module dev install
License
MIT