Merged in save-questions (pull request #5)
Add save endpoints but dont't actually save.
This commit is contained in:
370
app.py
370
app.py
@@ -17,6 +17,7 @@ import re
|
|||||||
|
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
from heygen.AvatarEnum import AvatarEnum
|
||||||
from templates.question_templates import *
|
from templates.question_templates import *
|
||||||
|
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
@@ -30,6 +31,7 @@ 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)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/healthcheck', methods=['GET'])
|
@app.route('/healthcheck', methods=['GET'])
|
||||||
def healthcheck():
|
def healthcheck():
|
||||||
return {"healthy": True}
|
return {"healthy": True}
|
||||||
@@ -54,7 +56,8 @@ def get_listening_section_1_question():
|
|||||||
print("Generated conversation: " + str(processed_conversation))
|
print("Generated conversation: " + str(processed_conversation))
|
||||||
|
|
||||||
start_id = 1
|
start_id = 1
|
||||||
exercises = generate_listening_conversation_exercises(unprocessed_conversation, req_exercises, number_of_exercises_q,
|
exercises = generate_listening_conversation_exercises(unprocessed_conversation, req_exercises,
|
||||||
|
number_of_exercises_q,
|
||||||
start_id)
|
start_id)
|
||||||
return {
|
return {
|
||||||
"exercises": exercises,
|
"exercises": exercises,
|
||||||
@@ -64,28 +67,6 @@ def get_listening_section_1_question():
|
|||||||
return str(e)
|
return str(e)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/save_listening_section_1', methods=['POST'])
|
|
||||||
@jwt_required()
|
|
||||||
def save_listening_section_1_question():
|
|
||||||
try:
|
|
||||||
# data = request.get_json()
|
|
||||||
# question = data.get('question')
|
|
||||||
question = getListening1Template()
|
|
||||||
file_name = str(uuid.uuid4()) + ".mp3"
|
|
||||||
sound_file_path = AUDIO_FILES_PATH + file_name
|
|
||||||
firebase_file_path = FIREBASE_LISTENING_AUDIO_FILES_PATH + file_name
|
|
||||||
# TODO it's the conversation audio, still work to do on text-to-speech
|
|
||||||
text_to_speech(question["audio"]["conversation"], sound_file_path)
|
|
||||||
file_url = upload_file_firebase_get_url(FIREBASE_BUCKET, firebase_file_path, sound_file_path)
|
|
||||||
question["audio"]["source"] = file_url
|
|
||||||
if save_to_db("listening", question):
|
|
||||||
return question
|
|
||||||
else:
|
|
||||||
raise Exception("Failed to save question: " + question)
|
|
||||||
except Exception as e:
|
|
||||||
return str(e)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/listening_section_2', methods=['GET'])
|
@app.route('/listening_section_2', methods=['GET'])
|
||||||
@jwt_required()
|
@jwt_required()
|
||||||
def get_listening_section_2_question():
|
def get_listening_section_2_question():
|
||||||
@@ -113,27 +94,6 @@ def get_listening_section_2_question():
|
|||||||
return str(e)
|
return str(e)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/save_listening_section_2', methods=['POST'])
|
|
||||||
@jwt_required()
|
|
||||||
def save_listening_section_2_question():
|
|
||||||
try:
|
|
||||||
# data = request.get_json()
|
|
||||||
# question = data.get('question')
|
|
||||||
question = getListening2Template()
|
|
||||||
file_name = str(uuid.uuid4()) + ".mp3"
|
|
||||||
sound_file_path = AUDIO_FILES_PATH + file_name
|
|
||||||
firebase_file_path = FIREBASE_LISTENING_AUDIO_FILES_PATH + file_name
|
|
||||||
text_to_speech(question["audio"]["text"], sound_file_path)
|
|
||||||
file_url = upload_file_firebase_get_url(FIREBASE_BUCKET, firebase_file_path, sound_file_path)
|
|
||||||
question["audio"]["source"] = file_url
|
|
||||||
if save_to_db("listening", question):
|
|
||||||
return question
|
|
||||||
else:
|
|
||||||
raise Exception("Failed to save question: " + question)
|
|
||||||
except Exception as e:
|
|
||||||
return str(e)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/listening_section_3', methods=['GET'])
|
@app.route('/listening_section_3', methods=['GET'])
|
||||||
@jwt_required()
|
@jwt_required()
|
||||||
def get_listening_section_3_question():
|
def get_listening_section_3_question():
|
||||||
@@ -153,7 +113,8 @@ def get_listening_section_3_question():
|
|||||||
print("Generated conversation: " + str(processed_conversation))
|
print("Generated conversation: " + str(processed_conversation))
|
||||||
|
|
||||||
start_id = 21
|
start_id = 21
|
||||||
exercises = generate_listening_conversation_exercises(unprocessed_conversation, req_exercises, number_of_exercises_q,
|
exercises = generate_listening_conversation_exercises(unprocessed_conversation, req_exercises,
|
||||||
|
number_of_exercises_q,
|
||||||
start_id)
|
start_id)
|
||||||
return {
|
return {
|
||||||
"exercises": exercises,
|
"exercises": exercises,
|
||||||
@@ -163,27 +124,6 @@ def get_listening_section_3_question():
|
|||||||
return str(e)
|
return str(e)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/save_listening_section_3', methods=['POST'])
|
|
||||||
@jwt_required()
|
|
||||||
def save_listening_section_3_question():
|
|
||||||
try:
|
|
||||||
# data = request.get_json()
|
|
||||||
# question = data.get('question')
|
|
||||||
question = getListening2Template()
|
|
||||||
file_name = str(uuid.uuid4()) + ".mp3"
|
|
||||||
sound_file_path = AUDIO_FILES_PATH + file_name
|
|
||||||
firebase_file_path = FIREBASE_LISTENING_AUDIO_FILES_PATH + file_name
|
|
||||||
text_to_speech(question["audio"]["text"], sound_file_path)
|
|
||||||
file_url = upload_file_firebase_get_url(FIREBASE_BUCKET, firebase_file_path, sound_file_path)
|
|
||||||
question["audio"]["source"] = file_url
|
|
||||||
if save_to_db("listening", question):
|
|
||||||
return question
|
|
||||||
else:
|
|
||||||
raise Exception("Failed to save question: " + question)
|
|
||||||
except Exception as e:
|
|
||||||
return str(e)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/listening_section_4', methods=['GET'])
|
@app.route('/listening_section_4', methods=['GET'])
|
||||||
@jwt_required()
|
@jwt_required()
|
||||||
def get_listening_section_4_question():
|
def get_listening_section_4_question():
|
||||||
@@ -211,23 +151,30 @@ def get_listening_section_4_question():
|
|||||||
return str(e)
|
return str(e)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/save_listening_section_4', methods=['POST'])
|
@app.route('/listening', methods=['POST'])
|
||||||
@jwt_required()
|
@jwt_required()
|
||||||
def save_listening_section_4_question():
|
def save_listening():
|
||||||
try:
|
try:
|
||||||
# data = request.get_json()
|
data = request.get_json()
|
||||||
# question = data.get('question')
|
parts = data.get('parts')
|
||||||
question = getListening2Template()
|
template = getListeningTemplate()
|
||||||
file_name = str(uuid.uuid4()) + ".mp3"
|
for i, part in enumerate(parts, start=0):
|
||||||
sound_file_path = AUDIO_FILES_PATH + file_name
|
file_name = str(uuid.uuid4()) + ".mp3"
|
||||||
firebase_file_path = FIREBASE_LISTENING_AUDIO_FILES_PATH + file_name
|
sound_file_path = AUDIO_FILES_PATH + file_name
|
||||||
text_to_speech(question["audio"]["text"], sound_file_path)
|
firebase_file_path = FIREBASE_LISTENING_AUDIO_FILES_PATH + file_name
|
||||||
file_url = upload_file_firebase_get_url(FIREBASE_BUCKET, firebase_file_path, sound_file_path)
|
if "conversation" in part["text"]:
|
||||||
question["audio"]["source"] = file_url
|
conversation_text_to_speech(part["text"]["conversation"], sound_file_path)
|
||||||
if save_to_db("listening", question):
|
else:
|
||||||
return question
|
text_to_speech(part["text"], sound_file_path)
|
||||||
else:
|
# file_url = upload_file_firebase_get_url(FIREBASE_BUCKET, firebase_file_path, sound_file_path)
|
||||||
raise Exception("Failed to save question: " + question)
|
file_url = "test_url/" + firebase_file_path
|
||||||
|
template["parts"][i]["audio"]["source"] = file_url
|
||||||
|
template["parts"][i]["exercises"].append(part["exercises"])
|
||||||
|
# if save_to_db("listening", template):
|
||||||
|
# return template
|
||||||
|
# else:
|
||||||
|
# raise Exception("Failed to save question: " + parts)
|
||||||
|
return template
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return str(e)
|
return str(e)
|
||||||
|
|
||||||
@@ -278,22 +225,6 @@ def get_writing_task_1_general_question():
|
|||||||
return str(e)
|
return str(e)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/save_writing_task_1', methods=['POST'])
|
|
||||||
@jwt_required()
|
|
||||||
def save_writing_task_1_question():
|
|
||||||
try:
|
|
||||||
# data = request.get_json()
|
|
||||||
# question = data.get('question')
|
|
||||||
# TODO ADD SAVE IMAGE TO DB
|
|
||||||
question = getListening2Template()
|
|
||||||
if save_to_db("writing", question):
|
|
||||||
return question
|
|
||||||
else:
|
|
||||||
raise Exception("Failed to save question: " + question)
|
|
||||||
except Exception as e:
|
|
||||||
return str(e)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/writing_task2', methods=['POST'])
|
@app.route('/writing_task2', methods=['POST'])
|
||||||
@jwt_required()
|
@jwt_required()
|
||||||
def grade_writing_task_2():
|
def grade_writing_task_2():
|
||||||
@@ -341,17 +272,20 @@ def get_writing_task_2_general_question():
|
|||||||
return str(e)
|
return str(e)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/save_writing_task_2', methods=['POST'])
|
@app.route('/writing', methods=['POST'])
|
||||||
@jwt_required()
|
@jwt_required()
|
||||||
def save_writing_task_2_question():
|
def save_writing_task():
|
||||||
try:
|
try:
|
||||||
# data = request.get_json()
|
data = request.get_json()
|
||||||
# question = data.get('question')
|
exercises = data.get('exercises')
|
||||||
question = getListening2Template()
|
template = getWritingTemplate()
|
||||||
if save_to_db("writing", question):
|
for i, exercise in enumerate(exercises, start=0):
|
||||||
return question
|
template["exercises"][i]["prompt"] = exercise
|
||||||
else:
|
# if save_to_db("writing", template):
|
||||||
raise Exception("Failed to save question: " + question)
|
# return template
|
||||||
|
# else:
|
||||||
|
# raise Exception("Failed to save writing: " + template)
|
||||||
|
return template
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return str(e)
|
return str(e)
|
||||||
|
|
||||||
@@ -408,54 +342,6 @@ def get_speaking_task_1_question():
|
|||||||
return str(e)
|
return str(e)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/save_speaking_task_1', methods=['POST'])
|
|
||||||
@jwt_required()
|
|
||||||
def save_speaking_task_1_question():
|
|
||||||
try:
|
|
||||||
# data = request.get_json()
|
|
||||||
# question = data.get('question')
|
|
||||||
questions_json = getSpeaking1Template()
|
|
||||||
questions = []
|
|
||||||
for question in questions_json["questions"]:
|
|
||||||
result = create_video(question)
|
|
||||||
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
|
|
||||||
}
|
|
||||||
questions.append(video)
|
|
||||||
else:
|
|
||||||
print("Failed to create video for question: " + question)
|
|
||||||
|
|
||||||
if len(questions) == len(questions_json["questions"]):
|
|
||||||
speaking_pt1_to_insert = {
|
|
||||||
"exercises": [
|
|
||||||
{
|
|
||||||
"id": str(uuid.uuid4()),
|
|
||||||
"prompts": questions,
|
|
||||||
"text": "Listen carefully and respond.",
|
|
||||||
"title": questions_json["topic"],
|
|
||||||
"type": "speakingPart1"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"isDiagnostic": True,
|
|
||||||
"minTimer": 5,
|
|
||||||
"module": "speaking"
|
|
||||||
}
|
|
||||||
if save_to_db("speaking", speaking_pt1_to_insert):
|
|
||||||
return speaking_pt1_to_insert
|
|
||||||
else:
|
|
||||||
raise Exception("Failed to save question: " + speaking_pt1_to_insert)
|
|
||||||
else:
|
|
||||||
raise Exception("Array sizes do not match. Video uploading failing is probably the cause.")
|
|
||||||
except Exception as e:
|
|
||||||
return str(e)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/speaking_task_2', methods=['POST'])
|
@app.route('/speaking_task_2', methods=['POST'])
|
||||||
@jwt_required()
|
@jwt_required()
|
||||||
def grade_speaking_task_2():
|
def grade_speaking_task_2():
|
||||||
@@ -509,54 +395,6 @@ def get_speaking_task_2_question():
|
|||||||
return str(e)
|
return str(e)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/save_speaking_task_2', methods=['POST'])
|
|
||||||
@jwt_required()
|
|
||||||
def save_speaking_task_2_question():
|
|
||||||
try:
|
|
||||||
# data = request.get_json()
|
|
||||||
# question = data.get('question')
|
|
||||||
questions_json = getSpeaking2Template()
|
|
||||||
questions = []
|
|
||||||
for question in questions_json["questions"]:
|
|
||||||
result = create_video(question)
|
|
||||||
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
|
|
||||||
}
|
|
||||||
questions.append(video)
|
|
||||||
else:
|
|
||||||
print("Failed to create video for question: " + question)
|
|
||||||
|
|
||||||
if len(questions) == len(questions_json["questions"]):
|
|
||||||
speaking_pt2_to_insert = {
|
|
||||||
"exercises": [
|
|
||||||
{
|
|
||||||
"id": str(uuid.uuid4()),
|
|
||||||
"prompts": questions,
|
|
||||||
"text": "Listen carefully and respond.",
|
|
||||||
"title": questions_json["topic"],
|
|
||||||
"type": "speakingPart2"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"isDiagnostic": True,
|
|
||||||
"minTimer": 5,
|
|
||||||
"module": "speaking"
|
|
||||||
}
|
|
||||||
if save_to_db("speaking", speaking_pt2_to_insert):
|
|
||||||
return speaking_pt2_to_insert
|
|
||||||
else:
|
|
||||||
raise Exception("Failed to save question: " + str(speaking_pt2_to_insert))
|
|
||||||
else:
|
|
||||||
raise Exception("Array sizes do not match. Video uploading failing is probably the cause.")
|
|
||||||
except Exception as e:
|
|
||||||
return str(e)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/speaking_task_3', methods=['GET'])
|
@app.route('/speaking_task_3', methods=['GET'])
|
||||||
@jwt_required()
|
@jwt_required()
|
||||||
def get_speaking_task_3_question():
|
def get_speaking_task_3_question():
|
||||||
@@ -612,50 +450,76 @@ def grade_speaking_task_3():
|
|||||||
return str(e), 400
|
return str(e), 400
|
||||||
|
|
||||||
|
|
||||||
@app.route('/save_speaking_task_3', methods=['POST'])
|
@app.route('/speaking', methods=['POST'])
|
||||||
@jwt_required()
|
@jwt_required()
|
||||||
def save_speaking_task_3_question():
|
def save_speaking():
|
||||||
try:
|
try:
|
||||||
# data = request.get_json()
|
data = request.get_json()
|
||||||
# question = data.get('question')
|
exercises = data.get('exercises')
|
||||||
questions_json = getSpeaking3Template()
|
template = getSpeakingTemplate()
|
||||||
questions = []
|
|
||||||
for question in questions_json["questions"]:
|
# Speaking 1
|
||||||
result = create_video(question)
|
# sp1_result = create_video(exercises[0]["question"], random.choice(list(AvatarEnum)))
|
||||||
|
sp1_result = "speaking_1"
|
||||||
|
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)
|
||||||
|
url = "speaking_1_url"
|
||||||
|
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)))
|
||||||
|
sp2_result = "speaking_2"
|
||||||
|
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)
|
||||||
|
url = "speaking_2_url"
|
||||||
|
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)
|
||||||
|
result = "speaking_3"
|
||||||
if result is not None:
|
if result is not None:
|
||||||
sound_file_path = VIDEO_FILES_PATH + result
|
sound_file_path = VIDEO_FILES_PATH + result
|
||||||
firebase_file_path = FIREBASE_SPEAKING_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)
|
# url = upload_file_firebase_get_url(FIREBASE_BUCKET, firebase_file_path, sound_file_path)
|
||||||
|
url = "speaking_3_url"
|
||||||
video = {
|
video = {
|
||||||
"text": question,
|
"text": question,
|
||||||
"video_path": firebase_file_path,
|
"video_path": firebase_file_path,
|
||||||
"video_url": url
|
"video_url": url
|
||||||
}
|
}
|
||||||
questions.append(video)
|
sp3_questions.append(video)
|
||||||
else:
|
else:
|
||||||
print("Failed to create video for question: " + question)
|
print("Failed to create video for part 3 question: " + question)
|
||||||
|
template["exercises"][2]["prompts"] = sp3_questions
|
||||||
|
template["exercises"][2]["title"] = exercises[2]["topic"]
|
||||||
|
|
||||||
if len(questions) == len(questions_json["questions"]):
|
# if save_to_db("speaking", template):
|
||||||
speaking_pt3_to_insert = {
|
# return template
|
||||||
"exercises": [
|
# else:
|
||||||
{
|
# raise Exception("Failed to save speaking: " + template)
|
||||||
"id": str(uuid.uuid4()),
|
return template
|
||||||
"prompts": questions,
|
|
||||||
"text": "Listen carefully and respond.",
|
|
||||||
"title": questions_json["topic"],
|
|
||||||
"type": "speakingPart3"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"isDiagnostic": True,
|
|
||||||
"minTimer": 5,
|
|
||||||
"module": "speaking"
|
|
||||||
}
|
|
||||||
if save_to_db("speaking", speaking_pt3_to_insert):
|
|
||||||
return speaking_pt3_to_insert
|
|
||||||
else:
|
|
||||||
raise Exception("Failed to save question: " + str(speaking_pt3_to_insert))
|
|
||||||
else:
|
|
||||||
raise Exception("Array sizes do not match. Video uploading failing is probably the cause.")
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return str(e)
|
return str(e)
|
||||||
|
|
||||||
@@ -688,28 +552,6 @@ def get_reading_passage_1_question():
|
|||||||
return str(e)
|
return str(e)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/reading_passage_1', methods=['POST'])
|
|
||||||
@jwt_required()
|
|
||||||
def save_reading_passage_1_question():
|
|
||||||
try:
|
|
||||||
# data = request.get_json()
|
|
||||||
# question = data.get('question')
|
|
||||||
question = getListening1Template()
|
|
||||||
file_name = str(uuid.uuid4()) + ".mp3"
|
|
||||||
sound_file_path = AUDIO_FILES_PATH + file_name
|
|
||||||
firebase_file_path = FIREBASE_LISTENING_AUDIO_FILES_PATH + file_name
|
|
||||||
# TODO it's the conversation audio, still work to do on text-to-speech
|
|
||||||
text_to_speech(question["audio"]["conversation"], sound_file_path)
|
|
||||||
file_url = upload_file_firebase_get_url(FIREBASE_BUCKET, firebase_file_path, sound_file_path)
|
|
||||||
question["audio"]["source"] = file_url
|
|
||||||
if save_to_db("listening", question):
|
|
||||||
return question
|
|
||||||
else:
|
|
||||||
raise Exception("Failed to save question: " + question)
|
|
||||||
except Exception as e:
|
|
||||||
return str(e)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/reading_passage_2', methods=['GET'])
|
@app.route('/reading_passage_2', methods=['GET'])
|
||||||
@jwt_required()
|
@jwt_required()
|
||||||
def get_reading_passage_2_question():
|
def get_reading_passage_2_question():
|
||||||
@@ -765,6 +607,22 @@ def get_reading_passage_3_question():
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
return str(e)
|
return str(e)
|
||||||
|
|
||||||
|
@app.route('/reading', methods=['POST'])
|
||||||
|
@jwt_required()
|
||||||
|
def save_reading_passage():
|
||||||
|
try:
|
||||||
|
data = request.get_json()
|
||||||
|
parts = data.get('parts')
|
||||||
|
template = getReadingTemplate()
|
||||||
|
template["parts"] = parts
|
||||||
|
# if save_to_db("reading", template):
|
||||||
|
# return template
|
||||||
|
# else:
|
||||||
|
# raise Exception("Failed to save reading: " + template)
|
||||||
|
return template
|
||||||
|
except Exception as e:
|
||||||
|
return str(e)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/level', methods=['GET'])
|
@app.route('/level', methods=['GET'])
|
||||||
@jwt_required()
|
@jwt_required()
|
||||||
|
|||||||
@@ -24,18 +24,19 @@ def text_to_speech(text: str, file_name: str):
|
|||||||
aws_access_key_id=os.getenv("AWS_ACCESS_KEY_ID"),
|
aws_access_key_id=os.getenv("AWS_ACCESS_KEY_ID"),
|
||||||
aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY")
|
aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY")
|
||||||
)
|
)
|
||||||
|
voice = random.choice(ALL_NEURAL_VOICES)['Id']
|
||||||
# Initialize an empty list to store audio segments
|
# Initialize an empty list to store audio segments
|
||||||
audio_segments = []
|
audio_segments = []
|
||||||
tts_response = client.synthesize_speech(
|
for part in divide_text(text):
|
||||||
Engine="neural",
|
tts_response = client.synthesize_speech(
|
||||||
Text=text,
|
Engine="neural",
|
||||||
OutputFormat="mp3",
|
Text=part,
|
||||||
VoiceId=random.choice(ALL_NEURAL_VOICES)['Id']
|
OutputFormat="mp3",
|
||||||
)
|
VoiceId=voice
|
||||||
audio_segments.append(tts_response['AudioStream'].read())
|
)
|
||||||
|
audio_segments.append(tts_response['AudioStream'].read())
|
||||||
# Combine the audio segments into a single audio file
|
# Combine the audio segments into a single audio file
|
||||||
combined_audio = b"".join(audio_segments)
|
combined_audio = b"".join(audio_segments)
|
||||||
file_name = file_name + ".mp3"
|
|
||||||
# Save the combined audio to a single file
|
# Save the combined audio to a single file
|
||||||
with open(file_name, "wb") as f:
|
with open(file_name, "wb") as f:
|
||||||
f.write(combined_audio)
|
f.write(combined_audio)
|
||||||
@@ -43,20 +44,6 @@ def text_to_speech(text: str, file_name: str):
|
|||||||
print("Speech segments saved to " + file_name)
|
print("Speech segments saved to " + file_name)
|
||||||
|
|
||||||
def conversation_text_to_speech(conversation: list, file_name: str):
|
def conversation_text_to_speech(conversation: list, file_name: str):
|
||||||
# Create a dictionary to store the mapping of 'name' to 'voice'
|
|
||||||
name_to_voice = {}
|
|
||||||
for segment in conversation:
|
|
||||||
if 'voice' not in segment:
|
|
||||||
name = segment['name']
|
|
||||||
if name in name_to_voice:
|
|
||||||
voice = name_to_voice[name]
|
|
||||||
else:
|
|
||||||
if segment['gender'].lower() == 'male':
|
|
||||||
voice = random.choice(MALE_NEURAL_VOICES)['Id']
|
|
||||||
else:
|
|
||||||
voice = random.choice(FEMALE_NEURAL_VOICES)['Id']
|
|
||||||
name_to_voice[name] = voice
|
|
||||||
segment['voice'] = voice
|
|
||||||
# Initialize the Amazon Polly client
|
# Initialize the Amazon Polly client
|
||||||
client = boto3.client(
|
client = boto3.client(
|
||||||
'polly',
|
'polly',
|
||||||
@@ -77,7 +64,6 @@ def conversation_text_to_speech(conversation: list, file_name: str):
|
|||||||
audio_segments.append(response['AudioStream'].read())
|
audio_segments.append(response['AudioStream'].read())
|
||||||
# Combine the audio segments into a single audio file
|
# Combine the audio segments into a single audio file
|
||||||
combined_audio = b"".join(audio_segments)
|
combined_audio = b"".join(audio_segments)
|
||||||
file_name = file_name + ".mp3"
|
|
||||||
# Save the combined audio to a single file
|
# Save the combined audio to a single file
|
||||||
with open(file_name, "wb") as f:
|
with open(file_name, "wb") as f:
|
||||||
f.write(combined_audio)
|
f.write(combined_audio)
|
||||||
@@ -94,3 +80,24 @@ def has_10_words(text: str):
|
|||||||
words_in_input = text.split()
|
words_in_input = text.split()
|
||||||
english_word_count = sum(1 for word in words_in_input if word.lower() in english_words)
|
english_word_count = sum(1 for word in words_in_input if word.lower() in english_words)
|
||||||
return english_word_count >= 10
|
return english_word_count >= 10
|
||||||
|
|
||||||
|
def divide_text(text, max_length=3000):
|
||||||
|
if len(text) <= max_length:
|
||||||
|
return [text]
|
||||||
|
|
||||||
|
divisions = []
|
||||||
|
current_position = 0
|
||||||
|
|
||||||
|
while current_position < len(text):
|
||||||
|
next_position = min(current_position + max_length, len(text))
|
||||||
|
next_period_position = text.rfind('.', current_position, next_position)
|
||||||
|
|
||||||
|
if next_period_position != -1 and next_period_position > current_position:
|
||||||
|
divisions.append(text[current_position:next_period_position + 1])
|
||||||
|
current_position = next_period_position + 1
|
||||||
|
else:
|
||||||
|
# If no '.' found in the next chunk, split at max_length
|
||||||
|
divisions.append(text[current_position:next_position])
|
||||||
|
current_position = next_position
|
||||||
|
|
||||||
|
return divisions
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user