|
@@ -0,0 +1,1339 @@
|
|
|
+from fastapi import FastAPI,Cookie, Depends, Query, status,File, UploadFile,Request,Response,HTTPException
|
|
|
+from fastapi.templating import Jinja2Templates
|
|
|
+from fastapi.responses import HTMLResponse, RedirectResponse, JSONResponse
|
|
|
+from pydantic import BaseModel
|
|
|
+from typing import List, Optional
|
|
|
+from os.path import isfile, isdir, join
|
|
|
+import threading
|
|
|
+import zhtts
|
|
|
+import os
|
|
|
+import urllib
|
|
|
+import requests
|
|
|
+from bs4 import BeautifulSoup
|
|
|
+from PIL import Image,ImageDraw,ImageFont
|
|
|
+import pyttsx3
|
|
|
+import rpyc
|
|
|
+import random
|
|
|
+import time
|
|
|
+import math
|
|
|
+import hashlib
|
|
|
+import re
|
|
|
+import asyncio
|
|
|
+import urllib.request
|
|
|
+from fastapi.responses import FileResponse
|
|
|
+from fastapi.middleware.cors import CORSMiddleware
|
|
|
+import dataset
|
|
|
+from datetime import datetime, timedelta
|
|
|
+from util.swap_face import swap_face
|
|
|
+from fastapi.staticfiles import StaticFiles
|
|
|
+import shutil
|
|
|
+import io
|
|
|
+from first import first
|
|
|
+from passlib.context import CryptContext
|
|
|
+from jose import JWTError, jwt
|
|
|
+from fastapi_jwt_auth import AuthJWT
|
|
|
+from fastapi_jwt_auth.exceptions import AuthJWTException
|
|
|
+from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
|
|
|
+import util.models
|
|
|
+import pymysql
|
|
|
+import mailer
|
|
|
+from moviepy.editor import VideoFileClip
|
|
|
+import traceback
|
|
|
+import logging
|
|
|
+import gSlide
|
|
|
+import aiofiles
|
|
|
+import json
|
|
|
+import util.user
|
|
|
+from routers import userRoute, toolAvatarVoiceOnly
|
|
|
+#https://www.choozmo.com:8887/verify_email?code=16370312713065429 =>
|
|
|
+#https://video.choozmo.com/verify_email.html?code=16370312713065429
|
|
|
+pymysql.install_as_MySQLdb()
|
|
|
+
|
|
|
+app = FastAPI()
|
|
|
+app.include_router(userRoute.router)
|
|
|
+app.include_router(toolAvatarVoiceOnly.router)
|
|
|
+db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/AI_anchor?charset=utf8mb4')
|
|
|
+print("db loaded")
|
|
|
+mode = 'run'
|
|
|
+app.add_middleware(
|
|
|
+ CORSMiddleware,
|
|
|
+ allow_origins=["*"],
|
|
|
+ #allow_origins=["https://show.choozmo.com","https://video.choozmo.com"],
|
|
|
+ allow_credentials=True,
|
|
|
+ allow_methods=["POST","GET"],
|
|
|
+ #allow_headers=["*"],
|
|
|
+ allow_headers = ["Authorization","Accept","accept","Origin","Content-Type","X-LS-CORS-Template","X-LS-Auth-Token","X-LS-Auth-User-Token","Content-Type","X-LS-Sync-Result","X-LS-Sequence","token"],
|
|
|
+)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+SECRET_KEY = "df2f77bd544240801a048bd4293afd8eeb7fff3cb7050e42c791db4b83ebadcd"
|
|
|
+ALGORITHM = "HS256"
|
|
|
+ACCESS_TOKEN_EXPIRE_DAYS = 5
|
|
|
+pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
|
|
+
|
|
|
+
|
|
|
+app.mount("/static", StaticFiles(directory="static"), name="static")
|
|
|
+app.mount("/static/img", StaticFiles(directory="static/img"), name="static/img")
|
|
|
+app.mount("/templates", StaticFiles(directory="templates"), name="templates")
|
|
|
+
|
|
|
+templates = Jinja2Templates(directory="templates")
|
|
|
+oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
|
|
|
+
|
|
|
+tmp_video_dir = '../OpenshotService/tmp_video/'
|
|
|
+tmp_avatar_dir = '../../face_swap/tmp_avatar/' #change source face path here
|
|
|
+resource_server = 'www.choozmo.com:8168/'
|
|
|
+resource_folder = '/var/www/html/'
|
|
|
+video_sub_folder = 'ai_anchor_video/'
|
|
|
+avatar_sub_folder = 'swap_save/'
|
|
|
+tmp_img_sub_folder = 'tmp_img/'
|
|
|
+pttx_sub_folder = 'tmp_pttx/'
|
|
|
+img_upload_folder = '/var/www/html/'+tmp_img_sub_folder
|
|
|
+video_dest = '/var/www/html/'+video_sub_folder
|
|
|
+avatar_dest = '/var/www/html/'+avatar_sub_folder
|
|
|
+pttx_dest = '/var/www/html/'+pttx_sub_folder
|
|
|
+speech_dest = '/var/www/html/speech/'
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+# @app.get("/index2")
|
|
|
+# async def index2():
|
|
|
+# return FileResponse('static/index2.html')
|
|
|
+
|
|
|
+@app.get("/index_eng")
|
|
|
+async def index2():
|
|
|
+ return FileResponse('static/index_eng.html')
|
|
|
+
|
|
|
+# home page
|
|
|
+@app.get("/index", response_class=HTMLResponse)
|
|
|
+async def get_home_page(request: Request, response: Response):
|
|
|
+ return templates.TemplateResponse("index.html", {"request": request, "response": response})
|
|
|
+
|
|
|
+@app.get("/checkStatus")
|
|
|
+async def checkStatus():
|
|
|
+ errorList = []
|
|
|
+ try:
|
|
|
+ conn = rpyc.classic.connect("192.168.1.111",18812)
|
|
|
+ conn.close()
|
|
|
+ except:
|
|
|
+ errorList.append('111:18812 server')
|
|
|
+
|
|
|
+ try:
|
|
|
+ c = rpyc.connect("localhost", 8858)
|
|
|
+ c.close()
|
|
|
+ except:
|
|
|
+ errorList.append('make_video(docker name : new openshot)')
|
|
|
+
|
|
|
+ try:
|
|
|
+ c = rpyc.connect("localhost", 8868)
|
|
|
+ c.close()
|
|
|
+ except:
|
|
|
+ errorList.append('swap_face(docker name : fcontainer)')
|
|
|
+
|
|
|
+
|
|
|
+ return {'errors':errorList}
|
|
|
+
|
|
|
+@app.get("/", response_class=HTMLResponse)
|
|
|
+async def get_home_page(request: Request, response: Response):
|
|
|
+ return templates.TemplateResponse("index.html", {"request": request, "response": response})
|
|
|
+
|
|
|
+@app.get("/make_video")
|
|
|
+async def get_home_page(request: Request, response: Response, Authorize: AuthJWT = Depends()):
|
|
|
+ try:
|
|
|
+ Authorize.jwt_required()
|
|
|
+ except Exception as e:
|
|
|
+ print(e)
|
|
|
+ return {'msg':{'eng':'Please login first','zh':'請先登入帳號'}}
|
|
|
+ current_user = Authorize.get_jwt_subject()
|
|
|
+ return templates.TemplateResponse("make_video.html", {"request": request, "response": response})
|
|
|
+
|
|
|
+@app.get("/make_video_long", response_class=HTMLResponse)
|
|
|
+async def get_home_page(request: Request, response: Response, Authorize: AuthJWT = Depends()):
|
|
|
+ try:
|
|
|
+ Authorize.jwt_required()
|
|
|
+ except Exception as e:
|
|
|
+ print(e)
|
|
|
+ return {'msg':{'eng':'Please login first','zh':'請先登入帳號'}}
|
|
|
+ current_user = Authorize.get_jwt_subject()
|
|
|
+ return templates.TemplateResponse("make_video_long.html", {"request": request, "response": response})
|
|
|
+
|
|
|
+@app.get("/make_video_slide", response_class=HTMLResponse)
|
|
|
+async def make_video_slide(request: Request, response: Response, Authorize: AuthJWT = Depends()):
|
|
|
+ try:
|
|
|
+ Authorize.jwt_required()
|
|
|
+ except Exception as e:
|
|
|
+ print(e)
|
|
|
+ return {'msg':{'eng':'Please login first','zh':'請先登入帳號'}}
|
|
|
+ current_user = Authorize.get_jwt_subject()
|
|
|
+ return templates.TemplateResponse("make_video_slide.html", {"request": request, "response": response})
|
|
|
+
|
|
|
+@app.post('/user_profile',response_class=HTMLResponse)
|
|
|
+async def user_profile(token: str = Depends(oauth2_scheme)):
|
|
|
+ db_check()
|
|
|
+ if 'ok'!=verify_jwt_token(token):
|
|
|
+ return {'msg':{'eng':'Please login first','zh':'請先登入帳號'}}
|
|
|
+
|
|
|
+ user_id = get_user_id(token)
|
|
|
+ user_obj = first(db.query('SELECT * FROM users where id ="'+str(user_id)+'"'))
|
|
|
+ if user_obj['invite_code'] is None:
|
|
|
+ util.user.init_invite_code(user_id)
|
|
|
+ user_obj = first(db.query('SELECT * FROM users where id ="'+str(user_id)+'"'))
|
|
|
+ if user_obj is None:
|
|
|
+ raise HTTPException(
|
|
|
+ status_code=status.HTTP_401_UNAUTHORIZED,
|
|
|
+ detail="Missing token",
|
|
|
+ headers={"WWW-Authenticate": "Bearer"},
|
|
|
+ )
|
|
|
+ video_num = str(first(db.query('SELECT COUNT(*) FROM history_input WHERE user_id ='+str(user_obj['id'])))['COUNT(*)'])
|
|
|
+ total_sec = str(first(db.query('SELECT SUM(duration) FROM history_input where user_id='+str(user_obj['id'])))['SUM(duration)'])
|
|
|
+ left_sec = user_obj['left_time']
|
|
|
+
|
|
|
+ video_info_list = []
|
|
|
+ statement = 'SELECT * FROM history_input WHERE user_id='+str(user_obj['id'])+' ORDER BY timestamp DESC LIMIT 50'
|
|
|
+ for row in db.query(statement):
|
|
|
+ video_info_list.append({'id':row['id'],'title':row['name'],'duration':row['duration'],'url':row['link'],'time_stamp':row['timestamp'].strftime("%m/%d/%Y, %H:%M:%S")})
|
|
|
+ dic_return = {'user_info':{'id':user_id,'userName':user_obj['username'],'email':user_obj['email']
|
|
|
+ ,'video_num':video_num,'total_sec':total_sec,'left_sec':user_obj['left_time'],'invite_code':user_obj['invite_code']}
|
|
|
+ ,'video_info':video_info_list}
|
|
|
+ str_return = json.dumps(dic_return)
|
|
|
+
|
|
|
+ return str_return
|
|
|
+
|
|
|
+@app.post('/edit_profile')
|
|
|
+async def edit_profile(userModel : util.models.UserProfile ,token: str = Depends(oauth2_scheme)):
|
|
|
+ db_check()
|
|
|
+ print(token)
|
|
|
+ user_id = get_user_id(token)
|
|
|
+ print(user_id)
|
|
|
+ user_obj = next(iter(db.query('SELECT * FROM users where id ="'+str(user_id)+'"')))
|
|
|
+ user_obj['email'] = userModel.email
|
|
|
+ db['users'].update(user_obj,['id'])
|
|
|
+ return {'msg':'ok'}
|
|
|
+
|
|
|
+# login & register page
|
|
|
+@app.get("/login", response_class=HTMLResponse)
|
|
|
+async def get_login_and_register_page(request: Request):
|
|
|
+ return templates.TemplateResponse("login.html", {"request": request})
|
|
|
+
|
|
|
+@app.post("/login")
|
|
|
+async def login_for_access_token(request: Request, form_data: OAuth2PasswordRequestForm = Depends(), Authorize: AuthJWT = Depends()):
|
|
|
+ db_check()
|
|
|
+ user = authenticate_user(form_data.username, form_data.password)
|
|
|
+ if not user:
|
|
|
+ raise HTTPException(
|
|
|
+ status_code=status.HTTP_401_UNAUTHORIZED,
|
|
|
+ detail="Incorrect username or password",
|
|
|
+ headers={"WWW-Authenticate": "Bearer"},
|
|
|
+ )
|
|
|
+ access_token_expires = timedelta(days=ACCESS_TOKEN_EXPIRE_DAYS)
|
|
|
+ access_token = create_access_token(
|
|
|
+ data={"sub": user.username}, expires_delta=access_token_expires
|
|
|
+ )
|
|
|
+ table = db['users']
|
|
|
+ user.token = access_token
|
|
|
+ table.update(dict(user), ['username'])
|
|
|
+ expires = timedelta(days=ACCESS_TOKEN_EXPIRE_DAYS)
|
|
|
+ access_token = Authorize.create_access_token(subject=user.username, expires_time=expires)
|
|
|
+ refresh_token = Authorize.create_refresh_token(subject=user.username, expires_time =expires)
|
|
|
+ Authorize.set_access_cookies(access_token)
|
|
|
+ Authorize.set_refresh_cookies(refresh_token)
|
|
|
+ #return templates.TemplateResponse("index.html", {"request": request, "msg": 'Login'})
|
|
|
+ if util.user.email_veri_pass(form_data.username):
|
|
|
+ return {"access_token": access_token, "token_type": "bearer",'veri':'ok'}
|
|
|
+ else:
|
|
|
+ veri_obj = first(db.query('SELECT * FROM register_veri_code where user_id ="'+str(user.id)+'"'))
|
|
|
+ mailer.register_verify('請至點擊網址驗證 : https://video.choozmo.com/verify_email.html?code='+veri_obj['code'], user.email)
|
|
|
+ return {"access_token": access_token, "token_type": "bearer",'veri':'fail'}
|
|
|
+
|
|
|
+
|
|
|
+@app.post("/token")
|
|
|
+async def access_token(form_data: OAuth2PasswordRequestForm = Depends(), Authorize: AuthJWT = Depends()):
|
|
|
+
|
|
|
+ user = authenticate_user(form_data.username, form_data.password)
|
|
|
+ if not user:
|
|
|
+ raise HTTPException(
|
|
|
+ status_code=status.HTTP_401_UNAUTHORIZED,
|
|
|
+ detail="Incorrect username or password",
|
|
|
+ headers={"WWW-Authenticate": "Bearer"},
|
|
|
+ )
|
|
|
+ access_token_expires = timedelta(days=ACCESS_TOKEN_EXPIRE_DAYS)
|
|
|
+ access_token = create_access_token(
|
|
|
+ data={"sub": user.username}, expires_delta=access_token_expires
|
|
|
+ )
|
|
|
+ return {"access_token": access_token, "token_type": "bearer"}
|
|
|
+
|
|
|
+#前後端分離完全實現後拔除
|
|
|
+@app.post("/register_old")
|
|
|
+async def register_old(request: Request):
|
|
|
+ db_check()
|
|
|
+ user = util.models.User(**await request.form())
|
|
|
+ user_obj = first(db.query('SELECT * FROM users where username ="'+str(user.username)+'"'))
|
|
|
+ if user_obj == None:
|
|
|
+ id = user_register(user)
|
|
|
+ result = util.user.add_to_basic_role(id)
|
|
|
+ print(result)
|
|
|
+ if type(id) is int:
|
|
|
+ code = str(time.time()).replace('.','')
|
|
|
+ db['register_veri_code'].insert({'code':code,'user_id':id})
|
|
|
+ mailer.register_verify('請至點擊網址驗證 : https://video.choozmo.com/verify_email.html?code='+code, user.email)
|
|
|
+ return {'msg':{'eng':'Register success! Please login at previous page','zh':'註冊成功! 請回到上頁登入帳號'}}
|
|
|
+ else :
|
|
|
+ return {'msg':{'eng':'error','zh':'error'}}
|
|
|
+ #return templates.TemplateResponse("make_video.html", {"request": request, "success": True},status_code=status.HTTP_302_FOUND)
|
|
|
+ #return templates.TemplateResponse("login.html", {'request': request,"success": True}, status_code=status.HTTP_302_FOUND)
|
|
|
+ else:
|
|
|
+ return {'msg':{'eng':user.username+' is duplicated user name try another','zh':user.username+'重複,請更改'}}
|
|
|
+
|
|
|
+@app.post("/register")
|
|
|
+async def register(request: util.models.register_req):
|
|
|
+ db_check()
|
|
|
+ user_obj = first(db.query('SELECT * FROM users where username ="'+str(request.username)+'"'))
|
|
|
+
|
|
|
+ if user_obj == None:
|
|
|
+
|
|
|
+ id = user_register(request)
|
|
|
+ udata = dict(id=id, left_time=60)
|
|
|
+ db['users'].update(udata, ['id'])
|
|
|
+ result = util.user.add_to_basic_role(id)
|
|
|
+ print(result)
|
|
|
+ if type(id) is int:
|
|
|
+ code = str(time.time()).replace('.','')
|
|
|
+ db['register_veri_code'].insert({'code':code,'user_id':id})
|
|
|
+ try:
|
|
|
+ mailer.register_verify('請至點擊網址驗證 : https://video.choozmo.com/verify_email.html?code='+code, request.email)
|
|
|
+ return {'msg':{'eng':'Register success! Please check your mailbox to verify your email','zh':'註冊成功! 請至信箱收取驗證信'}}
|
|
|
+ except:
|
|
|
+ return {'msg':{'eng':'Invalid email address','zh':'無法寄送認證信!'}}
|
|
|
+ else :
|
|
|
+ return {'msg':{'eng':'error','zh':'error'}}
|
|
|
+ else:
|
|
|
+ return {'msg':{'eng':user_obj['username']+' is duplicated user name try another','zh':user_obj['username']+'重複,請更改'}}
|
|
|
+
|
|
|
+@app.post("/register_by_invite")
|
|
|
+async def register_by_invite(request: util.models.register_invite_req):
|
|
|
+ db_check()
|
|
|
+ user_obj = first(db.query('SELECT * FROM users where username ="'+str(request.username)+'"'))
|
|
|
+
|
|
|
+ if user_obj == None:
|
|
|
+ invcode = request.invite_code
|
|
|
+ sha = hashlib.sha256()
|
|
|
+ sha.update(str(time.time()).replace('.','').encode())
|
|
|
+ request.invite_code = sha.hexdigest()
|
|
|
+ id = user_register(request)
|
|
|
+ result = util.user.add_to_basic_role(id)
|
|
|
+ udata = dict(id=id, left_time=60)
|
|
|
+ db['users'].update(udata, ['id'])
|
|
|
+ if type(id) is int:
|
|
|
+ code = str(time.time()).replace('.','')
|
|
|
+ db['register_veri_code'].insert({'code':code,'user_id':id})
|
|
|
+ try:
|
|
|
+ mailer.register_verify('請至點擊網址驗證 : https://video.choozmo.com/verify_email.html?code='+code, request.email)
|
|
|
+ except:
|
|
|
+ return {'msg':{'eng':'Invalid email address','zh':'無法寄送認證信!'}}
|
|
|
+ util.user.add_time_by_invite(invcode)
|
|
|
+ return {'msg':{'eng':'Register success! Please login at previous page','zh':'註冊成功! 請回到上頁登入帳號'}}
|
|
|
+ else :
|
|
|
+ return {'msg':{'eng':'error','zh':'error'}}
|
|
|
+ else:
|
|
|
+ return {'msg':{'eng':user_obj['username']+' is duplicated user name try another','zh':user_obj['username']+'重複,請更改'}}
|
|
|
+
|
|
|
+@app.get('/logout')
|
|
|
+def logout(request: Request, Authorize: AuthJWT = Depends()):
|
|
|
+ Authorize.jwt_required()
|
|
|
+ Authorize.unset_jwt_cookies()
|
|
|
+ return {"msg": "ok"}
|
|
|
+
|
|
|
+@app.post('/logout_jwt')
|
|
|
+def logout(token: str = Depends(oauth2_scheme)):
|
|
|
+ db_check()
|
|
|
+ time_stamp = datetime.fromtimestamp(time.time())
|
|
|
+ time_stamp = time_stamp.strftime("%Y-%m-%d %H:%M:%S")
|
|
|
+ db['jwt_black_list'].insert({'token':token,'datetime':time_stamp})
|
|
|
+ return {"msg": "ok"}
|
|
|
+
|
|
|
+@app.post('/get_role')
|
|
|
+async def get_role(token: str = Depends(oauth2_scheme)):
|
|
|
+
|
|
|
+ user_id = util.user.get_user_id(token)
|
|
|
+ roles = util.user.get_user_role(user_id)
|
|
|
+ return roles
|
|
|
+
|
|
|
+@app.post('/create_role')
|
|
|
+async def get_role(token: str = Depends(oauth2_scheme)):
|
|
|
+
|
|
|
+ user_id = get_user_id(token)
|
|
|
+
|
|
|
+ return user_id
|
|
|
+
|
|
|
+@app.post('/get_avatar_by_role')
|
|
|
+async def get_role(token: str = Depends(oauth2_scheme)):
|
|
|
+ user_id = util.user.get_user_id(token)
|
|
|
+ avatar_info = util.user.get_avatar_by_role(user_id)
|
|
|
+ return avatar_info
|
|
|
+
|
|
|
+@app.get('/verify_email')
|
|
|
+async def verify_email(code):
|
|
|
+ db_check()
|
|
|
+ veri_obj = first(db.query('SELECT * FROM register_veri_code where code ="'+str(code)+'"'))
|
|
|
+ if veri_obj != None:
|
|
|
+ db['register_veri_code'].delete(code=code)
|
|
|
+ return {"msg": "ok"}
|
|
|
+
|
|
|
+@app.get("/reset_pwd_page_email")
|
|
|
+async def reset_pwd_page():
|
|
|
+ return FileResponse('static/reset_pwd_email.html')
|
|
|
+
|
|
|
+@app.get("/reset_pwd_page")
|
|
|
+async def reset_pwd_page():
|
|
|
+ return FileResponse('static/reset_pwd.html')
|
|
|
+
|
|
|
+@app.get('/send_reset_pwd')
|
|
|
+async def send_reset_pwd(user_id,email):
|
|
|
+ db_check()
|
|
|
+ code = str(time.time()).replace('.','')
|
|
|
+
|
|
|
+ db['reset_pw_code'].insert({'code':code,'user_id':user_id,'email':email})
|
|
|
+ msg = '請至點擊網址以重設密碼 : https://www.choozmo.com:8887/reset_pwd_page 通行碼為 '+ code
|
|
|
+ print(msg)
|
|
|
+ msg =msg.encode(encoding='utf-8')
|
|
|
+ print(msg)
|
|
|
+ print(type(user_id))
|
|
|
+ if int(user_id) != -1:
|
|
|
+ print('print at first place')
|
|
|
+ print(user_id)
|
|
|
+ user_dict = next(iter(db.query('SELECT * FROM users where id ="'+str(user_id)+'"')))
|
|
|
+ else:
|
|
|
+ user_id = util.user.get_id_by_email(email)
|
|
|
+ print(user_id)
|
|
|
+ user_dict = next(iter(db.query('SELECT * FROM users where id ="'+str(user_id)+'"')))
|
|
|
+ mailer.send(msg, user_dict['email'])
|
|
|
+ return {'msg':'ok'}
|
|
|
+
|
|
|
+@app.post('/reset_pwd')
|
|
|
+async def reset_password(req :util.models.reset_pwd):
|
|
|
+ db_check()
|
|
|
+ print(req.code)
|
|
|
+ veri_obj = next(iter(db.query('SELECT * FROM reset_pw_code where code ="'+str(req.code)+'"')))
|
|
|
+ print(veri_obj['user_id'])
|
|
|
+ user_id = util.user.get_id_by_email(veri_obj['email'])
|
|
|
+ print(user_id)
|
|
|
+ db.query('UPDATE users SET password = '+'"'+get_password_hash(req.password)+'" where id ='+str(user_id))
|
|
|
+
|
|
|
+ if veri_obj != None:
|
|
|
+ db['reset_pw_code'].delete(code=req.code)
|
|
|
+ return {"msg": "ok"}
|
|
|
+
|
|
|
+@app.get("/gen_avatar")
|
|
|
+async def avatar():
|
|
|
+ return FileResponse('static/gen_avatar.html')
|
|
|
+
|
|
|
+@app.post("/swapFace")
|
|
|
+async def swapFace(req:util.models.swap_req):
|
|
|
+ if 'http' not in req.imgurl:
|
|
|
+ req.imgurl= 'http://'+req.imgurl
|
|
|
+ try:
|
|
|
+ im = Image.open(requests.get(req.imgurl, stream=True).raw)
|
|
|
+ im= im.convert("RGB")
|
|
|
+ except:
|
|
|
+ return {'msg':{'eng':req.imgurl+'cant be proccessed','zh':"無法辨別圖片網址"+req.imgurl}}
|
|
|
+ name_hash = str(time.time()).replace('.','')
|
|
|
+
|
|
|
+ x = threading.Thread(target=gen_avatar, args=(name_hash,req.imgurl))
|
|
|
+ x.start()
|
|
|
+ return {'msg':'ok'}
|
|
|
+
|
|
|
+@app.post("/uploadfile/")
|
|
|
+async def create_upload_file(file: UploadFile = File(...)):
|
|
|
+ img_name = str(time.time()).replace('.','')
|
|
|
+ try:
|
|
|
+ if file.content_type=='video/mp4':
|
|
|
+ async with aiofiles.open(img_upload_folder+img_name+'.mp4', 'wb') as out_file:
|
|
|
+ content = await file.read()
|
|
|
+ await out_file.write(content)
|
|
|
+ return {"msg": resource_server+tmp_img_sub_folder+img_name+'.mp4'}
|
|
|
+ else:
|
|
|
+ contents = await file.read()
|
|
|
+ image = Image.open(io.BytesIO(contents))
|
|
|
+ image= image.convert("RGB")
|
|
|
+ image.save(img_upload_folder+img_name+'.jpg')
|
|
|
+ return {"msg": resource_server+tmp_img_sub_folder+img_name+'.jpg'}
|
|
|
+ except Exception as e:
|
|
|
+ logging.error(traceback.format_exc())
|
|
|
+ return {'msg':{'eng':'file cant be prossessed','zh':'檔案無法使用'}}
|
|
|
+
|
|
|
+@app.post("/upload_pttx/")
|
|
|
+async def upload_pttx(file: UploadFile = File(...)):
|
|
|
+ try:
|
|
|
+ if "#" in file.filename:
|
|
|
+ return {'msg':{'eng':'symbol"#" is not allowed in file name','zh':'檔案無法使用檔名不能含有"#"符號'}}
|
|
|
+ else:
|
|
|
+ pttx_name = file.filename.replace('.pptx','#')+str(time.time()).replace('.','')+'.pptx'
|
|
|
+ with open(pttx_dest+pttx_name, "wb+") as file_object:
|
|
|
+ file_object.write(file.file.read())
|
|
|
+ return {"msg": resource_server+pttx_sub_folder+pttx_name}
|
|
|
+ except Exception as e:
|
|
|
+ logging.error(traceback.format_exc())
|
|
|
+ return {'msg':{'eng':'file cant be prossessed','zh':'檔案無法使用'}}
|
|
|
+
|
|
|
+@app.post("/make_anchor_video_gSlide")
|
|
|
+async def make_anchor_video_gSlide(req:util.models.gSlide_req,token: str = Depends(oauth2_scheme)):
|
|
|
+ if req.url_type == 0:
|
|
|
+ name, text_content, image_urls = gSlide.parse_slide_url(req.slide_url,eng=False)
|
|
|
+ else :
|
|
|
+ filename = req.slide_url.replace(resource_server+pttx_sub_folder,resource_folder+pttx_sub_folder)
|
|
|
+ name, text_content, image_urls = gSlide.parse_pttx_url(filename,img_upload_folder,resource_server+tmp_img_sub_folder,eng=False)
|
|
|
+
|
|
|
+ if len(image_urls) != len(text_content):
|
|
|
+ return {'msg':{'eng':'number of subtitles and images(videos) should be the same','zh':'副標題數量、圖片(影片)數量以及台詞數量必須一致'}}
|
|
|
+
|
|
|
+ for idx in range(len(image_urls)):
|
|
|
+ if 'http' not in image_urls[idx]:
|
|
|
+ image_urls[idx] = 'http://'+image_urls[idx]
|
|
|
+
|
|
|
+ mulitLang, hasError = Check_text_content(text_content)
|
|
|
+ if hasError is not False :
|
|
|
+ return hasError
|
|
|
+
|
|
|
+ imgError = Check_image_url(image_urls)
|
|
|
+ if imgError is not False :
|
|
|
+ return imgError
|
|
|
+
|
|
|
+ name_hash = str(time.time()).replace('.','')
|
|
|
+ user_id = get_user_id(token)
|
|
|
+ proto_req = util.models.request_normal()
|
|
|
+ proto_req.text_content = text_content
|
|
|
+ proto_req.name = name
|
|
|
+ proto_req.image_urls = image_urls
|
|
|
+ proto_req.avatar = req.avatar
|
|
|
+ proto_req.multiLang = req.multiLang
|
|
|
+ video_id = save_history(proto_req,name_hash,user_id)
|
|
|
+ freeTrial = 0
|
|
|
+ if 6 in util.user.get_user_role_list(user_id):
|
|
|
+ freeTrial = 1
|
|
|
+ print(freeTrial)
|
|
|
+ x = threading.Thread(target=gen_video_queue, args=(name_hash,name, text_content, image_urls,int(req.avatar),req.multiLang,video_id,user_id,freeTrial))
|
|
|
+ x.start()
|
|
|
+ return {"msg":"ok"}
|
|
|
+
|
|
|
+@app.post("/make_anchor_video_long")
|
|
|
+async def make_anchor_video_long(req:util.models.request,token: str = Depends(oauth2_scheme)):
|
|
|
+ db_check()
|
|
|
+ left_tag = [m.start() for m in re.finditer('{', req.text_content[0])]
|
|
|
+ if len(req.image_urls) != len(left_tag):
|
|
|
+ return {'msg':{'eng':'number of subtitles and images(videos) should be the same','zh':'副標題數量、圖片(影片)數量以及台詞數量必須一致'}}
|
|
|
+ for idx in range(len(req.image_urls)):
|
|
|
+ if 'http' not in req.image_urls[idx]:
|
|
|
+ req.image_urls[idx] = 'http://'+req.image_urls[idx]
|
|
|
+ if req.multiLang==0:
|
|
|
+ for txt in req.text_content:
|
|
|
+ if re.search('[a-zA-Z]', txt) !=None:
|
|
|
+ print('語言錯誤')
|
|
|
+ return {'msg':{'eng':'English is not allowed in subtitles','zh':'輸入字串不能包含英文字!'}}
|
|
|
+ if re.search(',', txt) !=None:
|
|
|
+ print('包含非法符號')
|
|
|
+ return {'msg':{'eng':'symbol "," is not allowede','zh':'輸入不能含有","符號'}}
|
|
|
+ name_hash = str(time.time()).replace('.','')
|
|
|
+ for imgu in req.image_urls:
|
|
|
+ try:
|
|
|
+ if get_url_type(imgu) =='video/mp4':
|
|
|
+ r=requests.get(imgu)
|
|
|
+ else:
|
|
|
+ im = Image.open(requests.get(imgu, stream=True).raw)
|
|
|
+ im= im.convert("RGB")
|
|
|
+ except:
|
|
|
+ return {'msg':{'eng':req.imgurl+'cant be proccessed','zh':"無法辨別圖片網址"+req.imgurl}}
|
|
|
+ user_id = get_user_id(token)
|
|
|
+ video_id = save_history(req,name_hash,user_id)
|
|
|
+ x = threading.Thread(target=gen_video_long_queue, args=(name_hash,req.name, req.text_content, req.image_urls,int(req.avatar),req.multiLang,video_id,user_id))
|
|
|
+ x.start()
|
|
|
+
|
|
|
+ returnMsg = ''
|
|
|
+ if first(db.query('SELECT COUNT(1) FROM video_queue'))['COUNT(1)'] >= 3:
|
|
|
+ returnMsg = {'msg':{'eng':'There are many videos have been processing, please wait.','zh':'目前有多部影片處理中,煩請耐心等候'}}
|
|
|
+ else:
|
|
|
+ returnMsg = {'msg':{'eng':'Processing video requires a few minutes, please wait for notification','zh':'影片處理需要數分鐘,請等待通知'}}
|
|
|
+ return returnMsg
|
|
|
+
|
|
|
+@app.post("/make_anchor_video")
|
|
|
+async def make_anchor_video(req:util.models.request,token: str = Depends(oauth2_scheme)):
|
|
|
+ db_check()
|
|
|
+ if len(req.image_urls) != len(req.text_content):
|
|
|
+ return {'msg':{'eng':'number of subtitles and images(videos) should be the same','zh':'副標題數量、圖片(影片)數量以及台詞數量必須一致'}}
|
|
|
+ for idx in range(len(req.image_urls)):
|
|
|
+ if 'http' not in req.image_urls[idx]:
|
|
|
+ req.image_urls[idx] = 'http://'+req.image_urls[idx]
|
|
|
+ if req.multiLang==0:
|
|
|
+ for txt in req.text_content:
|
|
|
+ if re.search('[a-zA-Z]', txt) !=None:
|
|
|
+ print('語言錯誤')
|
|
|
+ return {'msg':{'eng':'English is not allowed in subtitles','zh':'輸入字串不能包含英文字!'}}
|
|
|
+ if re.search(',', txt) !=None:
|
|
|
+ print('包含非法符號')
|
|
|
+ return {'msg':{'eng':'symbol "," is not allowede','zh':'輸入不能含有","符號'}}
|
|
|
+ name_hash = str(time.time()).replace('.','')
|
|
|
+ for imgu in req.image_urls:
|
|
|
+ try:
|
|
|
+ if get_url_type(imgu) =='video/mp4':
|
|
|
+ r=requests.get(imgu)
|
|
|
+ else:
|
|
|
+ im = Image.open(requests.get(imgu, stream=True).raw)
|
|
|
+ im= im.convert("RGB")
|
|
|
+ except:
|
|
|
+ return {'msg':{'eng':req.imgurl+'cant be proccessed','zh':"無法辨別圖片網址"+req.imgurl}}
|
|
|
+ user_id = get_user_id(token)
|
|
|
+ video_id = save_history(req,name_hash,user_id)
|
|
|
+ freeTrial = 0
|
|
|
+ if 6 in util.user.get_user_role_list(user_id):
|
|
|
+ freeTrial = 1
|
|
|
+ print(freeTrial)
|
|
|
+ x = threading.Thread(target=gen_video_queue, args=(name_hash,req.name, req.text_content, req.image_urls,int(req.avatar),req.multiLang,video_id,user_id,freeTrial))
|
|
|
+ x.start()
|
|
|
+
|
|
|
+ if first(db.query('SELECT COUNT(1) FROM video_queue'))['COUNT(1)'] >= 3:
|
|
|
+ return {'msg':{'eng':'There are many videos have been processing, please wait.','zh':'目前有多部影片處理中,煩請耐心等候'}}
|
|
|
+ else:
|
|
|
+ return {'msg':{'eng':'Processing video requires a few minutes, please wait for notification','zh':'影片處理需要數分鐘,請等待通知'}}
|
|
|
+ return {'msg':'ok'}
|
|
|
+#not auth
|
|
|
+@app.post("/make_anchor_video_noAuth")
|
|
|
+async def make_anchor_video_noAuth(req:util.models.request):
|
|
|
+ db_check()
|
|
|
+ if len(req.image_urls) != len(req.text_content):
|
|
|
+ return {'msg':{'eng':'number of subtitles and images(videos) should be the same','zh':'副標題數量、圖片(影片)數量以及台詞數量必須一致'}}
|
|
|
+ for idx in range(len(req.image_urls)):
|
|
|
+ if 'http' not in req.image_urls[idx]:
|
|
|
+ req.image_urls[idx] = 'http://'+req.image_urls[idx]
|
|
|
+ if req.multiLang==0:
|
|
|
+ for txt in req.text_content:
|
|
|
+ if re.search('[a-zA-Z]', txt) !=None:
|
|
|
+ print('語言錯誤')
|
|
|
+ return {'msg':{'eng':'English is not allowed in subtitles','zh':'輸入字串不能包含英文字!'}}
|
|
|
+ if re.search(',', txt) !=None:
|
|
|
+ print('包含非法符號')
|
|
|
+ return {'msg':{'eng':'symbol "," is not allowede','zh':'輸入不能含有","符號'}}
|
|
|
+ name_hash = str(time.time()).replace('.','')
|
|
|
+ for imgu in req.image_urls:
|
|
|
+ try:
|
|
|
+ if get_url_type(imgu) =='video/mp4':
|
|
|
+ r=requests.get(imgu)
|
|
|
+ else:
|
|
|
+ im = Image.open(requests.get(imgu, stream=True).raw)
|
|
|
+ im= im.convert("RGB")
|
|
|
+ except:
|
|
|
+ return {'msg':{'eng':req.imgurl+'cant be proccessed','zh':"無法辨別圖片網址"+req.imgurl}}
|
|
|
+ user_id = get_user_id(token)
|
|
|
+ video_id = save_history(req,name_hash,user_id)
|
|
|
+ freeTrial = 0
|
|
|
+ if 6 in util.user.get_user_role_list(user_id):
|
|
|
+ freeTrial = 1
|
|
|
+ print(freeTrial)
|
|
|
+ x = threading.Thread(target=gen_video_queue, args=(name_hash,req.name, req.text_content, req.image_urls,int(req.avatar),req.multiLang,video_id,user_id,freeTrial))
|
|
|
+ x.start()
|
|
|
+
|
|
|
+ if first(db.query('SELECT COUNT(1) FROM video_queue'))['COUNT(1)'] >= 3:
|
|
|
+ return {'msg':{'eng':'There are many videos have been processing, please wait.','zh':'目前有多部影片處理中,煩請耐心等候'}}
|
|
|
+ else:
|
|
|
+ return {'msg':{'eng':'Processing video requires a few minutes, please wait for notification','zh':'影片處理需要數分鐘,請等待通知'}}
|
|
|
+ return {'msg':'ok'}
|
|
|
+
|
|
|
+@app.post("/make_anchor_video_noAuth2" , response_class=JSONResponse)
|
|
|
+async def make_anchor_video_noAuth2(req:util.models.request):
|
|
|
+ db_check()
|
|
|
+ if len(req.image_urls) != len(req.text_content):
|
|
|
+ return {'msg':{'eng':'number of subtitles and images(videos) should be the same','zh':'副標題數量、圖片(影片)數量以及台詞數量必須一致'}}
|
|
|
+ for idx in range(len(req.image_urls)):
|
|
|
+ if 'http' not in req.image_urls[idx]:
|
|
|
+ req.image_urls[idx] = 'http://'+req.image_urls[idx]
|
|
|
+ if req.multiLang==0:
|
|
|
+ for txt in req.text_content:
|
|
|
+ if re.search('[a-zA-Z]', txt) !=None:
|
|
|
+ print('語言錯誤')
|
|
|
+ return {'msg':{'eng':'English is not allowed in subtitles','zh':'輸入字串不能包含英文字!'}}
|
|
|
+ if re.search(',', txt) !=None:
|
|
|
+ print('包含非法符號')
|
|
|
+ return {'msg':{'eng':'symbol "," is not allowede','zh':'輸入不能含有","符號'}}
|
|
|
+ name_hash = str(time.time()).replace('.','')
|
|
|
+ for imgu in req.image_urls:
|
|
|
+ try:
|
|
|
+ if get_url_type(imgu) =='video/mp4':
|
|
|
+ r=requests.get(imgu)
|
|
|
+ else:
|
|
|
+ im = Image.open(requests.get(imgu, stream=True).raw)
|
|
|
+ im= im.convert("RGB")
|
|
|
+ except:
|
|
|
+ return {'msg':{'eng':req.imgurl+'cant be proccessed','zh':"無法辨別圖片網址"+req.imgurl}}
|
|
|
+
|
|
|
+ video_id = save_history(req,name_hash,-1)
|
|
|
+ freeTrial = 0
|
|
|
+ x = threading.Thread(target=gen_video_queue, args=(name_hash,req.name, req.text_content, req.image_urls,int(req.avatar),req.multiLang,video_id,-1,freeTrial))
|
|
|
+ x.start()
|
|
|
+
|
|
|
+ if first(db.query('SELECT COUNT(1) FROM video_queue'))['COUNT(1)'] >= 3:
|
|
|
+ return {'msg':{'eng':'There are many videos have been processing, please wait.','zh':'目前有多部影片處理中,煩請耐心等候'}}
|
|
|
+ else:
|
|
|
+ return {'msg':{'eng':'Processing video requires a few minutes, please wait for notification','zh':'影片處理需要數分鐘,請等待通知'}}
|
|
|
+ return {'msg':'ok'}
|
|
|
+
|
|
|
+@app.post("/make_anchor_video_eng")
|
|
|
+async def make_anchor_video_eng(req:util.models.request_eng,token: str = Depends(oauth2_scheme)):
|
|
|
+ db_check()
|
|
|
+ if len(req.image_urls) != len(req.sub_titles) or len(req.sub_titles) != len(req.text_content):
|
|
|
+ return {'msg':{'eng':'number of subtitles and images(videos) should be the same','zh':'副標題數量、圖片(影片)數量以及台詞數量必須一致'}}
|
|
|
+ for idx in range(len(req.image_urls)):
|
|
|
+ if 'http' not in req.image_urls[idx]:
|
|
|
+ req.image_urls[idx] = 'http://'+req.image_urls[idx]
|
|
|
+ name_hash = str(time.time()).replace('.','')
|
|
|
+ for imgu in req.image_urls:
|
|
|
+ try:
|
|
|
+ if get_url_type(imgu) =='video/mp4':
|
|
|
+ r=requests.get(imgu)
|
|
|
+ else:
|
|
|
+ im = Image.open(requests.get(imgu, stream=True).raw)
|
|
|
+ im= im.convert("RGB")
|
|
|
+ except:
|
|
|
+ return {'msg':{'eng':req.imgurl+'cant be proccessed','zh':"無法辨別圖片網址"+req.imgurl}}
|
|
|
+ user_id = get_user_id(token)
|
|
|
+ video_id = save_history(req,name_hash, user_id)
|
|
|
+ freeTrial = 0
|
|
|
+ if 6 in util.user.get_user_role_list(user_id):
|
|
|
+ freeTrial = 1
|
|
|
+ print(freeTrial)
|
|
|
+ x = threading.Thread(target=gen_video_queue_eng, args=(name_hash,req.name, req.text_content, req.image_urls,req.sub_titles,int(req.avatar),video_id,user_id,freeTrial))
|
|
|
+ x.start()
|
|
|
+
|
|
|
+ if first(db.query('SELECT COUNT(1) FROM video_queue'))['COUNT(1)'] >= 3:
|
|
|
+ return {'msg':{'eng':'There are many videos have been processing, please wait.','zh':'目前有多部影片處理中,煩請耐心等候'}}
|
|
|
+ else:
|
|
|
+ return {'msg':{'eng':'Processing video requires a few minutes, please wait for notification','zh':'影片處理需要數分鐘,請等待通知'}}
|
|
|
+ return {"msg":"ok"}
|
|
|
+
|
|
|
+@app.post("/make_anchor_video_eng_noAuth")
|
|
|
+async def make_anchor_video_eng(req:util.models.request_eng):
|
|
|
+ db_check()
|
|
|
+ if len(req.image_urls) != len(req.sub_titles) or len(req.sub_titles) != len(req.text_content):
|
|
|
+ return {'msg':{'eng':'number of subtitles and images(videos) should be the same','zh':'副標題數量、圖片(影片)數量以及台詞數量必須一致'}}
|
|
|
+ for idx in range(len(req.image_urls)):
|
|
|
+ if 'http' not in req.image_urls[idx]:
|
|
|
+ req.image_urls[idx] = 'http://'+req.image_urls[idx]
|
|
|
+ name_hash = str(time.time()).replace('.','')
|
|
|
+ for imgu in req.image_urls:
|
|
|
+ try:
|
|
|
+ if get_url_type(imgu) =='video/mp4':
|
|
|
+ r=requests.get(imgu)
|
|
|
+ else:
|
|
|
+ im = Image.open(requests.get(imgu, stream=True).raw)
|
|
|
+ im= im.convert("RGB")
|
|
|
+ except:
|
|
|
+ return {'msg':{'eng':req.imgurl+'cant be proccessed','zh':"無法辨別圖片網址"+req.imgurl}}
|
|
|
+
|
|
|
+ video_id = save_history(req,name_hash, -1)
|
|
|
+ freeTrial = 1
|
|
|
+ x = threading.Thread(target=gen_video_queue_eng, args=(name_hash,req.name, req.text_content, req.image_urls,req.sub_titles,int(req.avatar),video_id,-1,freeTrial))
|
|
|
+ x.start()
|
|
|
+
|
|
|
+ if first(db.query('SELECT COUNT(1) FROM video_queue'))['COUNT(1)'] >= 3:
|
|
|
+ return {'msg':{'eng':'There are many videos have been processing, please wait.','zh':'目前有多部影片處理中,煩請耐心等候'}}
|
|
|
+ else:
|
|
|
+ return {'msg':{'eng':'Processing video requires a few minutes, please wait for notification','zh':'影片處理需要數分鐘,請等待通知'}}
|
|
|
+ return {"msg":"ok"}
|
|
|
+
|
|
|
+@app.post("/make_anchor_video_eng_noAuth2")
|
|
|
+async def make_anchor_video_eng(req:util.models.request_eng):
|
|
|
+ db_check()
|
|
|
+ if len(req.image_urls) != len(req.sub_titles) or len(req.sub_titles) != len(req.text_content):
|
|
|
+ return {'msg':{'eng':'number of subtitles and images(videos) should be the same','zh':'副標題數量、圖片(影片)數量以及台詞數量必須一致'}}
|
|
|
+ for idx in range(len(req.image_urls)):
|
|
|
+ if 'http' not in req.image_urls[idx]:
|
|
|
+ req.image_urls[idx] = 'http://'+req.image_urls[idx]
|
|
|
+ name_hash = str(time.time()).replace('.','')
|
|
|
+ for imgu in req.image_urls:
|
|
|
+ try:
|
|
|
+ if get_url_type(imgu) =='video/mp4':
|
|
|
+ r=requests.get(imgu)
|
|
|
+ else:
|
|
|
+ im = Image.open(requests.get(imgu, stream=True).raw)
|
|
|
+ im= im.convert("RGB")
|
|
|
+ except:
|
|
|
+ return {'msg':{'eng':req.imgurl+'cant be proccessed','zh':"無法辨別圖片網址"+req.imgurl}}
|
|
|
+
|
|
|
+ video_id = save_history(req,name_hash, -1)
|
|
|
+ freeTrial = 1
|
|
|
+ x = threading.Thread(target=gen_video_queue_eng, args=(name_hash,req.name, req.text_content, req.image_urls,req.sub_titles,int(req.avatar),video_id,-1,freeTrial))
|
|
|
+ x.start()
|
|
|
+
|
|
|
+ if first(db.query('SELECT COUNT(1) FROM video_queue'))['COUNT(1)'] >= 3:
|
|
|
+ return {'msg':{'eng':'There are many videos have been processing, please wait.','zh':'目前有多部影片處理中,煩請耐心等候'}}
|
|
|
+ else:
|
|
|
+ return {'msg':{'eng':'Processing video requires a few minutes, please wait for notification','zh':'影片處理需要數分鐘,請等待通知'}}
|
|
|
+ return {"msg":"ok"}
|
|
|
+
|
|
|
+@app.post("/save_draft")
|
|
|
+async def save_draft(req:util.models.video_draft,token: str = Depends(oauth2_scheme)):
|
|
|
+ db_check()
|
|
|
+ user_id = get_user_id(token)
|
|
|
+
|
|
|
+ txt_content_seperate_by_dot = ''
|
|
|
+ for txt in req.text_content:
|
|
|
+ txt_content_seperate_by_dot += txt+","
|
|
|
+ txt_content_seperate_by_dot = txt_content_seperate_by_dot[:-1]
|
|
|
+ img_urls_seperate_by_dot = ''
|
|
|
+ for iurl in req.image_urls:
|
|
|
+ img_urls_seperate_by_dot += iurl+","
|
|
|
+ img_urls_seperate_by_dot = img_urls_seperate_by_dot[:-1]
|
|
|
+ time_stamp = datetime.fromtimestamp(time.time())
|
|
|
+ time_stamp = time_stamp.strftime("%Y-%m-%d %H:%M:%S")
|
|
|
+
|
|
|
+ if req.id==-1:
|
|
|
+ pk = db['draft'].insert({'title':req.title,'text_content':txt_content_seperate_by_dot,'image_urls':img_urls_seperate_by_dot
|
|
|
+ ,'user_id':user_id,'avatar':req.avatar,'multiLang':req.multiLang,'time_stamp':time_stamp})
|
|
|
+ else:
|
|
|
+ db['draft'].update({'id':req.id,'title':req.title,'text_content':txt_content_seperate_by_dot,'image_urls':img_urls_seperate_by_dot
|
|
|
+ ,'user_id':user_id,'avatar':req.avatar,'multiLang':req.multiLang,'time_stamp':time_stamp},['id'])
|
|
|
+
|
|
|
+ return {'msg':'ok'}
|
|
|
+
|
|
|
+
|
|
|
+@app.post('/draft_list')
|
|
|
+async def draft_list(token: str = Depends(oauth2_scheme)):
|
|
|
+ db_check()
|
|
|
+ user_id = get_user_id(token)
|
|
|
+ statement = 'SELECT * FROM draft WHERE user_id='+str(user_id)+' ORDER BY time_stamp DESC LIMIT 50'
|
|
|
+ logs = []
|
|
|
+ for row in db.query(statement):
|
|
|
+ logs.append({'id':row['id'],'title':row['title'],'avatar':row['avatar'],'mulitLang':row['multiLang']
|
|
|
+ ,'text_content':row['text_content'].split(','),'image_urls':row['image_urls'].split(',')})
|
|
|
+ return logs
|
|
|
+
|
|
|
+@app.post('/del_draft')
|
|
|
+async def del_draft(id_obj:util.models.id_obj,token: str = Depends(oauth2_scheme)):
|
|
|
+ db_check()
|
|
|
+ user_id = get_user_id(token)
|
|
|
+ statement = 'SELECT * FROM draft WHERE user_id="'+str(user_id)+'" and id ="'+str(id_obj.id)+'"'
|
|
|
+ if first(db.query(statement)) is not None:
|
|
|
+ db['draft'].delete(id=id_obj.id)
|
|
|
+ else:
|
|
|
+ return {'msg':'wrong id'}
|
|
|
+
|
|
|
+
|
|
|
+ return {'msg':'ok'}
|
|
|
+
|
|
|
+
|
|
|
+@app.get("/history_input_old")
|
|
|
+async def history_input_old(request: Request, Authorize: AuthJWT = Depends()):
|
|
|
+ db_check()
|
|
|
+ Authorize.jwt_required()
|
|
|
+ current_user = Authorize.get_jwt_subject()
|
|
|
+
|
|
|
+
|
|
|
+ user_id = first(db.query('SELECT * FROM users where username="' + current_user +'"'))['id']
|
|
|
+ statement = 'SELECT * FROM history_input WHERE user_id="'+str(user_id)+'" ORDER BY timestamp DESC LIMIT 50'
|
|
|
+
|
|
|
+ logs = []
|
|
|
+ for row in db.query(statement):
|
|
|
+ logs.append({'id':row['id'],'name':row['name'],'text_content':row['text_content'].split(','),'link':row['link'],'image_urls':row['image_urls'].split(',')})
|
|
|
+ return logs
|
|
|
+
|
|
|
+
|
|
|
+@app.post("/history_input")
|
|
|
+async def history_input(token: str = Depends(oauth2_scheme)):
|
|
|
+ db_check()
|
|
|
+ user_id = get_user_id(token)
|
|
|
+ user_obj = first(db.query('SELECT * FROM users where id ="'+str(user_id)+'"'))
|
|
|
+ statement = 'SELECT * FROM history_input WHERE user_id="'+str(user_id)+'" ORDER BY timestamp DESC LIMIT 50'
|
|
|
+
|
|
|
+ logs = []
|
|
|
+ for row in db.query(statement):
|
|
|
+ logs.append({'id':row['id'],'name':row['name'],'avatar':row['avatar'],'text_content':row['text_content'].split(','),'link':row['link'],'image_urls':row['image_urls'].split(',')})
|
|
|
+ return logs
|
|
|
+
|
|
|
+@app.post("/history_input_noAuth")
|
|
|
+async def history_input_noAuth():
|
|
|
+ db_check()
|
|
|
+ statement = 'SELECT * FROM history_input ORDER BY timestamp DESC LIMIT 50'
|
|
|
+
|
|
|
+ logs = []
|
|
|
+ for row in db.query(statement):
|
|
|
+ logs.append({'id':row['id'],'name':row['name'],'avatar':row['avatar'],'text_content':row['text_content'].split(','),'link':row['link'],'image_urls':row['image_urls'].split(',')})
|
|
|
+ return logs
|
|
|
+
|
|
|
+
|
|
|
+@AuthJWT.load_config
|
|
|
+def get_config():
|
|
|
+ return util.models.Settings()
|
|
|
+
|
|
|
+@app.exception_handler(AuthJWTException)
|
|
|
+def authjwt_exception_handler(request: Request, exc: AuthJWTException):
|
|
|
+ return JSONResponse(
|
|
|
+ status_code=exc.status_code,
|
|
|
+ content={"detail": exc.message}
|
|
|
+ )
|
|
|
+
|
|
|
+def get_user_id(token):
|
|
|
+ db_check()
|
|
|
+ credentials_exception = HTTPException(
|
|
|
+ status_code=status.HTTP_401_UNAUTHORIZED,
|
|
|
+ detail="Could not validate credentials",
|
|
|
+ headers={"WWW-Authenticate": "Bearer"},
|
|
|
+ )
|
|
|
+ try:
|
|
|
+ payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
|
|
|
+ username: str = payload.get("sub")
|
|
|
+ if username is None:
|
|
|
+ raise credentials_exception
|
|
|
+ token_data = util.models.TokenData(username=username)
|
|
|
+ except JWTError:
|
|
|
+ raise credentials_exception
|
|
|
+ user = get_user(username=token_data.username)
|
|
|
+ if user is None:
|
|
|
+ raise credentials_exception
|
|
|
+ user_id = first(db.query('SELECT * FROM users where username="' + user.username+'"'))['id']
|
|
|
+ return user_id
|
|
|
+
|
|
|
+def check_user_exists(username):
|
|
|
+ db_check()
|
|
|
+ if int(next(iter(db.query('SELECT COUNT(*) FROM AI_anchor.users WHERE username = "'+username+'"')))['COUNT(*)']) > 0:
|
|
|
+ return True
|
|
|
+ else:
|
|
|
+ return False
|
|
|
+
|
|
|
+def get_user(username: str):
|
|
|
+
|
|
|
+ if not check_user_exists(username): # if user don't exist
|
|
|
+ return False
|
|
|
+ user_dict = next(
|
|
|
+ iter(db.query('SELECT * FROM AI_anchor.users where username ="'+username+'"')))
|
|
|
+ user = util.models.User(**user_dict)
|
|
|
+ return user
|
|
|
+
|
|
|
+def user_register(user):
|
|
|
+ db_check()
|
|
|
+ table = db['users']
|
|
|
+ user.password = get_password_hash(user.password)
|
|
|
+ id = table.insert(dict(user))
|
|
|
+ return id
|
|
|
+
|
|
|
+def get_password_hash(password):
|
|
|
+ return pwd_context.hash(password)
|
|
|
+def verify_password(plain_password, hashed_password):
|
|
|
+ return pwd_context.verify(plain_password, hashed_password)
|
|
|
+def authenticate_user(username: str, password: str):
|
|
|
+ db_check()
|
|
|
+ if not check_user_exists(username): # if user don't exist
|
|
|
+ return False
|
|
|
+ user_dict = next(iter(db.query('SELECT * FROM AI_anchor.users where username ="'+username+'"')))
|
|
|
+ user = util.models.User(**user_dict)
|
|
|
+ if not verify_password(password, user.password):
|
|
|
+ return False
|
|
|
+ return user
|
|
|
+
|
|
|
+def create_access_token(data: dict, expires_delta):
|
|
|
+ to_encode = data.copy()
|
|
|
+
|
|
|
+ expire = datetime.utcnow() + expires_delta
|
|
|
+ to_encode.update({"exp": expire})
|
|
|
+ encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
|
|
|
+ return encoded_jwt
|
|
|
+
|
|
|
+def save_history(req,name_hash,user_id):
|
|
|
+ db_check()
|
|
|
+ log_table = db['history_input']
|
|
|
+ txt_content_seperate_by_dot = ''
|
|
|
+ for txt in req.text_content:
|
|
|
+ txt_content_seperate_by_dot += txt+","
|
|
|
+ txt_content_seperate_by_dot = txt_content_seperate_by_dot[:-1]
|
|
|
+ img_urls_seperate_by_dot = ''
|
|
|
+ for iurl in req.image_urls:
|
|
|
+ img_urls_seperate_by_dot += iurl+","
|
|
|
+ img_urls_seperate_by_dot = img_urls_seperate_by_dot[:-1]
|
|
|
+ time_stamp = datetime.fromtimestamp(time.time())
|
|
|
+ time_stamp = time_stamp.strftime("%Y-%m-%d %H:%M:%S")
|
|
|
+ pk = log_table.insert({'name':req.name,'text_content':txt_content_seperate_by_dot,'image_urls':img_urls_seperate_by_dot
|
|
|
+ ,'user_id':user_id,'link':'www.choozmo.com:8168/'+video_sub_folder+name_hash+'.mp4','avatar':req.avatar,'timestamp':time_stamp})
|
|
|
+ return pk
|
|
|
+
|
|
|
+def get_url_type(url):
|
|
|
+ req = urllib.request.Request(url, method='HEAD', headers={'User-Agent': 'Mozilla/5.0'})
|
|
|
+ r = urllib.request.urlopen(req)
|
|
|
+ contentType = r.getheader('Content-Type')
|
|
|
+ return contentType
|
|
|
+
|
|
|
+def notify_group(msg):
|
|
|
+ #'WekCRfnAirSiSxALiD6gcm0B56EejsoK89zFbIaiZQD' is ChoozmoTeam
|
|
|
+ glist=['7vilzohcyQMPLfAMRloUawiTV4vtusZhxv8Czo7AJX8','WekCRfnAirSiSxALiD6gcm0B56EejsoK89zFbIaiZQD','1dbtJHbWVbrooXmQqc4r8OyRWDryjD4TMJ6DiDsdgsX','HOB1kVNgIb81tTB4Ort1BfhVp9GFo6NlToMQg88vEhh']
|
|
|
+ for gid in glist:
|
|
|
+ headers = {"Authorization": "Bearer " + gid,"Content-Type": "application/x-www-form-urlencoded"}
|
|
|
+ r = requests.post("https://notify-api.line.me/api/notify",headers=headers, params={"message": msg})
|
|
|
+
|
|
|
+def notify_choozmo(msg):
|
|
|
+ #'WekCRfnAirSiSxALiD6gcm0B56EejsoK89zFbIaiZQD' is ChoozmoTeam
|
|
|
+ glist = ['WekCRfnAirSiSxALiD6gcm0B56EejsoK89zFbIaiZQD']
|
|
|
+ for gid in glist:
|
|
|
+ headers = {"Authorization": "Bearer " + gid,"Content-Type": "application/x-www-form-urlencoded"}
|
|
|
+ r = requests.post("https://notify-api.line.me/api/notify",headers=headers, params={"message": msg})
|
|
|
+
|
|
|
+def Check_text_content(text_content):
|
|
|
+ mulitLang = 0
|
|
|
+ status = False
|
|
|
+ for txt in text_content:
|
|
|
+ if re.search('[a-zA-Z]', txt) !=None:
|
|
|
+ mulitLang = 1
|
|
|
+ if re.search(',', txt) !=None:
|
|
|
+ print('包含非法符號')
|
|
|
+ status = {'msg':{'eng':'symbol "," is not allowede','zh':'輸入不能含有","符號'}}
|
|
|
+ return mulitLang, status
|
|
|
+
|
|
|
+def Check_image_url(image_urls):
|
|
|
+ status =False
|
|
|
+ for imgu in image_urls:
|
|
|
+ try:
|
|
|
+ if get_url_type(imgu) =='video/mp4':
|
|
|
+ r=requests.get(imgu)
|
|
|
+ else:
|
|
|
+ im = Image.open(requests.get(imgu, stream=True).raw)
|
|
|
+ im= im.convert("RGB")
|
|
|
+ except:
|
|
|
+ status = {'msg':{'eng':req.imgurl+'cant be proccessed','zh':"無法辨別圖片網址"+req.imgurl}}
|
|
|
+ return status
|
|
|
+
|
|
|
+
|
|
|
+def gen_video_long_queue(name_hash,name,text_content, image_urls,avatar,multiLang,video_id,user_id):
|
|
|
+ db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/AI_anchor?charset=utf8mb4')
|
|
|
+ if name_hash == 'keepRunning':
|
|
|
+ if first(db.query('SELECT COUNT(1) FROM video_queue where video_type="longvideo"'))['COUNT(1)'] == 0:
|
|
|
+ return
|
|
|
+ db.query('UPDATE video_queue_status SET status = 0;')
|
|
|
+ print('start clear long video')
|
|
|
+ else:
|
|
|
+ time_stamp = datetime.fromtimestamp(time.time()).strftime("%Y-%m-%d %H:%M:%S")
|
|
|
+ txt_content_seperate_by_dot = ''
|
|
|
+ for txt in text_content:
|
|
|
+ txt_content_seperate_by_dot += txt+","
|
|
|
+ txt_content_seperate_by_dot = txt_content_seperate_by_dot[:-1]
|
|
|
+ img_urls_seperate_by_dot = ''
|
|
|
+ for iurl in image_urls:
|
|
|
+ img_urls_seperate_by_dot += iurl+","
|
|
|
+ img_urls_seperate_by_dot = img_urls_seperate_by_dot[:-1]
|
|
|
+ db['video_queue'].insert({'name_hash':name_hash,'name':name,'text_content':txt_content_seperate_by_dot
|
|
|
+ ,'image_urls':img_urls_seperate_by_dot,'multiLang':multiLang,'video_type':'longvideo','avatar':avatar,'timestamp':time_stamp})
|
|
|
+
|
|
|
+ while True:
|
|
|
+
|
|
|
+ if first(db.query('SELECT * FROM video_queue_status'))['status'] == 1:#only one row in this table, which is the id 1 one
|
|
|
+ print('another process running, leave loop')#1 means already running
|
|
|
+ break
|
|
|
+ if first(db.query('SELECT COUNT(1) FROM video_queue where video_type="longvideo"'))['COUNT(1)'] == 0:
|
|
|
+ print('all finish, leave loop')
|
|
|
+ break
|
|
|
+ top1 = first(db.query('SELECT * FROM video_queue where video_type="longvideo"'))
|
|
|
+ try:
|
|
|
+ # if True:
|
|
|
+ db.query('UPDATE video_queue_status SET status = 1;')
|
|
|
+ c = rpyc.connect("localhost", 8858)
|
|
|
+ c._config['sync_request_timeout'] = None
|
|
|
+ remote_svc = c.root
|
|
|
+ my_answer = remote_svc.call_video_gen(top1['name_hash'],top1['name'],top1['text_content'].split(','), top1['image_urls'].split(','),top1['multiLang'],top1['avatar']) # method call
|
|
|
+ shutil.copy(tmp_video_dir+top1['name_hash']+'.mp4',video_dest+top1['name_hash']+'.mp4')
|
|
|
+ os.remove(tmp_video_dir+top1['name_hash']+'.mp4')
|
|
|
+ vid_duration = VideoFileClip(video_dest+top1['name_hash']+'.mp4').duration
|
|
|
+ user_obj = first(db.query('SELECT * FROM users where id ="'+str(user_id)+'"'))
|
|
|
+ line_token = user_obj['line_token'] # aa
|
|
|
+ left_time = user_obj['left_time']
|
|
|
+ email = user_obj['email']
|
|
|
+ print('left_time is '+str(left_time))
|
|
|
+ db.query('UPDATE history_input SET duration ='+str(vid_duration)+' WHERE id='+str(video_id)+';')
|
|
|
+ if left_time is None:
|
|
|
+ left_time = 5*60
|
|
|
+ if left_time < vid_duration:
|
|
|
+ msg = '您本月額度剩下'+str(left_time)+'秒,此部影片有'+str(vid_duration)+'秒, 若要繼續產生影片請至 192.168.1.107:8887/confirm_add_value?name_hash='+name_hash+' 加值'
|
|
|
+ print(msg)
|
|
|
+ msg =msg.encode(encoding='utf-8')
|
|
|
+ mailer.send_left_not_enough(msg, email)
|
|
|
+ #notify_line_user(msg, line_token)
|
|
|
+ notify_group(name+":帳號餘額不足,請至email查看詳細資訊")
|
|
|
+ else:
|
|
|
+ left_time = left_time - vid_duration
|
|
|
+ db.query('UPDATE users SET left_time ='+str(left_time)+' WHERE id='+str(user_id)+';')
|
|
|
+ notify_group(name+"的影片已經產生完成囉! www.choozmo.com:8168/"+video_sub_folder+name_hash+".mp4")
|
|
|
+ #notify_line_user(name+"的影片已經產生完成囉! www.choozmo.com:8168/"+video_sub_folder+name_hash+".mp4", line_token)
|
|
|
+ except Exception as e:
|
|
|
+ logging.error(traceback.format_exc())
|
|
|
+ print('video generation error')
|
|
|
+ notify_group('長影片錯誤-測試')
|
|
|
+ db['video_queue'].delete(id=top1['id'])
|
|
|
+ db.query('UPDATE video_queue_status SET status = 0')
|
|
|
+ db.close()
|
|
|
+
|
|
|
+def gen_video_queue(name_hash,name,text_content, image_urls,avatar,multiLang,video_id,user_id,freeTrial):
|
|
|
+ db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/AI_anchor?charset=utf8mb4')
|
|
|
+ if name_hash == 'keepRunning':
|
|
|
+ if first(db.query('SELECT COUNT(1) FROM video_queue where video_type="short"'))['COUNT(1)'] == 0:
|
|
|
+ return
|
|
|
+ db.query('UPDATE video_queue_status SET status = 0;')
|
|
|
+ print('start clear short video')
|
|
|
+ else:
|
|
|
+ time_stamp = datetime.fromtimestamp(time.time()).strftime("%Y-%m-%d %H:%M:%S")
|
|
|
+ txt_content_seperate_by_dot = ''
|
|
|
+ for txt in text_content:
|
|
|
+ txt_content_seperate_by_dot += txt+","
|
|
|
+ txt_content_seperate_by_dot = txt_content_seperate_by_dot[:-1]
|
|
|
+ img_urls_seperate_by_dot = ''
|
|
|
+ for iurl in image_urls:
|
|
|
+ img_urls_seperate_by_dot += iurl+","
|
|
|
+ img_urls_seperate_by_dot = img_urls_seperate_by_dot[:-1]
|
|
|
+
|
|
|
+ db['video_queue'].insert({'name_hash':name_hash,'name':name,'text_content':txt_content_seperate_by_dot
|
|
|
+ ,'image_urls':img_urls_seperate_by_dot,'multiLang':multiLang,'video_type':'short','avatar':avatar,'timestamp':time_stamp,'freeTrial':freeTrial})
|
|
|
+ while True:
|
|
|
+ db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/AI_anchor?charset=utf8mb4')
|
|
|
+ if first(db.query('SELECT * FROM video_queue_status'))['status'] == 1:#only one row in this table, which is the id 1 one
|
|
|
+ print('another process running, leave loop')#1 means already running
|
|
|
+ break
|
|
|
+ if first(db.query('SELECT COUNT(1) FROM video_queue where video_type="short"'))['COUNT(1)'] == 0:
|
|
|
+ print('all finish, leave loop')
|
|
|
+ break
|
|
|
+ try:
|
|
|
+ db.close()
|
|
|
+ db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/AI_anchor?charset=utf8mb4')
|
|
|
+ top1 = first(db.query('SELECT * FROM video_queue where video_type="short"'))
|
|
|
+ print(top1)
|
|
|
+ print(top1['name_hash'])
|
|
|
+ # if True:
|
|
|
+ db.query('UPDATE video_queue_status SET status = 1;')
|
|
|
+ c = rpyc.connect("localhost", 8858)
|
|
|
+ c._config['sync_request_timeout'] = None
|
|
|
+ remote_svc = c.root
|
|
|
+ my_answer = remote_svc.call_video(top1['name_hash'],top1['name'],top1['text_content'].split(','), top1['image_urls'].split(','),top1['multiLang'],top1['avatar'],top1['freeTrial']) # method call
|
|
|
+ shutil.copy(tmp_video_dir+top1['name_hash']+'.mp4',video_dest+top1['name_hash']+'.mp4')
|
|
|
+ os.remove(tmp_video_dir+top1['name_hash']+'.mp4')
|
|
|
+ vid_duration = VideoFileClip(video_dest+top1['name_hash']+'.mp4').duration
|
|
|
+ line_token=''
|
|
|
+ left_time=10000
|
|
|
+ email=''
|
|
|
+ if user_id!=-1:
|
|
|
+ user_obj = first(db.query('SELECT * FROM users where id ="'+str(user_id)+'"'))
|
|
|
+ line_token = user_obj['line_token'] # aa
|
|
|
+ left_time = user_obj['left_time']
|
|
|
+ email = user_obj['email']
|
|
|
+
|
|
|
+ print('left_time is '+str(left_time))
|
|
|
+ db.query('UPDATE history_input SET duration ='+str(vid_duration)+' WHERE id='+str(video_id)+';')
|
|
|
+ if left_time is None:
|
|
|
+ left_time = 5*60
|
|
|
+ if left_time < vid_duration and freeTrial!=1:
|
|
|
+ msg = '您本月額度剩下'+str(left_time)+'秒,此部影片有'+str(vid_duration)+'秒, 若要繼續產生影片請至 192.168.1.107:8887/confirm_add_value?name_hash='+name_hash+' 加值'
|
|
|
+ print(msg)
|
|
|
+ msg =msg.encode(encoding='utf-8')
|
|
|
+ mailer.send_left_not_enough(msg, email)
|
|
|
+ notify_group(msg)
|
|
|
+ #notify_line_user(msg, line_token)
|
|
|
+ else:
|
|
|
+ left_time = left_time - vid_duration
|
|
|
+ if user_id != -1:
|
|
|
+ db.query('UPDATE users SET left_time ='+str(left_time)+' WHERE id='+str(user_id)+';')
|
|
|
+ notify_group(top1['name']+"的影片已經產生完成囉! www.choozmo.com:8168/"+video_sub_folder+top1['name_hash']+".mp4")
|
|
|
+ #notify_line_user(name+"的影片已經產生完成囉! www.choozmo.com:8168/"+video_sub_folder+name_hash+".mp4", line_token)
|
|
|
+ except Exception as e:
|
|
|
+ logging.error(traceback.format_exc())
|
|
|
+ print('video generation error')
|
|
|
+ notify_group('影片錯誤')
|
|
|
+
|
|
|
+ db['video_queue'].delete(id=top1['id'])
|
|
|
+ db.query('UPDATE video_queue_status SET status = 0')
|
|
|
+ db.close()
|
|
|
+ db.close()
|
|
|
+
|
|
|
+def gen_video_queue_eng(name_hash,name,text_content, image_urls,sub_titles,avatar,video_id,user_id,freeTrial):
|
|
|
+ db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/AI_anchor?charset=utf8mb4')
|
|
|
+ if name_hash == 'keepRunning':
|
|
|
+ if first(db.query('SELECT COUNT(1) FROM video_queue where video_type="eng"'))['COUNT(1)'] == 0:
|
|
|
+ return
|
|
|
+ db.query('UPDATE video_queue_status SET status = 0;')
|
|
|
+ print('start clear eng video')
|
|
|
+ else:
|
|
|
+ time_stamp = datetime.fromtimestamp(time.time()).strftime("%Y-%m-%d %H:%M:%S")
|
|
|
+ txt_content_seperate_by_dot = ''
|
|
|
+ for txt in text_content:
|
|
|
+ txt_content_seperate_by_dot += txt+","
|
|
|
+ txt_content_seperate_by_dot = txt_content_seperate_by_dot[:-1]
|
|
|
+ img_urls_seperate_by_dot = ''
|
|
|
+ for iurl in image_urls:
|
|
|
+ img_urls_seperate_by_dot += iurl+","
|
|
|
+ img_urls_seperate_by_dot = img_urls_seperate_by_dot[:-1]
|
|
|
+ subtitles_seperate_by_dot = ''
|
|
|
+ for sub in sub_titles:
|
|
|
+ subtitles_seperate_by_dot += sub+","
|
|
|
+ subtitles_seperate_by_dot = subtitles_seperate_by_dot[:-1]
|
|
|
+
|
|
|
+ db['video_queue'].insert({'name_hash':name_hash,'name':name,'text_content':txt_content_seperate_by_dot
|
|
|
+ ,'image_urls':img_urls_seperate_by_dot,'subtitles':subtitles_seperate_by_dot,'video_type':'eng','avatar':avatar,'timestamp':time_stamp,'freeTrial':freeTrial})
|
|
|
+ while True:
|
|
|
+ db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/AI_anchor?charset=utf8mb4')
|
|
|
+ if first(db.query('SELECT * FROM video_queue_status'))['status'] == 1:#only one row in this table, which is the id 1 one
|
|
|
+ print('another process running, leave loop')#1 means already running
|
|
|
+ break
|
|
|
+ if first(db.query('SELECT COUNT(1) FROM video_queue where video_type="eng"'))['COUNT(1)'] == 0:
|
|
|
+ print('all finish, leave loop')
|
|
|
+ break
|
|
|
+ try:
|
|
|
+ db.close()
|
|
|
+ db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/AI_anchor?charset=utf8mb4')
|
|
|
+ top1 = first(db.query('SELECT * FROM video_queue where video_type="eng"'))
|
|
|
+ print(top1)
|
|
|
+ print(top1['name_hash'])
|
|
|
+ # if True:
|
|
|
+ db.query('UPDATE video_queue_status SET status = 1;')
|
|
|
+ c = rpyc.connect("localhost", 8858)
|
|
|
+ c._config['sync_request_timeout'] = None
|
|
|
+ remote_svc = c.root
|
|
|
+ my_answer = remote_svc.call_video_eng(top1['name_hash'],top1['name'],top1['text_content'].split(','), top1['image_urls'].split(','),top1['subtitles'].split(','),top1['avatar'],top1['freeTrial']) # method call
|
|
|
+ shutil.copy(tmp_video_dir+top1['name_hash']+'.mp4',video_dest+top1['name_hash']+'.mp4')
|
|
|
+ os.remove(tmp_video_dir+top1['name_hash']+'.mp4')
|
|
|
+ vid_duration = VideoFileClip(video_dest+top1['name_hash']+'.mp4').duration
|
|
|
+ line_token=''
|
|
|
+ left_time=10000
|
|
|
+ email=''
|
|
|
+ if user_id!=-1:
|
|
|
+ user_obj = first(db.query('SELECT * FROM users where id ="'+str(user_id)+'"'))
|
|
|
+ line_token = user_obj['line_token'] # aa
|
|
|
+ left_time = user_obj['left_time']
|
|
|
+ email = user_obj['email']
|
|
|
+
|
|
|
+ print('left_time is '+str(left_time))
|
|
|
+ db.query('UPDATE history_input SET duration ='+str(vid_duration)+' WHERE id='+str(video_id)+';')
|
|
|
+ if left_time is None:
|
|
|
+ left_time = 5*60
|
|
|
+ if left_time < vid_duration and freeTrial!=1:
|
|
|
+ msg = '您本月額度剩下'+str(left_time)+'秒,此部影片有'+str(vid_duration)+'秒, 若要繼續產生影片請至 192.168.1.107:8887/confirm_add_value?name_hash='+name_hash+' 加值'
|
|
|
+ print(msg)
|
|
|
+ msg =msg.encode(encoding='utf-8')
|
|
|
+ mailer.send_left_not_enough(msg, email)
|
|
|
+ notify_group(msg)
|
|
|
+ #notify_line_user(msg, line_token)
|
|
|
+ else:
|
|
|
+ left_time = left_time - vid_duration
|
|
|
+ if user_id != -1:
|
|
|
+ db.query('UPDATE users SET left_time ='+str(left_time)+' WHERE id='+str(user_id)+';')
|
|
|
+ notify_group(top1['name']+"的影片(ENG)已經產生完成囉! www.choozmo.com:8168/"+video_sub_folder+top1['name_hash']+".mp4")
|
|
|
+ #notify_line_user(name+"的影片已經產生完成囉! www.choozmo.com:8168/"+video_sub_folder+name_hash+".mp4", line_token)
|
|
|
+ except Exception as e:
|
|
|
+ logging.error(traceback.format_exc())
|
|
|
+ print('video generation error')
|
|
|
+ notify_group('影片錯誤')
|
|
|
+
|
|
|
+ db['video_queue'].delete(id=top1['id'])
|
|
|
+ db.query('UPDATE video_queue_status SET status = 0')
|
|
|
+ db.close()
|
|
|
+ db.close()
|
|
|
+
|
|
|
+def gen_avatar(name_hash, imgurl):
|
|
|
+ db_check()
|
|
|
+ db['avatar_queue'].insert({'name_hash':name_hash,'imgurl':imgurl})
|
|
|
+ while True:
|
|
|
+
|
|
|
+ statement = 'SELECT * FROM avatar_service_status'#only one row in this table, which is the id 1 one
|
|
|
+ status = -1
|
|
|
+ for row in db.query(statement):
|
|
|
+ status = row['status']
|
|
|
+ if status == 1:
|
|
|
+ print('leave process loop')
|
|
|
+ break
|
|
|
+
|
|
|
+ statement = 'SELECT * FROM avatar_queue'
|
|
|
+ works = []
|
|
|
+ for row in db.query(statement):
|
|
|
+ works.append({'id':row['id'],'name_hash':row['name_hash'],'imgurl':row['imgurl']})
|
|
|
+ if len(works)==0:
|
|
|
+ print('leave process loop')
|
|
|
+ break
|
|
|
+ try:
|
|
|
+ statement = 'UPDATE avatar_service_status SET status = 1 WHERE id=1;'
|
|
|
+ db.query(statement)
|
|
|
+ name_hash = works[0]['name_hash']
|
|
|
+ imgurl = works[0]['imgurl']
|
|
|
+ c = rpyc.connect("localhost", 8868)
|
|
|
+ c._config['sync_request_timeout'] = None
|
|
|
+ remote_svc = c.root
|
|
|
+ my_answer = remote_svc.call_avatar(name_hash,imgurl) # method call
|
|
|
+ shutil.copy(tmp_avatar_dir+name_hash+'.mp4',avatar_dest+name_hash+'.mp4')
|
|
|
+ os.remove(tmp_avatar_dir+name_hash+'.mp4')
|
|
|
+
|
|
|
+ except:
|
|
|
+ print('gen error')
|
|
|
+ notify_group('無法辨識人臉')
|
|
|
+ db['avatar_queue'].delete(id=works[0]['id'])
|
|
|
+ statement = 'UPDATE avatar_service_status SET status = 0 WHERE id=1;' #only one row in this table, which id 1 one
|
|
|
+ db.query(statement)
|
|
|
+def call_voice(text):
|
|
|
+ c = rpyc.connect("localhost", 8858)
|
|
|
+ c._config['sync_request_timeout'] = None
|
|
|
+ remote_svc = c.root
|
|
|
+ my_answer = remote_svc.make_speech(text) # method call
|
|
|
+ src_path = '/home/ming/AI_Anchor/OpenshotService/speech.mp3'
|
|
|
+ shutil.copy(src_path,'/home/ming/speech.mp3')
|
|
|
+ os.remove(src_path)
|
|
|
+
|
|
|
+class text_in(BaseModel):
|
|
|
+ text: str
|
|
|
+
|
|
|
+@app.post("/make_voice")
|
|
|
+async def make_voice(in_text:text_in):
|
|
|
+ x = threading.Thread(target=call_voice, args=(in_text.text,))
|
|
|
+ x.start()
|
|
|
+
|
|
|
+
|
|
|
+@app.post("/gen_speech")
|
|
|
+async def make_voice(req:util.models.speech_req):
|
|
|
+ call_speech(req.text,req.speaker)
|
|
|
+ return {'msg':'wait please'}
|
|
|
+
|
|
|
+def call_speech(text,speaker):
|
|
|
+ conn = rpyc.classic.connect("192.168.1.105",8838)
|
|
|
+ ros = conn.modules.os
|
|
|
+ ros.system('docker exec -it mingc_tts bash gen_speech.sh '+text+' '+speaker)
|
|
|
+
|
|
|
+ while True:
|
|
|
+ print('waiting...')
|
|
|
+ if ros.path.exists('/home/ming/workspace/TTS_fs2/fast_speech2_ming024/output/result/AISHELL3/'+text+'.wav'):
|
|
|
+ break
|
|
|
+ time.sleep(5)
|
|
|
+ print('waiting...')
|
|
|
+
|
|
|
+ fr=conn.builtins.open('/home/ming/workspace/TTS_fs2/fast_speech2_ming024/output/result/AISHELL3/'+text+'.wav','rb')
|
|
|
+ fw=open(text+'.wav','wb')
|
|
|
+ while True:
|
|
|
+ b=fr.read(1024)
|
|
|
+ if b:
|
|
|
+ fw.write(b)
|
|
|
+ else:
|
|
|
+ break
|
|
|
+ fr.close()
|
|
|
+ fw.close()
|
|
|
+ shutil.copy(text+'.wav',speech_dest+text+'.wav')
|
|
|
+ os.remove(text+'.wav')
|
|
|
+ notify_choozmo("speech at www.choozmo.com:8168/speech/"+text+".wav")
|
|
|
+
|
|
|
+
|
|
|
+def verify_jwt_token(token):
|
|
|
+ if first(db.query('SELECT COUNT(*) FROM jwt_black_list where token="'+token+'"'))['COUNT(*)'] == 0:
|
|
|
+ return 'ok'
|
|
|
+ else:
|
|
|
+ return 'please login again'
|
|
|
+def db_check():
|
|
|
+ global db
|
|
|
+ if db!=None:
|
|
|
+ db.close()
|
|
|
+ db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/AI_anchor?charset=utf8mb4')
|
|
|
+
|
|
|
+
|
|
|
+def clear_video_queue():
|
|
|
+ x = threading.Thread(target=gen_video_queue_eng, args=('keepRunning','', '', '','','','',-1,0))
|
|
|
+ x.start()
|
|
|
+
|
|
|
+ x2 = threading.Thread(target=gen_video_queue, args=('keepRunning','', '', '','','','',-1,0))
|
|
|
+ x2.start()
|
|
|
+
|
|
|
+ x3 = threading.Thread(target=gen_video_long_queue, args=('keepRunning','', '', '','','','',''))
|
|
|
+ x3.start()
|
|
|
+
|
|
|
+clear_video_queue()
|
|
|
+
|