High-performance EVT 3.0 raw data decoder for Prophesee event cameras, written in Rust.
5.6x faster than the C++ reference implementation with byte-for-byte identical output.
- 🚀 High Performance - 50M+ events/second, 5.6x faster than C++ reference
- 📦 Multiple Interfaces - CLI tool, Python bindings, Rust library
- 🐍 Zero-copy Python - NumPy array access via PyO3
- 🧪 Optional HDF5 Input -
.h5and.hdf5support behind a cargo feature - ✅ Validated - Output matches C++ reference implementation exactly
- 🔧 Customizable - Configurable output field order
curl -sSL https://raw.githubusercontent.com/muthmann/evt3/main/install.sh | bashThis downloads the binary to ~/.local/bin/evt3. You may need to add it to your PATH:
# Add to ~/.bashrc or ~/.zshrc
export PATH="$HOME/.local/bin:$PATH"Download from Releases:
| Platform | Binary |
|---|---|
| Linux x64 | evt3-linux-x64 |
| Linux ARM64 | evt3-linux-arm64 |
| macOS Intel | evt3-macos-x64 |
| macOS Apple Silicon | evt3-macos-arm64 |
| Windows | evt3-windows-x64.exe |
# Example for macOS Apple Silicon
curl -LO https://github.com/muthmann/evt3/releases/latest/download/evt3-macos-arm64
chmod +x evt3-macos-arm64
./evt3-macos-arm64 recording.raw events.csvUsing uv (recommended):
uv pip install evt3Or with pip:
pip install evt3Published wheels target CPython 3.9 through 3.13.
Note: The pip package supports
.rawfiles only. HDF5 (.h5/.hdf5) requires building from source — see HDF5 Inputs below.
# Clone repository
git clone https://github.com/muthmann/evt3.git
cd evt3
# Build CLI (requires Rust)
cargo build --release
# The binary is at: ./target/release/evt3
./target/release/evt3 recording.raw events.csv
# Optional HDF5 support
HDF5_DIR="$(brew --prefix hdf5)" cargo build --release -p evt3-cli --features hdf5
# Optional: Install to PATH
cp target/release/evt3 ~/.local/bin/
# Build Python package (requires Python 3.9+, uv + Rust)
cd evt3-python
uv venv
uv pip install maturin
source .venv/bin/activate
maturin develop --release# Decode to CSV (default: x,y,p,t)
evt3 recording.raw events.csv
# Timestamp-first format
evt3 recording.raw events.csv --format "t,x,y,p"
# Binary output (more efficient)
evt3 recording.raw events.bin
# Include trigger events
evt3 recording.raw events.csv --triggers triggers.csv
# Quiet mode
evt3 recording.raw events.csv --quietimport evt3
import numpy as np
# Decode a .raw or .h5 file — format is auto-detected by extension
events = evt3.decode_file("recording.raw")
events = evt3.decode_file("recording.h5") # requires hdf5 feature at build time
print(f"Decoded {len(events):,} events")
print(f"Sensor: {events.sensor_width}x{events.sensor_height}")
# Access as NumPy arrays (zero-copy)
x = events.x # np.ndarray[uint16]
y = events.y # np.ndarray[uint16]
p = events.polarity # np.ndarray[uint8]
t = events.timestamp # np.ndarray[uint64] (microseconds)
# Basic analysis
print(f"Duration: {(t[-1] - t[0]) / 1e6:.2f} seconds")
print(f"Event rate: {len(events) / ((t[-1] - t[0]) / 1e6):.0f} events/sec")
# Create pandas DataFrame
import pandas as pd
df = pd.DataFrame(events.to_dict())use evt3_core::Evt3Decoder;
let mut decoder = Evt3Decoder::new();
let result = decoder.decode_file("recording.raw")?;
println!("Decoded {} events", result.cd_events.len());
for event in result.cd_events.iter().take(10) {
println!("x={}, y={}, p={}, t={}",
event.x, event.y, event.polarity, event.timestamp);
}For live camera pipelines or embedded integrations, you can stream raw USB
packet bytes directly into the decoder without converting to Vec<u16> first:
use evt3_core::Evt3Decoder;
let mut decoder = Evt3Decoder::new();
let mut cd_events = Vec::new();
let mut trigger_events = Vec::new();
for chunk in usb_packet_chunks {
decoder.decode_bytes(chunk, &mut cd_events, &mut trigger_events)?;
}
decoder.finish_stream()?;This keeps evt3-core usable in incremental preview paths while preserving the
existing file and word-based APIs.
Notes:
decode_bufferstill expects 16-bit EVT3 words, not raw bytes.decode_bytesexpects little-endian EVT3 payload bytes and can be called with odd-sized chunks.- Call
finish_stream()only when the stream is complete so a trailing half-word is reported as an error instead of being buffered for the next chunk. .h5and.hdf5decoding is available when the crate or binary is built with thehdf5feature.
Important: HDF5 support requires
libhdf5(a native C library) and is not included inpip install evt3or pre-built CLI binaries. It must be built from source. See docs/features/hdf5-file-support.md for the full limitations table.
# macOS
brew install hdf5
HDF5_DIR="$(brew --prefix hdf5)" cargo build --release -p evt3-cli --features hdf5
./target/release/evt3 recording.h5 events.csv
# Ubuntu / Debian
sudo apt install libhdf5-dev
cargo build --release -p evt3-cli --features hdf5
./target/release/evt3 recording.h5 events.csvMost Prophesee HDF5 files use the ECF compression codec, which requires an additional runtime plugin:
# Build and install the ECF plugin (one-time, macOS/Linux/Windows)
./scripts/install-ecf-plugin.sh
# Then set the plugin path before running
export HDF5_PLUGIN_PATH="$HOME/.local/share/hdf5/plugin"
./target/release/evt3 recording.h5 events.csvNotes:
- Builds without
--features hdf5return a clear error rather than silently failing. - Real-data integration tests that skip still show as
ok. Run with-- --show-outputto see[SKIP]reasons. - Full plugin and dependency documentation: docs/features/hdf5-file-support.md
Tested on Apple M1 with laser.raw (325MB, 116M events):
| Decoder | Events/sec | Speedup |
|---|---|---|
| Rust (Python) | 49M/s | 5.6x |
| Rust CLI | 12M/s | 1.3x |
| C++ Reference | 9M/s | 1.0x |
Note: Python benchmark measures pure decode speed. CLI benchmarks include CSV file I/O overhead.
Run benchmarks yourself:
cargo bench
python benchmarks/benchmark.pyHuman-readable, with optional geometry header:
%geometry:1280,720
642,481,1,10960097
783,415,1,10960139
...Efficient packed format for programmatic access:
- 8-byte magic header:
EVT3BIN\0 - 24-byte metadata: version, width, height, event count
- Events: 14 bytes each (x:u16, y:u16, polarity:u8, pad:u8, timestamp:u64)
EVT 3.0 is a 16-bit vectorized event encoding from Prophesee. This decoder supports:
| Event Type | Code | Description |
|---|---|---|
| EVT_ADDR_Y | 0x0 | Y coordinate |
| EVT_ADDR_X | 0x2 | Single event (X + polarity) |
| VECT_BASE_X | 0x3 | Base X for vectors |
| VECT_12 | 0x4 | 12-event vector |
| VECT_8 | 0x5 | 8-event vector |
| EVT_TIME_LOW | 0x6 | Lower 12 bits of timestamp |
| EVT_TIME_HIGH | 0x8 | Upper 12 bits of timestamp |
| EXT_TRIGGER | 0xA | External trigger |
For full specification: Prophesee EVT 3.0 Documentation
evt3/
├── evt3-core/ # Core Rust decoder library
├── evt3-cli/ # Command-line tool
├── evt3-python/ # Python bindings (PyO3)
├── benchmarks/ # Performance benchmarks
└── test_data/ # Sample EVT3 files
See CONTRIBUTING.md for development setup and guidelines.
Licensed under the MIT License - see LICENSE-MIT for details.