Browse Source

add generate text2video in text2zip.py

tomoya 1 month ago
parent
commit
c20233ffd0
1 changed files with 179 additions and 1 deletions
  1. 179 1
      backend/app/app/api/api_v1/endpoints/text2zip.py

+ 179 - 1
backend/app/app/api/api_v1/endpoints/text2zip.py

@@ -29,10 +29,22 @@ import tempfile
 import shutil
 import PIL
 import re
+from app.db.session import SessionLocal
+import requests
+import asyncio
+from app.core.celery_app import celery_app
+from app.core.config import settings
+from app.aianchor.utils2 import check_zip, VideoMakerError
+from pathlib import Path
+import emails
 
-router = APIRouter()
+BACKEND_ZIP_STORAGE = Path("/app").joinpath(settings.BACKEND_ZIP_STORAGE)
+LOCAL_ZIP_STORAGE = Path("/").joinpath(settings.LOCAL_ZIP_STORAGE)
 
+LINE_URL = 'https://notify-api.line.me/api/notify'
+LINE_TOKEN = 'o8dqdVL2k8aiWO4jy3pawZamBu53bbjoSh2u0GJ7F0j'
 
+router = APIRouter()
 
 def gen_prompt(content:str):
     client = OpenAI(api_key='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')
@@ -133,3 +145,169 @@ def generate_zip(
         background_tasks.add_task(remove_zip)
     return FileResponse(f'{output_dir}/{dir.name}.zip', media_type="application/zip")
 
+@router.post('/gen-video')
+def generate_video(
+      *,
+    background_tasks: BackgroundTasks,
+    db: Session = Depends(deps.get_db),
+    #current_user: models.User = Depends(deps.get_current_active_user),
+    model:Literal['sd3', 'flux']="sd3", 
+    email:EmailStr,
+    texts:List[str],
+    lang:Literal["en", 'zh']):
+
+    if not model:
+        model = 'sd3'
+    wb = px.Workbook()
+    ws = wb.active
+    ws.title = 'script'
+    ws['A1'] = '大標'
+    ws['B1'] = '字幕'
+    ws['C1'] = '素材'
+    with tempfile.TemporaryDirectory() as td:
+        dir = Path(f'{td}/{datetime.datetime.now().strftime("%Y%m%d%H%M%S")}')
+        dir.mkdir(exist_ok=False)
+        texts = [text for text in texts if text]
+        for i, text in enumerate(texts):
+            print(f'{i+1}/{len(texts)}')
+            prompt = gen_prompt(text)
+            if model=='flux':
+                img_path = Path(gen_flux_image(prompt))
+
+            elif model=='sd3':
+                img_path = Path(gen_sd_image(prompt))
+            print("before", str(img_path))
+            img_path = img_path.rename(dir/(f'{i+1:02}'+img_path.suffix))
+            print("after", str(img_path))
+            ws['B'+ str(i+2)] = re.sub(punctuation, r"\\", text)
+            ws['C'+ str(i+2)] = img_path.name
+        excel_path = Path(dir/'script.xlsx')
+        wb.save(excel_path)
+        output_dir = '/tmp'
+        shutil.make_archive(f'{output_dir}/{dir.name}', format='zip', root_dir=td)
+        def remove_zip():
+            if os.path.exists(f'{output_dir}/{dir.name}.zip'):
+                os.remove(f'{output_dir}/{dir.name}.zip')
+        current_user = crud.user(db, id=0)
+        video_create = schemas.VideoCreate(title="guest", progress_state="PENDING", stored_filename=dir.name)
+        video = crud.video.create_with_owner(db=db, obj_in=video_create, owner_id=current_user.id)
+        return_msg = {"video_message":"accepted", "accepted":True}
+        video_data = jsonable_encoder(video)
+        video_data['membership_status'] = current_user.membership_status
+        video_data['available_time'] = current_user.available_time
+        video_data['video_id'] = video_data['id']
+        video_data['character'] = "hannah-2"
+        video_data['anchor'] = "hannah-2"
+        video_data['style'] = "style14"
+        video_data['lang'] = lang
+        video_data['email'] = email
+        background_tasks.add_task(wait_finish, video_data)
+        
+        
+    return "OK"
+
+async def wait_finish(video_data:dict): 
+    zip_filename = video_data['stored_filename']+".zip"
+    process = await asyncio.create_subprocess_exec("sshpass", "-p", "choozmo9", 
+                    "scp", "-P", "5722", "-o", "StrictHostKeyChecking=no", f"/tmp/{zip_filename}", f"root@172.104.93.163:{str(LOCAL_ZIP_STORAGE)}")
+    await process.wait()
+
+    task = celery_app.send_task("app.worker.make_video", kwargs=video_data)
+    while True:
+       await asyncio.sleep(1)
+       if task.state != "PENDING":
+           break
+       
+    db = SessionLocal()
+    video = db.query(models.Video).get(video_data['id'])
+    video.progress_state = "STARTED" 
+    db.commit()
+    db.close()
+    msg_data = f"{video_data['stored_filename']}:STARTED"
+    headers = {
+        'Authorization': 'Bearer ' + LINE_TOKEN    
+    }
+    data = {
+        'message':f'cloud-choozmo-com\n \
+                    Video\n \
+                    user: {video_data["owner_id"]}\n \
+                    membership: {video_data["membership_status"]}\n \
+                    video: {video_data["id"]}\n \
+                    state: start'     
+    }
+    data = requests.post(LINE_URL, headers=headers, data=data) 
+    while True:
+        await asyncio.sleep(1)
+        if task.state != "STARTED":
+            break
+
+    if task.state == "SUCCESS":
+        db = SessionLocal()
+        video = db.query(models.Video).get(video_data['id'])
+        user = db.query(models.User).get(video_data['owner_id'])
+        video.progress_state = "SUCCESS" 
+        if time := task.result:
+            user.available_time -= int(time) if int(time) <= user.available_time else 0
+            video.length = int(time)
+        db.commit()
+        db.close()
+        msg_data = f"{video_data['stored_filename']}:SUCCESS:{int(time)}"
+        headers = {
+            'Authorization': 'Bearer ' + LINE_TOKEN    
+        }
+        data = {
+            'message':f'cloud-choozmo-com\n \
+                        Video\n \
+                        user: {video_data["owner_id"]}\n \
+                        membership: {video_data["membership_status"]}\n \
+                        video: {video_data["id"]}\n \
+                        state: success'    
+        }
+        data = requests.post(LINE_URL, headers=headers, data=data) 
+
+    elif task.state == "FAILURE":
+        db = SessionLocal()
+        video = db.query(models.Video).get(video_data['id'])
+        video.progress_state = "FAILURE" 
+        db.commit()
+        db.close()
+        msg_data = f"{video_data['stored_filename']}:FAILURE"
+
+        headers = {
+            'Authorization': 'Bearer ' + LINE_TOKEN   
+        }
+        data = {
+            'message':f'cloud-choozmo-com\n \
+                        Video\n \
+                        user: {video_data["owner_id"]}\n \
+                        membership: {video_data["membership_status"]}\n \
+                        video: {video_data["id"]}\n \
+                        state: failure'     
+        }
+        data = requests.post(LINE_URL, headers=headers, data=data) 
+        send_simple_email(email_to=video_data['email'], video_path=f'http://172.104.93.163:30080/{video_data['stored_filename']}.mp4')
+        
+def send_simple_email(email_to: str, video_path: str):
+    if video_path==None:
+        message = emails.html(html="<p>Sorry!<br>The video failed to produce for some reason.</p>",
+                          subject="Choozmo Video Service",
+                          mail_from=('ChoozMo Video Service', 'verify@choozmo.com'))
+        r = message.send(to=email_to, mail_from='verify@choozmo.com', smtp={'host': 'smtp.gmail.com',
+                                                                        'port': '587',
+                                                                        'tls':True,
+                                                                        'user':'verify@choozmo.com',
+                                                                        'password':'hlmaxzjnvpeaulhw',
+                                                                        'timeout': 30})
+        assert r.status_code == 250
+    else:
+        message = emails.html(html=f"<p>Hi!<br>Here is Choozmo Video<br><a href='{video_path}'>Video</a></p>",
+                            subject="Choozmo Video Service",
+                            mail_from=('ChoozMo Video Service', 'verify@choozmo.com'))
+        message.attach(data=open(video_path, 'rb'), filename=video_path)
+        r = message.send(to=email_to, mail_from='verify@choozmo.com', smtp={'host': 'smtp.gmail.com',
+                                                                            'port': '587',
+                                                                            'tls':True,
+                                                                            'user':'verify@choozmo.com',
+                                                                            'password':'hlmaxzjnvpeaulhw',
+                                                                            'timeout': 30})
+        assert r.status_code == 250