Initial commit. Creates valid json for database. Properlly laods yaml input. Properly downloads video and creates short clips
This commit is contained in:
commit
9235669ba5
91
create_open_workout_database.py
Normal file
91
create_open_workout_database.py
Normal file
@ -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
Normal file
108
data/databaseSchema.json
Normal file
@ -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
Normal file
25
data/input/samples/exercises.yaml
Normal file
@ -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
Normal file
43
load_exercises.py
Normal file
@ -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
Normal file
17
readme.md
Normal file
@ -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
Normal file
4
requirements.txt
Normal file
@ -0,0 +1,4 @@
|
||||
pyyaml
|
||||
pytube
|
||||
moviepy
|
||||
imageio
|
Loading…
x
Reference in New Issue
Block a user