A powerful Rust library for processing and analyzing Rocket League replay files. Built on top of the boxcars parser, subtr-actor simplifies the complex actor-based structure of replay files into easy-to-use data formats.
subtr-actor transforms Rocket League replay files into structured data that's perfect for:
- Data analysis - Extract detailed player statistics, ball movement, and game events
- Machine learning - Generate training datasets from replay data
- Research - Study player behavior and game dynamics
- Visualization - Create custom replay viewers and analysis tools
- π High-performance processing - Efficiently handles large replay files
- π Multiple output formats - JSON, NumPy arrays, and custom data structures
- π― Frame-by-frame precision - Access every detail of gameplay
- π Language bindings - Use from JavaScript, Python, or Rust
- π§© Extensible architecture - Add custom data extractors and processors
Add to your Cargo.toml
:
[dependencies]
subtr-actor = "0.1.8"
pip install subtr-actor-py
npm install rl-replay-subtr-actor
use subtr_actor::ReplayDataCollector;
use boxcars::ParserBuilder;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Load and parse replay file
let data = std::fs::read("my_replay.replay")?;
let replay = ParserBuilder::new(&data)
.must_parse_network_data()
.parse()?;
// Extract structured data
let collector = ReplayDataCollector::new();
let replay_data = collector.get_replay_data(&replay)?;
// Convert to JSON
let json = replay_data.as_json()?;
println!("{}", json);
Ok(())
}
use subtr_actor::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let data = std::fs::read("my_replay.replay")?;
let replay = ParserBuilder::new(&data)
.must_parse_network_data()
.parse()?;
// Configure data extraction
let mut collector = NDArrayCollector::new(
vec![
InterpolatedBallRigidBodyNoVelocities::arc_new(0.003),
CurrentTime::arc_new(),
],
vec![
InterpolatedPlayerRigidBodyNoVelocities::arc_new(0.003),
PlayerBoost::arc_new(),
PlayerAnyJump::arc_new(),
],
);
// Process at 30 FPS
FrameRateDecorator::new_from_fps(30.0, &mut collector)
.process_replay(&replay)?;
let (meta, array) = collector.get_meta_and_ndarray()?;
println!("Generated {}Γ{} training matrix", array.nrows(), array.ncols());
Ok(())
}
import subtr_actor_py
# Load replay and extract data
with open("my_replay.replay", "rb") as f:
replay_data = f.read()
result = subtr_actor_py.get_replay_data(replay_data)
print(f"Found {len(result['players'])} players")
import * as subtrActor from 'rl-replay-subtr-actor';
// Load replay file
const replayData = await fetch('my_replay.replay')
.then(r => r.arrayBuffer())
.then(buffer => new Uint8Array(buffer));
// Extract structured data
const result = subtrActor.get_replay_data(replayData);
console.log(`Replay duration: ${result.duration} seconds`);
The heart of subtr-actor's processing pipeline. It handles the complex task of navigating through replay frames and maintaining game state.
Pluggable data extractors that define what information to extract from replays:
ReplayDataCollector
- Extracts comprehensive replay data as JSON-serializable structuresNDArrayCollector
- Generates numerical arrays perfect for machine learning- Custom collectors - Implement the
Collector
trait for specialized data extraction
Configurable extractors that specify exactly what data to capture:
- Global features - Ball position, game time, score
- Player features - Position, boost, controls, team info
- Custom features - Implement
FeatureAdder
orPlayerFeatureAdder
traits
use subtr_actor::*;
// Create custom feature adders
build_global_feature_adder!(
CustomBallFeature,
f32,
3, // Output 3 values
|processor, _time| {
// Extract custom ball data
let ball_data = processor.get_ball_data();
Ok(vec![ball_data.x, ball_data.y, ball_data.z])
}
);
// Process at custom frame rate
let mut collector = ReplayDataCollector::new();
FrameRateDecorator::new_from_fps(60.0, &mut collector)
.process_replay(&replay)?;
Useful for language bindings or configuration files:
let collector = NDArrayCollector::<f32>::from_strings(
&["BallRigidBody", "CurrentTime"],
&["PlayerRigidBody", "PlayerBoost", "PlayerAnyJump"]
)?;
pub struct ReplayData {
pub frame_data: FrameData, // Frame-by-frame game data
pub meta: ReplayMeta, // Player info, game settings
pub demolish_infos: Vec<DemolishInfo>, // Demolition events
}
pub struct FrameData {
pub ball_data: BallData, // Ball position/physics over time
pub players: Vec<(PlayerId, PlayerData)>, // Player data by ID
pub metadata_frames: Vec<MetadataFrame>, // Game state metadata
}
- Full API access through Python functions
- NumPy integration for data analysis
- Ideal for data science workflows
- WebAssembly-based for high performance
- Works in browsers and Node.js
- Perfect for web applications
- Use appropriate frame rates - Higher FPS = more data but slower processing
- Select only needed features - Fewer feature adders = faster processing
- Batch processing - Process multiple replays in parallel
- Memory management - Consider streaming for very large datasets
We welcome contributions! Please check our issues for ways to help.
git clone https://github.com/rlrml/subtr-actor.git
cd subtr-actor
cargo build
cargo test
# Python
cd python && poetry build
# JavaScript
cd js && npm run build
MIT License - see LICENSE file for details.
- boxcars - The underlying replay parser
- ballchasing.com - Replay analysis platform
- π Documentation
- π Issue Tracker
- π¬ Discussions