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

This commit is contained in:
gabriel becker 2023-08-24 23:34:57 +10:00
commit 9235669ba5
6 changed files with 288 additions and 0 deletions

View 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
View 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"
}
}
}
}
}
}

View 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
View 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
View 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
View File

@ -0,0 +1,4 @@
pyyaml
pytube
moviepy
imageio