Save speaking asynchronously
This commit is contained in:
82
app.py
82
app.py
@@ -1,14 +1,13 @@
|
|||||||
import random
|
import threading
|
||||||
|
|
||||||
from flask import Flask, request
|
from flask import Flask, request
|
||||||
from flask_jwt_extended import JWTManager, jwt_required
|
from flask_jwt_extended import JWTManager, jwt_required
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
from helper.api_messages import *
|
from helper.api_messages import *
|
||||||
from helper.constants import *
|
|
||||||
from helper.exercises import *
|
from helper.exercises import *
|
||||||
from helper.file_helper import delete_files_older_than_one_day
|
from helper.file_helper import delete_files_older_than_one_day
|
||||||
from helper.firebase_helper import *
|
from helper.firebase_helper import *
|
||||||
from helper.heygen_api import create_video
|
from helper.heygen_api import create_videos_and_save_to_db
|
||||||
from helper.speech_to_text_helper import *
|
from helper.speech_to_text_helper import *
|
||||||
from helper.token_counter import count_tokens
|
from helper.token_counter import count_tokens
|
||||||
from helper.openai_interface import make_openai_call, make_openai_instruct_call
|
from helper.openai_interface import make_openai_call, make_openai_instruct_call
|
||||||
@@ -31,6 +30,8 @@ jwt = JWTManager(app)
|
|||||||
cred = credentials.Certificate(os.getenv("GOOGLE_APPLICATION_CREDENTIALS"))
|
cred = credentials.Certificate(os.getenv("GOOGLE_APPLICATION_CREDENTIALS"))
|
||||||
firebase_admin.initialize_app(cred)
|
firebase_admin.initialize_app(cred)
|
||||||
|
|
||||||
|
thread_event = threading.Event()
|
||||||
|
|
||||||
|
|
||||||
@app.route('/healthcheck', methods=['GET'])
|
@app.route('/healthcheck', methods=['GET'])
|
||||||
def healthcheck():
|
def healthcheck():
|
||||||
@@ -158,6 +159,7 @@ def save_listening():
|
|||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
parts = data.get('parts')
|
parts = data.get('parts')
|
||||||
template = getListeningTemplate()
|
template = getListeningTemplate()
|
||||||
|
id = str(uuid.uuid4())
|
||||||
for i, part in enumerate(parts, start=0):
|
for i, part in enumerate(parts, start=0):
|
||||||
file_name = str(uuid.uuid4()) + ".mp3"
|
file_name = str(uuid.uuid4()) + ".mp3"
|
||||||
sound_file_path = AUDIO_FILES_PATH + file_name
|
sound_file_path = AUDIO_FILES_PATH + file_name
|
||||||
@@ -170,7 +172,7 @@ def save_listening():
|
|||||||
template["parts"][i]["audio"]["source"] = file_url
|
template["parts"][i]["audio"]["source"] = file_url
|
||||||
template["parts"][i]["exercises"] = part["exercises"]
|
template["parts"][i]["exercises"] = part["exercises"]
|
||||||
|
|
||||||
(result, id) = save_to_db("listening", template)
|
(result, id) = save_to_db_with_id("listening", template, id)
|
||||||
if result:
|
if result:
|
||||||
return {**template, "id": id}
|
return {**template, "id": id}
|
||||||
else:
|
else:
|
||||||
@@ -292,10 +294,11 @@ def save_writing_task():
|
|||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
exercises = data.get('exercises')
|
exercises = data.get('exercises')
|
||||||
template = getWritingTemplate()
|
template = getWritingTemplate()
|
||||||
|
id = str(uuid.uuid4())
|
||||||
for i, exercise in enumerate(exercises, start=0):
|
for i, exercise in enumerate(exercises, start=0):
|
||||||
template["exercises"][i]["prompt"] = exercise
|
template["exercises"][i]["prompt"] = exercise
|
||||||
|
|
||||||
(result, id) = save_to_db("writing", template)
|
(result, id) = save_to_db_with_id("writing", template, id)
|
||||||
if result:
|
if result:
|
||||||
return {**template, "id": id}
|
return {**template, "id": id}
|
||||||
else:
|
else:
|
||||||
@@ -524,63 +527,18 @@ def save_speaking():
|
|||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
exercises = data.get('exercises')
|
exercises = data.get('exercises')
|
||||||
template = getSpeakingTemplate()
|
template = getSpeakingTemplate()
|
||||||
|
id = str(uuid.uuid4())
|
||||||
|
|
||||||
# Speaking 1
|
thread_event.set()
|
||||||
sp1_result = create_video(exercises[0]["question"], random.choice(list(AvatarEnum)))
|
thread = threading.Thread(
|
||||||
if sp1_result is not None:
|
target=create_videos_and_save_to_db,
|
||||||
sound_file_path = VIDEO_FILES_PATH + sp1_result
|
args=(exercises, template, id),
|
||||||
firebase_file_path = FIREBASE_SPEAKING_VIDEO_FILES_PATH + sp1_result
|
name=("thread-save-speaking-" + id)
|
||||||
url = upload_file_firebase_get_url(FIREBASE_BUCKET, firebase_file_path, sound_file_path)
|
)
|
||||||
sp1_video_path = firebase_file_path
|
thread.start()
|
||||||
sp1_video_url = url
|
|
||||||
template["exercises"][0]["text"] = exercises[0]["question"]
|
|
||||||
template["exercises"][0]["title"] = exercises[0]["topic"]
|
|
||||||
template["exercises"][0]["video_url"] = sp1_video_url
|
|
||||||
template["exercises"][0]["video_path"] = sp1_video_path
|
|
||||||
else:
|
|
||||||
print("Failed to create video for part 1 question: " + exercises[0]["question"])
|
|
||||||
|
|
||||||
# Speaking 2
|
# Return response without waiting for create_videos_and_save_to_db to finish
|
||||||
sp2_result = create_video(exercises[1]["question"], random.choice(list(AvatarEnum)))
|
return {**template, "id": id}
|
||||||
if sp2_result is not None:
|
|
||||||
sound_file_path = VIDEO_FILES_PATH + sp2_result
|
|
||||||
firebase_file_path = FIREBASE_SPEAKING_VIDEO_FILES_PATH + sp2_result
|
|
||||||
url = upload_file_firebase_get_url(FIREBASE_BUCKET, firebase_file_path, sound_file_path)
|
|
||||||
sp2_video_path = firebase_file_path
|
|
||||||
sp2_video_url = url
|
|
||||||
template["exercises"][1]["prompts"] = exercises[1]["prompts"]
|
|
||||||
template["exercises"][1]["text"] = exercises[1]["question"]
|
|
||||||
template["exercises"][1]["title"] = exercises[1]["topic"]
|
|
||||||
template["exercises"][1]["video_url"] = sp2_video_url
|
|
||||||
template["exercises"][1]["video_path"] = sp2_video_path
|
|
||||||
else:
|
|
||||||
print("Failed to create video for part 2 question: " + exercises[1]["question"])
|
|
||||||
|
|
||||||
# Speaking 3
|
|
||||||
sp3_questions = []
|
|
||||||
avatar = random.choice(list(AvatarEnum))
|
|
||||||
for question in exercises[2]["questions"]:
|
|
||||||
result = create_video(question, avatar)
|
|
||||||
if result is not None:
|
|
||||||
sound_file_path = VIDEO_FILES_PATH + result
|
|
||||||
firebase_file_path = FIREBASE_SPEAKING_VIDEO_FILES_PATH + result
|
|
||||||
url = upload_file_firebase_get_url(FIREBASE_BUCKET, firebase_file_path, sound_file_path)
|
|
||||||
video = {
|
|
||||||
"text": question,
|
|
||||||
"video_path": firebase_file_path,
|
|
||||||
"video_url": url
|
|
||||||
}
|
|
||||||
sp3_questions.append(video)
|
|
||||||
else:
|
|
||||||
print("Failed to create video for part 3 question: " + question)
|
|
||||||
template["exercises"][2]["prompts"] = sp3_questions
|
|
||||||
template["exercises"][2]["title"] = exercises[2]["topic"]
|
|
||||||
|
|
||||||
(result, id) = save_to_db("speaking", template)
|
|
||||||
if result:
|
|
||||||
return {**template, "id": id}
|
|
||||||
else:
|
|
||||||
raise Exception("Failed to save speaking: " + template)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return str(e)
|
return str(e)
|
||||||
|
|
||||||
@@ -677,8 +635,8 @@ def save_reading_passage():
|
|||||||
parts = data.get('parts')
|
parts = data.get('parts')
|
||||||
template = getReadingTemplate()
|
template = getReadingTemplate()
|
||||||
template["parts"] = parts
|
template["parts"] = parts
|
||||||
|
id = str(uuid.uuid4())
|
||||||
(result, id) = save_to_db("reading", template)
|
(result, id) = save_to_db_with_id("reading", template, id)
|
||||||
if result:
|
if result:
|
||||||
return {**template, "id": id}
|
return {**template, "id": id}
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -59,4 +59,18 @@ def save_to_db(collection: str, item):
|
|||||||
return (False, None)
|
return (False, None)
|
||||||
|
|
||||||
|
|
||||||
|
def save_to_db_with_id(collection: str, item, id: str):
|
||||||
|
db = firestore.client()
|
||||||
|
collection_ref = db.collection(collection)
|
||||||
|
# Reference to the specific document with the desired ID
|
||||||
|
document_ref = collection_ref.document(id)
|
||||||
|
# Set the data to the document
|
||||||
|
document_ref.set(item)
|
||||||
|
if document_ref:
|
||||||
|
print(f"Document added with ID: {document_ref.id}")
|
||||||
|
return (True, document_ref.id)
|
||||||
|
else:
|
||||||
|
return (False, None)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
import os
|
import os
|
||||||
|
import random
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
from helper.constants import *
|
||||||
|
from helper.firebase_helper import upload_file_firebase_get_url, save_to_db_with_id
|
||||||
from heygen.AvatarEnum import AvatarEnum
|
from heygen.AvatarEnum import AvatarEnum
|
||||||
|
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
@@ -30,6 +33,59 @@ KAYLA_ABBI = "d688099f8db9472cb4890b0561e81793"
|
|||||||
JEROME_RYAN = "ad41feb2a5c4483085525e3d8907f512"
|
JEROME_RYAN = "ad41feb2a5c4483085525e3d8907f512"
|
||||||
TYLER_CHRISTOPHER = "03c796f8ed274bb38f19e893bcbc6121"
|
TYLER_CHRISTOPHER = "03c796f8ed274bb38f19e893bcbc6121"
|
||||||
|
|
||||||
|
def create_videos_and_save_to_db(exercises, template, id):
|
||||||
|
# Speaking 1
|
||||||
|
sp1_result = create_video(exercises[0]["question"], random.choice(list(AvatarEnum)))
|
||||||
|
if sp1_result is not None:
|
||||||
|
sound_file_path = VIDEO_FILES_PATH + sp1_result
|
||||||
|
firebase_file_path = FIREBASE_SPEAKING_VIDEO_FILES_PATH + sp1_result
|
||||||
|
url = upload_file_firebase_get_url(FIREBASE_BUCKET, firebase_file_path, sound_file_path)
|
||||||
|
sp1_video_path = firebase_file_path
|
||||||
|
sp1_video_url = url
|
||||||
|
template["exercises"][0]["text"] = exercises[0]["question"]
|
||||||
|
template["exercises"][0]["title"] = exercises[0]["topic"]
|
||||||
|
template["exercises"][0]["video_url"] = sp1_video_url
|
||||||
|
template["exercises"][0]["video_path"] = sp1_video_path
|
||||||
|
else:
|
||||||
|
print("Failed to create video for part 1 question: " + exercises[0]["question"])
|
||||||
|
|
||||||
|
# Speaking 2
|
||||||
|
sp2_result = create_video(exercises[1]["question"], random.choice(list(AvatarEnum)))
|
||||||
|
if sp2_result is not None:
|
||||||
|
sound_file_path = VIDEO_FILES_PATH + sp2_result
|
||||||
|
firebase_file_path = FIREBASE_SPEAKING_VIDEO_FILES_PATH + sp2_result
|
||||||
|
url = upload_file_firebase_get_url(FIREBASE_BUCKET, firebase_file_path, sound_file_path)
|
||||||
|
sp2_video_path = firebase_file_path
|
||||||
|
sp2_video_url = url
|
||||||
|
template["exercises"][1]["prompts"] = exercises[1]["prompts"]
|
||||||
|
template["exercises"][1]["text"] = exercises[1]["question"]
|
||||||
|
template["exercises"][1]["title"] = exercises[1]["topic"]
|
||||||
|
template["exercises"][1]["video_url"] = sp2_video_url
|
||||||
|
template["exercises"][1]["video_path"] = sp2_video_path
|
||||||
|
else:
|
||||||
|
print("Failed to create video for part 2 question: " + exercises[1]["question"])
|
||||||
|
|
||||||
|
# Speaking 3
|
||||||
|
sp3_questions = []
|
||||||
|
avatar = random.choice(list(AvatarEnum))
|
||||||
|
for question in exercises[2]["questions"]:
|
||||||
|
result = create_video(question, avatar)
|
||||||
|
if result is not None:
|
||||||
|
sound_file_path = VIDEO_FILES_PATH + result
|
||||||
|
firebase_file_path = FIREBASE_SPEAKING_VIDEO_FILES_PATH + result
|
||||||
|
url = upload_file_firebase_get_url(FIREBASE_BUCKET, firebase_file_path, sound_file_path)
|
||||||
|
video = {
|
||||||
|
"text": question,
|
||||||
|
"video_path": firebase_file_path,
|
||||||
|
"video_url": url
|
||||||
|
}
|
||||||
|
sp3_questions.append(video)
|
||||||
|
else:
|
||||||
|
print("Failed to create video for part 3 question: " + question)
|
||||||
|
template["exercises"][2]["prompts"] = sp3_questions
|
||||||
|
template["exercises"][2]["title"] = exercises[2]["topic"]
|
||||||
|
|
||||||
|
save_to_db_with_id("speaking", template, id)
|
||||||
|
|
||||||
def create_video(text, avatar: AvatarEnum):
|
def create_video(text, avatar: AvatarEnum):
|
||||||
# POST TO CREATE VIDEO
|
# POST TO CREATE VIDEO
|
||||||
|
|||||||
Reference in New Issue
Block a user