WiFi DensePose Latency and FPS: Real-Time Performance Metrics Explained
WiFi DensePose streams pose estimation data at a default 30 FPS with average latency under 100 ms, while the underlying model maintains inference throughput above 10 FPS as validated by integration tests in the ruvnet/wifi-densepose repository.
WiFi DensePose enables real-time human pose estimation using WiFi channel state information (CSI) transmitted over WebSocket connections. Understanding the latency and FPS characteristics is critical for deploying this open-source system in time-sensitive applications. This article examines the exact performance metrics defined in the codebase, how they are measured, and where to monitor them in production.
Default Streaming Performance Metrics
WiFi DensePose separates streaming FPS (the rate at which pose data is broadcast to clients) from inference FPS (the speed of the neural network processing).
Streaming FPS Configuration
The default streaming frequency is defined in the Pydantic settings model. In v1/src/config/settings.py, the stream_fps field controls how often the WebSocket server emits new pose frames:
# v1/src/config/settings.py
stream_fps: int = Field(default=30, description="Streaming frames per second")
This 30 FPS default translates to a frame interval of approximately 33.3 ms, calculated as 1 / stream_fps.
Latency Benchmarks
Latency is measured as the round-trip time between receiving CSI data, running the pose model, and broadcasting the result. The integration test suite in v1/tests/integration/test_streaming_pipeline.py enforces strict performance boundaries:
# v1/tests/integration/test_streaming_pipeline.py
assert latency > 0
assert latency < 200 # per-frame must be < 200 ms
assert avg_latency < 100 # average < 100 ms
These assertions confirm that WiFi DensePose maintains per-frame latency under 200 ms and average latency under 100 ms under test conditions.
How Performance Is Measured in the Codebase
The system tracks performance through three architectural layers: configuration, runtime statistics, and WebSocket timing control.
Configuration Layer
The Settings class in v1/src/config/settings.py serves as the single source of truth for streaming parameters. Beyond the default 30 FPS, it allows runtime overrides through environment variables or query parameters.
Runtime Statistics
The StreamService class in v1/src/services/stream_service.py maintains a live statistics dictionary that tracks latency and throughput:
# v1/src/services/stream_service.py
self.stats = {
"active_connections": 0,
"total_connections": 0,
"messages_sent": 0,
"messages_failed": 0,
"data_points_streamed": 0,
"average_latency_ms": 0.0
}
The average_latency_ms value updates dynamically after each frame broadcast, providing real-time visibility into system performance.
WebSocket Timing Control
The actual frame emission timing is controlled in v1/src/api/websocket/pose_stream.py. The WebSocket loop uses an asynchronous sleep interval calculated from the configured FPS:
# v1/src/api/websocket/pose_stream.py
await asyncio.sleep(1.0 / self.stream_config["fps"])
This ensures that the server respects the stream_fps setting regardless of inference speed, buffering or skipping frames as necessary to maintain the target broadcast rate.
Inference Throughput vs. Streaming FPS
It is important to distinguish between the streaming FPS (WebSocket broadcast rate) and the inference FPS (model processing speed).
Model Inference Speed
The neural network processing speed depends on hardware and model complexity. The performance test suite in v1/tests/performance/test_inference_speed.py validates the minimum throughput:
# v1/tests/performance/test_inference_speed.py
assert stats["throughput_fps"] > 10 # at least 10 fps overall
Additionally, the benchmark verifies that lightweight model configurations can achieve:
# v1/tests/performance/test_inference_speed.py
assert result["inference_time_ms"] < 50 # lightweight model < 50 ms
This translates to approximately 20 FPS inference capability for optimized models.
Performance Test Validation
The integration tests ensure that the system gracefully handles the mismatch between inference and streaming speeds. When inference is slower than the streaming FPS, the system buffers or interpolates frames to maintain the WebSocket broadcast rate without breaking the latency constraints.
Monitoring Real-Time Metrics
You can access current performance data through both programmatic APIs and HTTP endpoints.
Retrieve Current Streaming FPS
from src.config.settings import get_settings
settings = get_settings()
print(f"Current streaming FPS: {settings.stream_fps}")
Access Runtime Latency Statistics
from src.services.stream_service import StreamService
from src.config.settings import get_settings
from src.config.domains import DomainConfig
service = StreamService(get_settings(), DomainConfig())
# … after the service has processed a few frames …
print(f"Average latency (ms): {service.stats['average_latency_ms']}")
Query Metrics via HTTP
curl http://localhost:8000/api/v1/metrics
The JSON response includes:
{
"stream_service": {
"average_latency_ms": 84.2,
"stream_fps": 30,
"data_points_streamed": 1200
}
}
Override FPS for Specific Clients
You can adjust the streaming rate per WebSocket connection using query parameters:
# WebSocket URL – set max_fps query param (max 60)
ws://localhost:8000/api/v1/stream/pose?zone_ids=zone_1&max_fps=45
Summary
- Default streaming FPS is 30, configurable via
v1/src/config/settings.pyor WebSocket query parameters. - Average latency stays under 100 ms with a per-frame maximum of 200 ms, enforced by integration tests in
v1/tests/integration/test_streaming_pipeline.py. - Inference throughput exceeds 10 FPS independently of the streaming rate, with lightweight models capable of 20 FPS (50 ms per inference).
- Real-time monitoring is available through
StreamService.statsand the/api/v1/metricsHTTP endpoint.
Frequently Asked Questions
What is the default FPS of WiFi DensePose?
The default streaming FPS is 30, defined in the stream_fps field within v1/src/config/settings.py. This value controls how frequently the WebSocket server broadcasts pose estimation frames to connected clients, translating to a frame interval of approximately 33.3 milliseconds.
How does WiFi DensePose measure latency?
Latency is calculated as the round-trip time between receiving CSI data, executing the pose estimation model, and broadcasting the result via WebSocket. The StreamService class in v1/src/services/stream_service.py tracks this in the stats["average_latency_ms"] dictionary field, which updates dynamically after each frame transmission.
Can the streaming FPS be adjusted dynamically?
Yes, the streaming FPS can be overridden at runtime. Clients can specify the max_fps query parameter when establishing a WebSocket connection (e.g., ws://localhost:8000/api/v1/stream/pose?max_fps=45), or developers can modify the stream_fps value in the Settings class before service initialization.
What is the difference between streaming FPS and inference FPS?
Streaming FPS refers to the rate at which pose data is broadcast to clients via WebSocket (default 30 FPS), controlled by v1/src/api/websocket/pose_stream.py. Inference FPS refers to the neural network processing speed, which the performance tests in v1/tests/performance/test_inference_speed.py validate at >10 FPS (up to 20 FPS for lightweight models). The system buffers or interpolates frames when inference speed differs from the streaming rate.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →