runarium 0.1.0

Generate animated videos from GPS running/cycling data with real-time statistics
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
# Runarium πŸƒβ€β™‚οΈ

A Rust library for generating animated videos and static images from GPS running/cycling data. Convert your FIT files into beautiful route visualizations with customizable configurations.

## Features

- πŸ“ Parse GPS data from FIT files (Garmin, Polar, etc.)
- 🎬 Generate animated route videos with progressive drawing
- πŸ–ΌοΈ Generate static route images
- πŸ“Š Display real-time statistics (pace, heart rate, distance)
- πŸ—ΊοΈ Overlay routes on custom background images
- 🎨 Fully customizable colors, fonts, and styling
- ⚑ Fast rendering with OpenCV
- βš™οΈ Configuration-based API for easy customization

## Prerequisites

Before installing, you need to have OpenCV installed on your system.

### macOS

```bash
# Install OpenCV via Homebrew
brew install opencv

# Install LLVM (required for Rust bindings)
brew install llvm

# Set up environment variables (add to ~/.zshrc or ~/.bash_profile)
export LIBCLANG_PATH="/opt/homebrew/opt/llvm/lib"
export SDKROOT="$(xcrun --show-sdk-path)"
export CPATH="$SDKROOT/usr/include"
export CPLUS_INCLUDE_PATH="$SDKROOT/usr/include/c++/v1:$SDKROOT/usr/include"
```

### Linux (Ubuntu/Debian)

```bash
# Install OpenCV development files
sudo apt-get update
sudo apt-get install libopencv-dev clang libclang-dev

# Set environment variable
export LIBCLANG_PATH=/usr/lib/llvm-14/lib  # Adjust version as needed
```

### Windows

```bash
# Install via vcpkg
vcpkg install opencv4

# Set environment variables
set OPENCV_LINK_LIBS=opencv_world4
set OPENCV_LINK_PATHS=C:\path\to\vcpkg\installed\x64-windows\lib
set OPENCV_INCLUDE_PATHS=C:\path\to\vcpkg\installed\x64-windows\include
```

## Installation

Add this to your `Cargo.toml`:

```toml
[dependencies]
runarium = "0.1.0"  # Replace with actual version
```

Or install via cargo:

```bash
cargo add runarium
```

## Usage

### Quick Start - Video Generation

```rust
use anyhow::Result;
use runarium::configs::video_config::{
  Color, FileConfig, Font, LapDataConfig, PaceDistConfig,
  RouteColor, RouteScale, RouteVideoConfig,
};
use runarium::generators::route_video::progressive_route_with_config;

fn main() -> Result<()> {
  // Configure route scale and position
  let route_scale = RouteScale::new(
    0.2,  // scale
    0.1,  // offset_x_percent
    0.1   // offset_y_percent
  );
  
  // Configure colors (BGRA format)
  let colors = RouteColor::new(
    [0.0, 0.0, 255.0, 0.0],     // route_line_color (Red)
    [0.0, 255.0, 0.0, 0.0],     // current_position_color (Green)
    [255.0, 255.0, 255.0, 0.0], // text_color (White)
    [0.0, 165.0, 255.0, 0.0]    // lap_bars_color (Orange)
  );
  
  // Configure pace/distance display
  let pace_dist = PaceDistConfig::new(
    0.6,          // pace_font_scale
    2,            // pace_thickness
    Font::Simplex,// font_face
    None,         // position (auto)
    true,         // show_pace
    true          // show_distance
  );
  
  // Configure lap data panel
  let lap_data = LapDataConfig::new(
    (0.5, 0.09),  // position (x, y)
    0.5,          // lap_font_scale
    1,            // lap_thickness
    Font::Simplex,// font_face
    Color::White, // text_color
    true,         // show_heart_rate
    true,         // show_stride_length
    true          // show_pace_bars
  );
  
  // Set file paths
  let file_config = FileConfig::new(
    "source/example.fit".to_string(),
    "source/example.jpg".to_string(),
    "outputs/video.mp4".to_string(),
  );
  
  // Create and run configuration
  let config = RouteVideoConfig::new(
    route_scale,  // route scale settings
    colors,       // color configuration
    pace_dist,    // pace/distance config
    lap_data,     // lap data panel config
    file_config,  // file paths
    true,         // show_bottom_bar
    true,         // show_route
    true          // show_lap_data
  );
  
  progressive_route_with_config(config)?;
  Ok(())
}
```

### Quick Start - Static Image

```rust
use anyhow::Result;
use runarium::configs::image_config::RouteImageConfig;
use runarium::configs::video_config::{FileConfig, RouteColor, RouteScale};
use runarium::generators::route_image::image_route_with_config;

fn main() -> Result<()> {
  let route_scale = RouteScale::new(
    0.2,  // scale
    0.1,  // offset_x_percent
    0.1   // offset_y_percent
  );
  
  let colors = RouteColor::new(
    [0.0, 0.0, 255.0, 0.0],     // route_line_color (Red)
    [0.0, 255.0, 0.0, 0.0],     // current_position_color (Green)
    [255.0, 255.0, 255.0, 0.0], // text_color (White)
    [0.0, 165.0, 255.0, 0.0]    // lap_bars_color (Orange)
  );
  
  let file_config = FileConfig::new(
    "source/example.fit".to_string(),
    "source/example.jpg".to_string(),
    "outputs/route.png".to_string(),
  );
  
  let config = RouteImageConfig::new(
    route_scale,  // route scale settings
    colors,       // color configuration
    file_config,  // file paths
    2             // line_thickness
  );
  
  image_route_with_config(config)?;
  Ok(())
}
```

### File Structure Required

```
your-project/
β”œβ”€β”€ source/
β”‚   β”œβ”€β”€ example.fit       # Your FIT file with GPS data
β”‚   └── example.jpg       # Background map image
└── outputs/
    β”œβ”€β”€ video.mp4         # Generated video (created automatically)
    └── route.png         # Generated image (created automatically)
```

## Configuration

See [CONFIGURATION.md](CONFIGURATION.md) for detailed configuration options including:
- Route scaling and positioning
- Color customization
- Font styles
- Lap data display options
- Visibility controls

### Available Colors

```rust
Color::Black, Color::White, Color::Red, Color::Green, Color::Blue,
Color::Orange, Color::Yellow, Color::Violet, Color::YellowGreen,
Color::BlueGreen, Color::BlueViolet, Color::RedViolet,
Color::RedOrange, Color::YellowOrange
```

### Available Fonts

```rust
Font::Simplex, Font::Plain, Font::Duplex, Font::Complex,
Font::Triplex, Font::ComplexSmall, Font::ScriptSimplex,
Font::ScriptComplex, Font::Italic
```

## HTTP Server

Runarium includes an HTTP server for generating videos and images via REST API.

### Running the Server

```bash
# Local development
cargo run --example server --release

# Using Docker
make docker-build
make docker-up

# Using Makefile
make server
```

### API Endpoints

- `POST /generate-video` - Generate animated route video
- `POST /generate-image` - Generate static route image
- `GET /download-video/:video_id` - Download generated video (one-time)
- `GET /download-image/:image_id` - Download generated image (one-time)
- `GET /health` - Health check

### Quick Test

```bash
# Test video generation
make api-test-video

# Test video with custom config
make api-test-video-config

# Test image generation
make api-test-image

# Test image with custom config
make api-test-image-config
```

### Example cURL Request

```bash
# Generate video with custom configuration
curl -X POST http://localhost:3000/generate-video \
  -F "fit_file=@source/example.fit" \
  -F "background=@source/example.jpg" \
  -F 'config={
    "scale": 0.3,
    "offset_x_percent": 0.15,
    "offset_y_percent": 0.15,
    "route_line_color": [255.0, 0.0, 0.0, 0.0],
    "show_lap_data": true,
    "show_pace": true
  }'

# Download the video (replace VIDEO_ID with response id)
curl -o output.mp4 http://localhost:3000/download-video/VIDEO_ID
```

See [SERVER.md](SERVER.md) for complete API documentation.

## Examples

Run the included examples:

```bash
# Generate a video with configuration
cargo run --example video_config --release

# Generate a static image with configuration
cargo run --example image_config --release
```

## API Reference

### Video Generation

#### `progressive_route_with_config`

Generates an animated video showing the route being drawn progressively with full configuration control.

```rust
pub fn progressive_route_with_config(config: RouteVideoConfig) -> Result<()>
```

**Configuration includes:**
- Route scale and positioning (`RouteScale`)
- Colors for route, markers, text, and bars (`RouteColor`)
- Pace/distance display settings (`PaceDistConfig`)
- Lap statistics panel settings (`LapDataConfig`)
- File paths (`FileConfig`)
- Visibility flags (show_bottom_bar, show_route, show_lap_data)

**Output Features:**
- Animated route drawing
- Current position marker
- Real-time pace and distance overlay
- Lap statistics panel with heart rate, stride length, and pace bars

### Image Generation

#### `image_route_with_config`

Generates a static image of the complete route with customizable styling.

```rust
pub fn image_route_with_config(config: RouteImageConfig) -> Result<()>
```

**Configuration includes:**
- Route scale and positioning (`RouteScale`)
- Route line color (`RouteColor`)
- File paths (`FileConfig`)
- Line thickness

### Legacy API

Simple functions without configuration are still available:

```rust
// Video generation (simple)
pub fn progressive_route(
    route_scale: f64,
    offset_x_percent: f64,
    offset_y_percent: f64,
) -> Result<()>

// Image generation (simple)
pub fn route_image(
    route_scale: f64,
    offset_x_percent: f64,
    offset_y_percent: f64,
) -> Result<()>
```

### Utility Functions

#### Performance Measurement

```rust
use runarium::utils::performance::measure;

measure("Operation name", || {
    // Your code here
    Ok(())
})?;
```

## Project Structure

```
runarium/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ configs/          # Configuration types
β”‚   β”‚   β”œβ”€β”€ config.rs     # Shared configs (RouteScale, RouteColor, FileConfig)
β”‚   β”‚   β”œβ”€β”€ image_config.rs   # Image-specific config
β”‚   β”‚   └── video_config.rs   # Video-specific config
β”‚   β”œβ”€β”€ generators/       # Main generation functions
β”‚   β”‚   β”œβ”€β”€ route_image.rs    # Static image generation
β”‚   β”‚   └── route_video.rs    # Animated video generation
β”‚   β”œβ”€β”€ types/            # Data types
β”‚   β”‚   β”œβ”€β”€ drawer_data.rs    # Drawing utilities data
β”‚   β”‚   └── fit_data.rs       # FIT file data structures
β”‚   └── utils/            # Utility functions
β”‚       β”œβ”€β”€ converter.rs      # Coordinate conversion
β”‚       β”œβ”€β”€ creator.rs        # Image/video creation
β”‚       β”œβ”€β”€ element_drawer.rs # Drawing utilities
β”‚       β”œβ”€β”€ performance.rs    # Performance measurement
β”‚       └── read_file.rs      # FIT file reading
β”œβ”€β”€ examples/
β”‚   β”œβ”€β”€ video_config.rs   # Video generation example
β”‚   β”œβ”€β”€ image_config.rs   # Image generation example
β”‚   └── server.rs         # HTTP API server
β”œβ”€β”€ CONFIGURATION.md      # Detailed configuration guide
β”œβ”€β”€ SERVER.md             # HTTP server documentation
β”œβ”€β”€ Dockerfile            # Docker container setup
└── docker-compose.yml    # Docker orchestration
```

## Troubleshooting

### OpenCV Not Found

```
error: failed to run custom build command for `opencv`
```

**Solution:** Make sure OpenCV is installed and environment variables are set:
```bash
# macOS
brew install opencv llvm
export LIBCLANG_PATH="/opt/homebrew/opt/llvm/lib"

# Check if OpenCV is found
pkg-config --modversion opencv4
```

### LIBCLANG_PATH Error

```
couldn't find any valid shared libraries matching: ['libclang.dylib']
```

**Solution:** Set the LIBCLANG_PATH environment variable:
```bash
export LIBCLANG_PATH="/opt/homebrew/opt/llvm/lib"
```

Make it permanent by adding to `~/.zshrc`:
```bash
echo 'export LIBCLANG_PATH="/opt/homebrew/opt/llvm/lib"' >> ~/.zshrc
source ~/.zshrc
```

### FIT File Not Found

```
ERROR: field size: 1 is not a multiple of the base type
```

**Solution:** Ensure your FIT file is in the `source/` directory and is a valid FIT file format.

## Performance

Typical performance metrics:
- Processing ~5000 GPS points: ~12 seconds
- Video encoding: Real-time (30 FPS)
- Image generation: <1 second
- Memory usage: ~100-200 MB

## Module Overview

- **configs**: Configuration types for customizing output
- **generators**: Core functions for video and image generation
- **types**: Data structures for FIT data and drawing
- **utils**: Helper utilities for file I/O, conversion, and rendering

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## License

[Add your license here]

## Credits

Built with:
- [opencv-rust]https://github.com/twistedfall/opencv-rust - OpenCV bindings for Rust
- [fitparser]https://github.com/stadelmanma/fitparse-rs - FIT file parser
- [image]https://github.com/image-rs/image - Image processing

## Roadmap

- [x] Support for FIT file parsing
- [x] Animated video generation
- [x] Static image generation
- [x] Customizable color schemes
- [x] Configuration-based API
- [x] Font customization
- [x] HTTP REST API server
- [x] Docker deployment support
- [ ] Support for multiple file formats (GPX, TCX)
- [ ] Command-line interface
- [ ] Preset configuration templates
- [ ] Web-based visualization
- [ ] Real-time preview