Browse Source

Initial commit. Creates valid json for database. Properlly laods yaml input. Properly downloads video and creates short clips

main
gabriel becker 1 year ago
commit
9235669ba5
  1. 91
      create_open_workout_database.py
  2. 108
      data/databaseSchema.json
  3. 25
      data/input/samples/exercises.yaml
  4. 43
      load_exercises.py
  5. 17
      readme.md
  6. 4
      requirements.txt

91
create_open_workout_database.py

@ -0,0 +1,91 @@
import json
WORKOUT_DATABASE = {
"countFinishedTraining": 0,
"imagePath": "defaultTraining.png",
"isImagePathExternal": False,
"name": "lol2",
"orderNr": -1,
"trainingPlanId": 0,
"workoutSessions": []
}
def create_work_database(name, workout_sessions):
new_db = dict(WORKOUT_DATABASE)
new_content = {
"name": name,
"workoutSessions": workout_sessions
}
new_db.update(new_content)
return new_db
WORKOUT_SESSION = {
"finished": False,
"name": "1. day",
"orderNr": -1,
"trainingPlanId": 13,
"workoutItems": [],
"workoutSessionId": 0
}
def create_work_session(workout_items: list):
new_session = dict(WORKOUT_SESSION)
new_session_content = {
"workoutItems": workout_items
}
new_session.update(new_session_content)
return new_session
WOPRKOUT_ITEM = {
"breakTime": 2,
"description": "Stand up with your legs spread and your hands touching overhead. Then as you jump, bring your legs back together and put your arms to your sides. You can speed these up or slow them down to suit your fitness level.",
"elapsedTime": 0,
"finished": False,
"imagePath": "jumping_jack.png",
"isImagePathExternal": False,
"isTimeMode": True,
"isVideoMode": True,
"isVideoPathExternal": False,
"name": "Jumping Jack",
"orderNr": -1,
"prepTime": 5,
"repetitionCount": 5,
"videoPath": "jumping_jack.mp4",
"workoutItemId": 0,
"workoutSessionId": 1,
"workoutTime": 30
}
def create_item():
new_item = dict(WOPRKOUT_ITEM)
new_item_content = {
"description": "Stand up with your legs spread and your hands touching overhead. Then as you jump, bring your legs back together and put your arms to your sides. You can speed these up or slow them down to suit your fitness level.",
"elapsedTime": 0,
"imagePath": "jumping_jack.png",
"isImagePathExternal": False,
"isTimeMode": True,
"isVideoMode": True,
"prepTime": 5,
"repetitionCount": 5,
"videoPath": "jumping_jack.mp4",
"workoutTime": 30
}
new_item.update(new_item_content)
return new_item
def lasdikfsh():
items = [create_item()]
sessions = [create_work_session(items)]
db = create_work_database('urdur', sessions)
with open("your_json_file.json", "w") as fp:
json.dump(db , fp)
if __name__ == '__main__':
lasdikfsh()

108
data/databaseSchema.json

@ -0,0 +1,108 @@
{
"type": "object",
"required": [],
"properties": {
"countFinishedTraining": {
"type": "string"
},
"imagePath": {
"type": "string"
},
"isImagePathExternal": {
"type": "string"
},
"name": {
"type": "string"
},
"orderNr": {
"type": "number"
},
"trainingPlanId": {
"type": "string"
},
"workoutSessions": {
"type": "array",
"items": {
"type": "object",
"required": [],
"properties": {
"finished": {
"type": "boolean"
},
"name": {
"type": "string"
},
"orderNr": {
"type": "string"
},
"trainingPlanId": {
"type": "number"
},
"workoutItems": {
"type": "array",
"items": {
"type": "object",
"required": [],
"properties": {
"breakTime": {
"type": "number"
},
"description": {
"type": "string"
},
"elapsedTime": {
"type": "number"
},
"finished": {
"type": "boolean"
},
"imagePath": {
"type": "string"
},
"isImagePathExternal": {
"type": "string"
},
"isTimeMode": {
"type": "boolean"
},
"isVideoMode": {
"type": "boolean"
},
"isVideoPathExternal": {
"type": "string"
},
"name": {
"type": "string"
},
"orderNr": {
"type": "string"
},
"prepTime": {
"type": "number"
},
"repetitionCount": {
"type": "number"
},
"videoPath": {
"type": "string"
},
"workoutItemId": {
"type": "string"
},
"workoutSessionId": {
"type": "number"
},
"workoutTime": {
"type": "number"
}
}
}
},
"workoutSessionId": {
"type": "string"
}
}
}
}
}
}

25
data/input/samples/exercises.yaml

@ -0,0 +1,25 @@
exercises:
- name: nomoney
video: "https://www.youtube.com/watch?v=etAwQ4jzyNY"
start: 74
end: 80
- name: plank shoulder tap
video: "https://www.youtube.com/watch?v=etAwQ4jzyNY"
start: 113
end: 116
- name: standing ws
video: "https://www.youtube.com/watch?v=etAwQ4jzyNY"
start: 243
end: 248
- name: side plank
video: "https://www.youtube.com/watch?v=etAwQ4jzyNY"
start: 277
end: 280
- name: face pulls
video: "https://www.youtube.com/watch?v=etAwQ4jzyNY"
start: 413
end: 417
- name: recruitment pulls
video: "https://www.youtube.com/watch?v=etAwQ4jzyNY"
start: 541
end: 548

43
load_exercises.py

@ -0,0 +1,43 @@
import yaml
import pytube
import tempfile
import imageio
from pathlib import Path
from functools import lru_cache
import moviepy.editor as mpy
FILE = 'data/input/samples/exercises.yaml'
@lru_cache(5)
def get_video(url):
output_dir = tempfile.mktemp()
video = pytube.YouTube(url)
video.streams.filter(res="360p").first().download(filename=output_dir)
return output_dir
def create_gif_from_video_and_timestamps(video_path, start, end):
video = mpy.VideoFileClip(video_path)
clip: mpy.VideoFileClip = video.subclip(start, end)
output_dir = tempfile.mktemp() + '.mp4'
clip.set_fps(2)
clip.without_audio().write_videofile(output_dir)
return output_dir
if __name__ == '__main__':
file = open(FILE)
exercises = yaml.safe_load(file)
for ex in exercises['exercises']:
name = ex['name']
video_url = ex['video']
start = ex['start']
end = ex['end']
video_path = get_video(video_url)
gif = create_gif_from_video_and_timestamps(video_path, start, end)
ex['gif_path'] = gif
print(gif)

17
readme.md

@ -0,0 +1,17 @@
# Cli-Coach
Creates a workout plan form an yaml file that can be imported to <img src="https://github.com/oliexdev/openWorkout/raw/master/fastlane/metadata/android/en-GB/images/icon.png" width="50"/> [openWorkout](https://github.com/oliexdev/openWorkout) android app.
Inputs can be of format
```yaml
exercises:
- name: nomoney
video: "https://www.youtube.com/watch?v=etAwQ4jzyNY"
start: 74
end: 80
- name: plank shoulder tap
video: "https://www.youtube.com/watch?v=etAwQ4jzyNY"
start: 113
end: 116
```
The script will download the video and create short clips.

4
requirements.txt

@ -0,0 +1,4 @@
pyyaml
pytube
moviepy
imageio
Loading…
Cancel
Save