403a16c137
Comprehensive analysis of exercise data sources: - ExerciseDB API (1,300+ exercises with GIFs) - wger (open source, self-hostable) - free-exercise-db (public domain) - MusclesWorked, API Ninjas Includes: - Data structure recommendations - Exercise substitution patterns - Import script examples - License summary
438 lines
11 KiB
Markdown
438 lines
11 KiB
Markdown
# Övningsdatabaser & APIs — Research för Gravl
|
|
|
|
## Sammanfattning
|
|
|
|
Det finns flera högkvalitativa, **gratis och open source** övningsdatabaser tillgängliga. De bästa alternativen är:
|
|
|
|
| Databas | Övningar | Media | Licens | API |
|
|
|---------|----------|-------|--------|-----|
|
|
| **ExerciseDB** | 1,300-11,000 | GIF | Open Source | ✅ REST |
|
|
| **wger** | 800+ | Bilder | AGPL | ✅ REST |
|
|
| **free-exercise-db** | 800+ | Bilder | Public Domain | JSON |
|
|
| **MusclesWorked** | 856 | — | Commercial | ✅ REST + MCP |
|
|
| **API Ninjas** | 3,000+ | — | Freemium | ✅ REST |
|
|
|
|
**Rekommendation:** Kombinera **ExerciseDB** (GIF-demos, omfattande) med **wger** (open source, self-hosted möjligt).
|
|
|
|
---
|
|
|
|
## Top Picks
|
|
|
|
### 1. ExerciseDB API (Rekommenderat)
|
|
|
|
**URL:** https://exercisedb.dev / https://github.com/cyberboyanmol/exercisedb-api
|
|
|
|
**Styrkor:**
|
|
- 1,300+ övningar (v1) eller 11,000+ (v2)
|
|
- GIF-demonstrationer för varje övning
|
|
- Detaljerad metadata
|
|
- Open source (self-hostable)
|
|
- Aktiv utveckling
|
|
|
|
**Data per övning:**
|
|
```json
|
|
{
|
|
"id": "0001",
|
|
"name": "3/4 sit-up",
|
|
"target": "abs",
|
|
"bodyPart": "waist",
|
|
"equipment": "body weight",
|
|
"gifUrl": "https://...",
|
|
"secondaryMuscles": ["hip flexors"],
|
|
"instructions": [
|
|
"Lie flat on your back with your knees bent...",
|
|
"Place your hands behind your head...",
|
|
"..."
|
|
]
|
|
}
|
|
```
|
|
|
|
**Endpoints:**
|
|
```
|
|
GET /exercises - Alla övningar
|
|
GET /exercises/bodyPart/{part} - Filter på kroppsdel
|
|
GET /exercises/equipment/{equip} - Filter på utrustning
|
|
GET /exercises/target/{muscle} - Filter på målmuskel
|
|
GET /exercises/{id} - Specifik övning
|
|
```
|
|
|
|
**Bodyparts:**
|
|
- back, cardio, chest, lower arms, lower legs
|
|
- neck, shoulders, upper arms, upper legs, waist
|
|
|
|
**Equipment:**
|
|
- assisted, band, barbell, body weight, bosu ball
|
|
- cable, dumbbell, elliptical machine, ez barbell
|
|
- hammer, kettlebell, leverage machine, medicine ball
|
|
- olympic barbell, resistance band, roller, rope
|
|
- skierg machine, sled machine, smith machine
|
|
- stability ball, stationary bike, stepmill machine
|
|
- tire, trap bar, upper body ergometer, weighted
|
|
- wheel roller
|
|
|
|
---
|
|
|
|
### 2. wger (Open Source, Self-Hosted)
|
|
|
|
**URL:** https://wger.de / https://github.com/wger-project/wger
|
|
|
|
**Styrkor:**
|
|
- Helt open source (AGPL)
|
|
- Self-hosted möjligt (Docker)
|
|
- 800+ övningar
|
|
- Stöd för flera språk (inkl. svenska möjligt)
|
|
- Workout manager ingår
|
|
- Nutrition tracking ingår
|
|
- REST API
|
|
|
|
**Data per övning:**
|
|
```json
|
|
{
|
|
"id": 9,
|
|
"uuid": "1b020b3a-3732-4c7e-92fd-a0cec90ed69b",
|
|
"category": 10,
|
|
"muscles": [1, 2],
|
|
"muscles_secondary": [3],
|
|
"equipment": [10],
|
|
"license": 2,
|
|
"license_author": "wger.de"
|
|
}
|
|
```
|
|
|
|
**API Endpoints:**
|
|
```
|
|
GET /api/v2/exercise/ - Lista övningar
|
|
GET /api/v2/muscle/ - Lista muskler
|
|
GET /api/v2/equipment/ - Lista utrustning
|
|
GET /api/v2/exerciseimage/ - Övningsbilder
|
|
GET /api/v2/exercisevideo/ - Övningsvideor
|
|
```
|
|
|
|
**Self-hosting:**
|
|
```bash
|
|
git clone https://github.com/wger-project/wger
|
|
cd wger
|
|
docker compose up -d
|
|
```
|
|
|
|
---
|
|
|
|
### 3. free-exercise-db (Public Domain)
|
|
|
|
**URL:** https://github.com/yuhonas/free-exercise-db
|
|
|
|
**Styrkor:**
|
|
- 800+ övningar
|
|
- Public Domain (Unlicense) — inga restriktioner
|
|
- Ren JSON-data
|
|
- Bilder inkluderade
|
|
- Sökbar frontend: https://yuhonas.github.io/free-exercise-db/
|
|
|
|
**Data format:**
|
|
```json
|
|
{
|
|
"name": "Barbell Bench Press",
|
|
"force": "push",
|
|
"level": "intermediate",
|
|
"mechanic": "compound",
|
|
"equipment": "barbell",
|
|
"primaryMuscles": ["chest"],
|
|
"secondaryMuscles": ["shoulders", "triceps"],
|
|
"instructions": ["..."],
|
|
"category": "strength",
|
|
"images": ["Barbell-Bench-Press/0.jpg", "Barbell-Bench-Press/1.jpg"]
|
|
}
|
|
```
|
|
|
|
**GitHub stats:** 1,100+ stars, aktivt community
|
|
|
|
---
|
|
|
|
### 4. MusclesWorked API
|
|
|
|
**URL:** https://musclesworked.com
|
|
|
|
**Styrkor:**
|
|
- 856 övningar, 63 muskler, 7,310+ mappings
|
|
- REST API + MCP server (för AI-agenter)
|
|
- Detaljerad muskel-mapping
|
|
|
|
**Begränsningar:**
|
|
- Kommersiell (API key krävs)
|
|
- Ingen media (bilder/video)
|
|
|
|
**Endpoints:**
|
|
```
|
|
GET /api/v1/exercises
|
|
GET /api/v1/muscles
|
|
GET /api/v1/exercise/{id}/muscles
|
|
```
|
|
|
|
---
|
|
|
|
### 5. API Ninjas Exercises
|
|
|
|
**URL:** https://api-ninjas.com/api/exercises
|
|
|
|
**Styrkor:**
|
|
- 3,000+ övningar
|
|
- Enkel att använda
|
|
- Filter på namn, typ, muskel, svårighetsgrad
|
|
|
|
**Begränsningar:**
|
|
- Freemium (gratis tier har limits)
|
|
- Ingen media
|
|
|
|
**Endpoint:**
|
|
```
|
|
GET https://api.api-ninjas.com/v1/exercises?muscle=biceps&difficulty=beginner
|
|
```
|
|
|
|
---
|
|
|
|
## Exercise Substitution (Alternativa övningar)
|
|
|
|
### Problemet
|
|
|
|
> "The bench is taken, what do I do instead?"
|
|
|
|
Användare vill kunna byta övning till en som tränar samma muskelgrupp.
|
|
|
|
### Lösningar
|
|
|
|
#### 1. Muskelgrupp-baserad substitution
|
|
|
|
```python
|
|
def get_alternatives(exercise_id):
|
|
exercise = get_exercise(exercise_id)
|
|
target_muscle = exercise.target
|
|
|
|
alternatives = db.query("""
|
|
SELECT * FROM exercises
|
|
WHERE target = %s
|
|
AND id != %s
|
|
ORDER BY popularity DESC
|
|
LIMIT 5
|
|
""", [target_muscle, exercise_id])
|
|
|
|
return alternatives
|
|
```
|
|
|
|
#### 2. Utrustnings-baserad substitution
|
|
|
|
```python
|
|
def get_alternatives_for_equipment(exercise_id, available_equipment):
|
|
exercise = get_exercise(exercise_id)
|
|
target_muscle = exercise.target
|
|
|
|
alternatives = db.query("""
|
|
SELECT * FROM exercises
|
|
WHERE target = %s
|
|
AND equipment = ANY(%s)
|
|
AND id != %s
|
|
""", [target_muscle, available_equipment, exercise_id])
|
|
|
|
return alternatives
|
|
```
|
|
|
|
#### 3. Sweat App-approach
|
|
|
|
Sweat har built-in substitution:
|
|
- Samma muskelgrupp
|
|
- Liknande rörelse-pattern (push/pull/hinge)
|
|
- Utrustning användaren har
|
|
|
|
#### 4. Tonal's Movement Replacements
|
|
|
|
280+ movement substitutes kategoriserade efter:
|
|
- Target muscle
|
|
- Movement pattern
|
|
- Equipment required
|
|
- Difficulty level
|
|
|
|
### Substitution-data
|
|
|
|
**Fitness Volt Substitute Finder:**
|
|
https://fitnessvolt.com/substitute-exercises/
|
|
|
|
Manuellt kurerad lista av alternativ för varje övning.
|
|
|
|
---
|
|
|
|
## Video/GIF Sources
|
|
|
|
### Gratis/Open Source
|
|
|
|
| Källa | Format | Kvalitet | Licens |
|
|
|-------|--------|----------|--------|
|
|
| ExerciseDB | GIF | Bra | Open |
|
|
| wger | Video/Bild | Varierar | AGPL |
|
|
| free-exercise-db | Bild | Bra | Public Domain |
|
|
|
|
### Kommersiella
|
|
|
|
| Källa | Format | Övningar | Pris |
|
|
|-------|--------|----------|------|
|
|
| Gym Visual | GIF/Video | 1000+ | $$ |
|
|
| Central Athlete | Video | 2,800+ | $$$ |
|
|
| Exercise.com | Video | Omfattande | $$$ |
|
|
| JEFIT | GIF | 1,400+ | I appen |
|
|
|
|
### Skapa egna
|
|
|
|
**GIPHY:** Sök "exercise" för community-uploads (osäker licens)
|
|
|
|
**AI-genererade:** Modeller som kan generera exercise-demos utvecklas, men kvaliteten är ännu inte där.
|
|
|
|
---
|
|
|
|
## Datastruktur för Gravl
|
|
|
|
### Rekommenderad schema
|
|
|
|
```sql
|
|
CREATE TABLE exercises (
|
|
id SERIAL PRIMARY KEY,
|
|
external_id VARCHAR(50), -- ID från extern källa
|
|
source VARCHAR(50), -- 'exercisedb', 'wger', 'custom'
|
|
|
|
-- Basic info
|
|
name VARCHAR(255) NOT NULL,
|
|
name_sv VARCHAR(255), -- Svenskt namn
|
|
description TEXT,
|
|
instructions TEXT[],
|
|
|
|
-- Categorization
|
|
body_part VARCHAR(50), -- 'chest', 'back', etc.
|
|
target_muscle VARCHAR(50), -- Primary muscle
|
|
secondary_muscles VARCHAR(50)[], -- Secondary muscles
|
|
equipment VARCHAR(50),
|
|
|
|
-- Metadata
|
|
difficulty VARCHAR(20), -- 'beginner', 'intermediate', 'advanced'
|
|
force_type VARCHAR(20), -- 'push', 'pull', 'static'
|
|
mechanic VARCHAR(20), -- 'compound', 'isolation'
|
|
|
|
-- Media
|
|
gif_url VARCHAR(500),
|
|
image_urls TEXT[],
|
|
video_url VARCHAR(500),
|
|
|
|
-- Gravl-specific
|
|
is_active BOOLEAN DEFAULT true,
|
|
popularity_score INT DEFAULT 0,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
CREATE TABLE exercise_alternatives (
|
|
exercise_id INT REFERENCES exercises(id),
|
|
alternative_id INT REFERENCES exercises(id),
|
|
similarity_score DECIMAL(3,2), -- 0.0 - 1.0
|
|
reason VARCHAR(100), -- 'same_muscle', 'same_equipment', etc.
|
|
PRIMARY KEY (exercise_id, alternative_id)
|
|
);
|
|
|
|
-- Index för snabb lookup
|
|
CREATE INDEX idx_exercises_target ON exercises(target_muscle);
|
|
CREATE INDEX idx_exercises_equipment ON exercises(equipment);
|
|
CREATE INDEX idx_exercises_body_part ON exercises(body_part);
|
|
```
|
|
|
|
### Import-script
|
|
|
|
```python
|
|
import requests
|
|
import json
|
|
|
|
def import_exercisedb():
|
|
"""Import exercises from ExerciseDB API"""
|
|
|
|
response = requests.get("https://exercisedb.p.rapidapi.com/exercises",
|
|
headers={"X-RapidAPI-Key": API_KEY})
|
|
|
|
exercises = response.json()
|
|
|
|
for ex in exercises:
|
|
db.execute("""
|
|
INSERT INTO exercises (
|
|
external_id, source, name, body_part,
|
|
target_muscle, equipment, gif_url, instructions
|
|
) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
|
|
ON CONFLICT (external_id, source) DO UPDATE
|
|
SET gif_url = EXCLUDED.gif_url,
|
|
updated_at = NOW()
|
|
""", [
|
|
ex['id'], 'exercisedb', ex['name'], ex['bodyPart'],
|
|
ex['target'], ex['equipment'], ex['gifUrl'],
|
|
ex.get('instructions', [])
|
|
])
|
|
```
|
|
|
|
---
|
|
|
|
## Rekommendationer för Gravl
|
|
|
|
### Phase 1: MVP
|
|
|
|
1. **Använd ExerciseDB** som primär källa
|
|
- 1,300+ övningar med GIF
|
|
- Gratis, open source
|
|
- Bra API
|
|
|
|
2. **Importera till lokal databas**
|
|
- Cache för performance
|
|
- Möjlighet att lägga till custom övningar
|
|
- Offline-stöd
|
|
|
|
3. **Basic substitution**
|
|
- Samma target muscle = alternativ
|
|
- Visa 3-5 alternativ per övning
|
|
|
|
### Phase 2: Enhanced
|
|
|
|
1. **Lägg till svenska namn**
|
|
- Manuellt eller via översättning
|
|
- Community contributions
|
|
|
|
2. **Smarter substitution**
|
|
- Equipment-aware
|
|
- Difficulty-matching
|
|
- Movement pattern-matching
|
|
|
|
3. **Custom exercises**
|
|
- Användare kan lägga till egna
|
|
- Upload egen GIF/video
|
|
|
|
### Phase 3: Advanced
|
|
|
|
1. **AI-driven substitution**
|
|
- "Axeln gör ont" → undvik overhead press
|
|
- "Bänken upptagen" → DB press istället
|
|
|
|
2. **Video tutorials**
|
|
- Licens commercial content
|
|
- Eller skapa egna
|
|
|
|
3. **Form analysis**
|
|
- Pose estimation
|
|
- Jämför mot ideal form
|
|
|
|
---
|
|
|
|
## Licens-sammanfattning
|
|
|
|
| Källa | Kan använda kommersiellt | Attribution krävs |
|
|
|-------|-------------------------|-------------------|
|
|
| ExerciseDB (open) | ✅ | Rekommenderas |
|
|
| wger | ✅ (AGPL) | Ja, och dela ändringar |
|
|
| free-exercise-db | ✅ (Unlicense) | Nej |
|
|
| API Ninjas | ⚠️ Check terms | Ja |
|
|
| MusclesWorked | 💰 Betala | Enligt avtal |
|
|
|
|
**Säkraste valet:** free-exercise-db (Public Domain) + ExerciseDB (Open Source)
|
|
|
|
---
|
|
|
|
*Källa: GitHub, ExerciseDB, wger, Reddit, Exa AI Search — 2023-2026*
|