Changes to endpoints so they allow to only get context and then the exercises as well as tidying up a bit
This commit is contained in:
@@ -3,11 +3,13 @@ from .heygen import Heygen
|
||||
from .openai import OpenAI
|
||||
from .whisper import OpenAIWhisper
|
||||
from .gpt_zero import GPTZero
|
||||
from .elai import ELAI
|
||||
|
||||
__all__ = [
|
||||
"AWSPolly",
|
||||
"Heygen",
|
||||
"OpenAI",
|
||||
"OpenAIWhisper",
|
||||
"GPTZero"
|
||||
"GPTZero",
|
||||
"ELAI"
|
||||
]
|
||||
|
||||
95
app/services/impl/third_parties/elai/__init__.py
Normal file
95
app/services/impl/third_parties/elai/__init__.py
Normal file
@@ -0,0 +1,95 @@
|
||||
import asyncio
|
||||
import os
|
||||
import logging
|
||||
from asyncio import sleep
|
||||
from copy import deepcopy
|
||||
|
||||
import aiofiles
|
||||
from charset_normalizer.md import getLogger
|
||||
|
||||
from httpx import AsyncClient
|
||||
|
||||
from app.configs.constants import ELAIAvatars
|
||||
from app.services.abc import IVideoGeneratorService
|
||||
|
||||
|
||||
class ELAI(IVideoGeneratorService):
|
||||
|
||||
_ELAI_ENDPOINT = 'https://apis.elai.io/api/v1/videos'
|
||||
|
||||
def __init__(self, client: AsyncClient, token: str, conf: dict):
|
||||
self._http_client = client
|
||||
self._conf = deepcopy(conf)
|
||||
self._logger = getLogger(__name__)
|
||||
self._GET_HEADER = {
|
||||
"accept": "application/json",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
self._POST_HEADER = {
|
||||
"accept": "application/json",
|
||||
"content-type": "application/json",
|
||||
"Authorization": f"Bearer {token}"
|
||||
}
|
||||
|
||||
|
||||
async def create_video(self, text: str, avatar: str):
|
||||
avatar_url = ELAIAvatars[avatar].value.get("avatar_url")
|
||||
avatar_code = ELAIAvatars[avatar].value.get("avatar_code")
|
||||
avatar_gender = ELAIAvatars[avatar].value.get("avatar_gender")
|
||||
avatar_canvas = ELAIAvatars[avatar].value.get("avatar_canvas")
|
||||
voice_id = ELAIAvatars[avatar].value.get("voice_id")
|
||||
voice_provider = ELAIAvatars[avatar].value.get("voice_provider")
|
||||
|
||||
self._conf["slides"][0]["canvas"]["objects"][0]["src"] = avatar_url
|
||||
self._conf["slides"]["avatar"] = {
|
||||
"code": avatar_code,
|
||||
"gender": avatar_gender,
|
||||
"canvas": avatar_canvas
|
||||
}
|
||||
self._conf["slides"]["speech"] = text
|
||||
self._conf["slides"]["voice"] = voice_id
|
||||
self._conf["slides"]["voiceProvider"] = voice_provider
|
||||
|
||||
response = await self._http_client.post(self._ELAI_ENDPOINT, headers=self._POST_HEADER, json=self._conf)
|
||||
|
||||
self._logger.info(response.status_code)
|
||||
self._logger.info(response.json())
|
||||
|
||||
video_id = response.json()["_id"]
|
||||
|
||||
if video_id:
|
||||
await self._http_client.post(f'{self._ELAI_ENDPOINT}/render/{video_id}', headers=self._GET_HEADER)
|
||||
|
||||
while True:
|
||||
response = await self._http_client.get(f'{self._ELAI_ENDPOINT}/{video_id}', headers=self._GET_HEADER)
|
||||
response_data = response.json()
|
||||
|
||||
if response_data['status'] == 'ready':
|
||||
self._logger.info(response_data)
|
||||
|
||||
download_url = response_data.get('url')
|
||||
output_directory = 'download-video/'
|
||||
output_filename = video_id + '.mp4'
|
||||
|
||||
response = await self._http_client.get(download_url)
|
||||
|
||||
if response.status_code == 200:
|
||||
os.makedirs(output_directory, exist_ok=True)
|
||||
output_path = os.path.join(output_directory, output_filename)
|
||||
|
||||
with open(output_path, 'wb') as f:
|
||||
f.write(response.content)
|
||||
|
||||
self._logger.info(f"File '{output_filename}' downloaded successfully.")
|
||||
return output_filename
|
||||
|
||||
else:
|
||||
self._logger.error(f"Failed to download file. Status code: {response.status_code}")
|
||||
return None
|
||||
|
||||
elif response_data['status'] == 'failed':
|
||||
self._logger.error('Video creation failed.')
|
||||
break
|
||||
else:
|
||||
self._logger.info('Video is still processing. Checking again in 10 seconds...')
|
||||
await sleep(10)
|
||||
72
app/services/impl/third_parties/elai/elai_conf.json
Normal file
72
app/services/impl/third_parties/elai/elai_conf.json
Normal file
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"name": "API test",
|
||||
"slides": [
|
||||
{
|
||||
"id": 1,
|
||||
"canvas": {
|
||||
"objects": [
|
||||
{
|
||||
"type": "avatar",
|
||||
"left": 151.5,
|
||||
"top": 36,
|
||||
"fill": "#4868FF",
|
||||
"scaleX": 0.3,
|
||||
"scaleY": 0.3,
|
||||
"width": 1080,
|
||||
"height": 1080,
|
||||
"avatarType": "transparent",
|
||||
"animation": {
|
||||
"type": null,
|
||||
"exitType": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"version": "5.3.0",
|
||||
"originX": "left",
|
||||
"originY": "top",
|
||||
"left": 30,
|
||||
"top": 30,
|
||||
"width": 800,
|
||||
"height": 600,
|
||||
"fill": "rgb(0,0,0)",
|
||||
"stroke": null,
|
||||
"strokeWidth": 0,
|
||||
"strokeDashArray": null,
|
||||
"strokeLineCap": "butt",
|
||||
"strokeDashOffset": 0,
|
||||
"strokeLineJoin": "miter",
|
||||
"strokeUniform": false,
|
||||
"strokeMiterLimit": 4,
|
||||
"scaleX": 0.18821429,
|
||||
"scaleY": 0.18821429,
|
||||
"angle": 0,
|
||||
"flipX": false,
|
||||
"flipY": false,
|
||||
"opacity": 1,
|
||||
"shadow": null,
|
||||
"visible": true,
|
||||
"backgroundColor": "",
|
||||
"fillRule": "nonzero",
|
||||
"paintFirst": "fill",
|
||||
"globalCompositeOperation": "source-over",
|
||||
"skewX": 0,
|
||||
"skewY": 0,
|
||||
"cropX": 0,
|
||||
"cropY": 0,
|
||||
"id": 676845479989,
|
||||
"src": "https://d3u63mhbhkevz8.cloudfront.net/production/uploads/66f5190349f943682dd776ff/en-coach-main-logo-800x600_sm1ype.jpg?Expires=1727654400&Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly9kM3U2M21oYmhrZXZ6OC5jbG91ZGZyb250Lm5ldC9wcm9kdWN0aW9uL3VwbG9hZHMvNjZmNTE5MDM0OWY5NDM2ODJkZDc3NmZmL2VuLWNvYWNoLW1haW4tbG9nby04MDB4NjAwX3NtMXlwZS5qcGciLCJDb25kaXRpb24iOnsiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjE3Mjc2NTQ0MDB9fX1dfQ__&Signature=kTVzlDeS7cua2HiAE5G%7E-yFqbhu0bHraFH5SauUln7yuNXoX7vtiKIBYiL%7Eps3LCLEZS77arSZ7H%7EG8CKzabHDjAR-Y6Uc%7ELD5KQaMmk0jbAxbC3Wdoq6cfd0qIwEuodQYlC0It2WBidP8KsgOy3uUQ%7EvcBoqlb255yMFw4pHuptOBB1kPs%7EFyzDV0fnRNsKaYRcy0Fn2EFUp13axm0CZQclazuLFM622AyCydKMy0vfxV%7Etny3sskwPaUe2OANGMFg07Q1pRuy6fUON0DsbhAh1tA2H6-nnem5KbFwiZK3IIwwYGBx3H41ovzC6Ejt80Fd0%7EPSHw7GzVBnUmtP-IA__&Key-Pair-Id=K1Y7U91AR6T7E5",
|
||||
"crossOrigin": "anonymous",
|
||||
"filters": [],
|
||||
"_exists": true
|
||||
}
|
||||
],
|
||||
"background": "#ffffff",
|
||||
"version": "4.4.0"
|
||||
},
|
||||
"animation": "fade_in",
|
||||
"language": "English",
|
||||
"voiceType": "text"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -10,12 +10,11 @@ from app.services.abc import IVideoGeneratorService
|
||||
|
||||
class Heygen(IVideoGeneratorService):
|
||||
|
||||
# TODO: Not used, remove if not necessary
|
||||
# CREATE_VIDEO_URL = 'https://api.heygen.com/v1/template.generate'
|
||||
|
||||
_GET_VIDEO_URL = 'https://api.heygen.com/v1/video_status.get'
|
||||
|
||||
def __init__(self, client: AsyncClient, heygen_token: str):
|
||||
def __init__(self, client: AsyncClient, token: str):
|
||||
pass
|
||||
"""
|
||||
self._get_header = {
|
||||
'X-Api-Key': heygen_token
|
||||
}
|
||||
@@ -25,9 +24,12 @@ class Heygen(IVideoGeneratorService):
|
||||
}
|
||||
self._http_client = client
|
||||
self._logger = logging.getLogger(__name__)
|
||||
"""
|
||||
|
||||
async def create_video(self, text: str, avatar: str):
|
||||
pass
|
||||
# POST TO CREATE VIDEO
|
||||
"""
|
||||
create_video_url = 'https://api.heygen.com/v2/template/' + avatar + '/generate'
|
||||
data = {
|
||||
"test": False,
|
||||
@@ -87,4 +89,5 @@ class Heygen(IVideoGeneratorService):
|
||||
else:
|
||||
self._logger.error(f"Failed to download file. Status code: {response.status_code}")
|
||||
return None
|
||||
"""
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ class OpenAI(ILLMService):
|
||||
params["temperature"] = temperature
|
||||
|
||||
attempt = 0
|
||||
while attempt < max_retries:
|
||||
while attempt < 3:
|
||||
result = await self._client.chat.completions.create(**params)
|
||||
result_content = result.choices[0].message.content
|
||||
try:
|
||||
@@ -142,6 +142,7 @@ class OpenAI(ILLMService):
|
||||
"content": (
|
||||
f"Previous response: {result_content}\n"
|
||||
f"JSON format: {json_scheme}"
|
||||
f"Validation errors: {e}"
|
||||
)
|
||||
}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user