Initial commit: M4 Pro optimized overlay pipeline

This commit is contained in:
Erhan Keseli
2026-01-20 20:20:14 +01:00
commit 98026e0087
8 changed files with 193 additions and 0 deletions

17
.gitignore vendored Normal file
View File

@@ -0,0 +1,17 @@
# Python
__pycache__/
venv/
*.pyc
# Mac OS
.DS_Store
# Media Files (Do not commit these!)
*.mp4
*.mov
*.mkv
*.fit
*.gpx
# Output files
overlay_*

49
README.md Normal file
View File

@@ -0,0 +1,49 @@
# Garmin Video Edit
This project provides a streamlined workflow for overlaying Garmin telemetry data onto video files, specifically optimized for macOS (M4 Pro). It utilizes the `gopro-overlay` toolset to generate high-quality data visualizations from Garmin `.fit` files.
## Prerequisites
- **Python 3.12+**
- **FFmpeg** (installed via Homebrew: `brew install ffmpeg`)
- **macOS** (Optimized for Apple Silicon hardware acceleration)
## Setup
1. **Create and activate a virtual environment:**
```bash
python3 -m venv venv
source venv/bin/activate
```
2. **Install dependencies:**
```bash
pip install -r requirements.txt
```
## Files
- `render.sh`: The main script to trigger the rendering process.
- `ffmpeg-profiles.json`: Custom FFmpeg profiles, including `m4-youtube` for hardware-accelerated H.264 encoding.
- `pro_layout.xml` / `power_layout.xml`: Custom XML layout definitions for the data overlay.
- `Roboto-Medium.ttf`: The font used for the overlay text.
## Usage
To render a video with a Garmin telemetry overlay, use the `render.sh` script:
```bash
./render.sh <PATH_TO_FIT_FILE> <PATH_TO_VIDEO_FILE>
```
### Example:
```bash
./render.sh 21595187246_ACTIVITY.fit footage.mp4
```
The script will generate an output file named `overlay_footage.mov` (where `footage` is the original filename).
## Configuration
- **Layouts**: You can switch between `pro_layout.xml` and `power_layout.xml` by editing the `render.sh` script or modifying the command line arguments.
- **Hardware Acceleration**: The `m4-youtube` profile in `ffmpeg-profiles.json` is configured to use `h264_videotoolbox` for fast rendering on macOS.

BIN
Roboto-Medium.ttf Normal file

Binary file not shown.

10
ffmpeg-profiles.json Normal file
View File

@@ -0,0 +1,10 @@
{
"m4-youtube": {
"input": [],
"output": [
"-c:v", "h264_videotoolbox",
"-b:v", "50000k",
"-profile:v", "high"
]
}
}

16
power_layout.xml Normal file
View File

@@ -0,0 +1,16 @@
<layout>
<!-- HARITA -->
<component name="map" x="2300" y="50" size="1500" type="moving_map" />
<!-- HIZ -->
<component name="speed" x="100" y="1500" type="metric" metric="speed" size="250" units="kph" />
<!-- POWER -->
<component name="power" x="100" y="1800" type="metric" metric="power" size="120" />
<!-- KADANS -->
<component name="cadence" x="500" y="1800" type="metric" metric="cadence" size="120" />
<!-- NABIZ (Duzeltildi: heartbeat -> hr) -->
<component name="heartbeat" x="900" y="1800" type="metric" metric="hr" size="120" />
</layout>

22
pro_layout.xml Normal file
View File

@@ -0,0 +1,22 @@
<layout>
<!-- HARITA: Sag ust, yuvarlak koseli, seffaf -->
<component name="map" type="moving_map" x="3100" y="100" size="650" corner_radius="30" opacity="0.8" />
<!-- SOL ALT: HIZ -->
<component name="speed_val" type="metric" metric="speed" units="kph" dp="0" x="100" y="1650" size="350" align="left" />
<component name="speed_lbl" type="text" x="120" y="2000" size="60" align="left">KM/H</component>
<!-- SAG TARAF: VERILER -->
<!-- POWER -->
<component name="pwr_val" type="metric" metric="power" x="3600" y="900" size="120" align="right" />
<component name="pwr_lbl" type="text" x="3600" y="1020" size="40" align="right">WATTS</component>
<!-- KADANS -->
<component name="cad_val" type="metric" metric="cadence" x="3600" y="1200" size="120" align="right" />
<component name="cad_lbl" type="text" x="3600" y="1320" size="40" align="right">RPM</component>
<!-- NABIZ -->
<component name="hr_val" type="metric" metric="hr" x="3600" y="1500" size="120" align="right" />
<component name="hr_lbl" type="text" x="3600" y="1620" size="40" align="right">BPM</component>
</layout>

76
render.sh Executable file
View File

@@ -0,0 +1,76 @@
#!/bin/bash
# ==============================================================================
# Garmin Overlay Render Script for macOS (M4 Pro Optimized)
# Usage: ./render.sh <PATH_TO_FIT_FILE> <PATH_TO_VIDEO_FILE>
# ==============================================================================
# 1. Validate Arguments
if [ "$#" -ne 2 ]; then
echo "Error: Invalid number of arguments."
echo "Usage: ./render.sh <FIT_FILE> <VIDEO_FILE>"
echo "Example: ./render.sh activity.fit footage.mp4"
exit 1
fi
# 2. Define Variables
FIT_FILE="$1"
VIDEO_FILE="$2"
# Extract filename without extension to auto-generate output name
BASENAME=$(basename "$VIDEO_FILE")
FILENAME="${BASENAME%.*}"
# Output format is .mov because we are using H.264/ProRes containers
OUTPUT_FILE="overlay_${FILENAME}.mov"
# 3. Check and Activate Virtual Environment
# This assumes the script is run from the project root where 'venv' exists
if [ -d "venv" ]; then
source venv/bin/activate
else
echo "Error: 'venv' directory not found. Please run this script from the project root."
exit 1
fi
# 4. Check for Dependencies
if [ ! -f "pro_layout.xml" ] || [ ! -f "ffmpeg-profiles.json" ]; then
echo "Error: Configuration files (pro_layout.xml or ffmpeg-profiles.json) are missing."
exit 1
fi
echo "================================================================"
echo "Starting Render Process"
echo "================================================================"
echo "FIT Data : $FIT_FILE"
echo "Video Input : $VIDEO_FILE"
echo "Output File : $OUTPUT_FILE"
echo "Profile : m4-youtube (Hardware Accelerated H.264)"
echo "Layout : pro_layout.xml"
echo "Timestamp : $(date)"
echo "================================================================"
# 5. Execute gopro-dashboard.py
# Using --use-gpx-only to ignore GoPro metadata and force external FIT data
gopro-dashboard.py \
--use-gpx-only \
--gpx "$FIT_FILE" \
--layout xml \
--layout-xml pro_layout.xml \
--overlay-size 3840x2160 \
--units-speed kph \
--units-altitude meter \
--font "Roboto-Medium.ttf" \
--config-dir . \
--profile m4-youtube \
"$VIDEO_FILE" "$OUTPUT_FILE"
# 6. Completion
if [ $? -eq 0 ]; then
echo "================================================================"
echo "SUCCESS: Render finished. Output saved to: $OUTPUT_FILE"
echo "================================================================"
else
echo "================================================================"
echo "FAILURE: An error occurred during rendering."
echo "================================================================"
fi

3
requirements.txt Normal file
View File

@@ -0,0 +1,3 @@
gopro-overlay
fitdecode
pycairo