commit 9235669ba5a5a583c93ba9ece8b3eb04f94ee189 Author: gabriel becker Date: Thu Aug 24 23:34:57 2023 +1000 Initial commit. Creates valid json for database. Properlly laods yaml input. Properly downloads video and creates short clips diff --git a/create_open_workout_database.py b/create_open_workout_database.py new file mode 100644 index 0000000..5c10f0a --- /dev/null +++ b/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() diff --git a/data/databaseSchema.json b/data/databaseSchema.json new file mode 100644 index 0000000..bd73ca1 --- /dev/null +++ b/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" + } + } + } + } + } + } \ No newline at end of file diff --git a/data/input/samples/exercises.yaml b/data/input/samples/exercises.yaml new file mode 100644 index 0000000..9c5ca2f --- /dev/null +++ b/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 diff --git a/load_exercises.py b/load_exercises.py new file mode 100644 index 0000000..450f08a --- /dev/null +++ b/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) diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..6a036b9 --- /dev/null +++ b/readme.md @@ -0,0 +1,17 @@ +# Cli-Coach +Creates a workout plan form an yaml file that can be imported to [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. \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..eeea973 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +pyyaml +pytube +moviepy +imageio \ No newline at end of file