Browse Source

add student account

deployer 2 years ago
parent
commit
56757610a9
100 changed files with 1367 additions and 13 deletions
  1. BIN
      api/16445517353270257.mp4
  2. BIN
      api/16445518357382975.mp4
  3. BIN
      api/16448196560575469.mp4
  4. BIN
      api/16448200617815137.mp4
  5. BIN
      api/1644820433917736.mp4
  6. BIN
      api/16448206223113022.mp4
  7. BIN
      api/16448209424334617.mp4
  8. BIN
      api/16448211702621484.mp4
  9. BIN
      api/16448214070772307.mp4
  10. BIN
      api/164551908123599.mp4
  11. BIN
      api/16455192161435413.mp4
  12. BIN
      api/16455197168074334.mp4
  13. BIN
      api/16455197853134997.mp4
  14. BIN
      api/16455197865516844.mp4
  15. BIN
      api/16455199105679839.mp4
  16. BIN
      api/1645520312325568.mp4
  17. BIN
      api/16455203870237365.mp4
  18. BIN
      api/16455205504511318.mp4
  19. BIN
      api/16455208246712224.mp4
  20. BIN
      api/16455211552634325.mp4
  21. BIN
      api/__pycache__/gSlide.cpython-36.pyc
  22. BIN
      api/__pycache__/mailer.cpython-36.pyc
  23. BIN
      api/__pycache__/main.cpython-36.pyc
  24. 28 13
      api/main.py
  25. 1339 0
      api/main_bak.py
  26. BIN
      api/mp3/0.mp3
  27. BIN
      api/mp3/1.mp3
  28. BIN
      api/mp3/10.mp3
  29. BIN
      api/mp3/100.mp3
  30. BIN
      api/mp3/1000.mp3
  31. BIN
      api/mp3/1001.mp3
  32. BIN
      api/mp3/1002.mp3
  33. BIN
      api/mp3/1003.mp3
  34. BIN
      api/mp3/1004.mp3
  35. BIN
      api/mp3/1005.mp3
  36. BIN
      api/mp3/1006.mp3
  37. BIN
      api/mp3/1007.mp3
  38. BIN
      api/mp3/1008.mp3
  39. BIN
      api/mp3/1009.mp3
  40. BIN
      api/mp3/101.mp3
  41. BIN
      api/mp3/1010.mp3
  42. BIN
      api/mp3/1011.mp3
  43. BIN
      api/mp3/1012.mp3
  44. BIN
      api/mp3/1013.mp3
  45. BIN
      api/mp3/1014.mp3
  46. BIN
      api/mp3/1015.mp3
  47. BIN
      api/mp3/1016.mp3
  48. BIN
      api/mp3/1017.mp3
  49. BIN
      api/mp3/1018.mp3
  50. BIN
      api/mp3/1019.mp3
  51. BIN
      api/mp3/102.mp3
  52. BIN
      api/mp3/1020.mp3
  53. BIN
      api/mp3/1021.mp3
  54. BIN
      api/mp3/1022.mp3
  55. BIN
      api/mp3/1023.mp3
  56. BIN
      api/mp3/1024.mp3
  57. BIN
      api/mp3/1025.mp3
  58. BIN
      api/mp3/1026.mp3
  59. BIN
      api/mp3/1027.mp3
  60. BIN
      api/mp3/1028.mp3
  61. BIN
      api/mp3/1029.mp3
  62. BIN
      api/mp3/103.mp3
  63. BIN
      api/mp3/1030.mp3
  64. BIN
      api/mp3/1031.mp3
  65. BIN
      api/mp3/1032.mp3
  66. BIN
      api/mp3/1033.mp3
  67. BIN
      api/mp3/1034.mp3
  68. BIN
      api/mp3/1035.mp3
  69. BIN
      api/mp3/1036.mp3
  70. BIN
      api/mp3/1037.mp3
  71. BIN
      api/mp3/1038.mp3
  72. BIN
      api/mp3/1039.mp3
  73. BIN
      api/mp3/104.mp3
  74. BIN
      api/mp3/1040.mp3
  75. BIN
      api/mp3/1041.mp3
  76. BIN
      api/mp3/1042.mp3
  77. BIN
      api/mp3/1043.mp3
  78. BIN
      api/mp3/1044.mp3
  79. BIN
      api/mp3/1045.mp3
  80. BIN
      api/mp3/1046.mp3
  81. BIN
      api/mp3/1047.mp3
  82. BIN
      api/mp3/1048.mp3
  83. BIN
      api/mp3/1049.mp3
  84. BIN
      api/mp3/105.mp3
  85. BIN
      api/mp3/1050.mp3
  86. BIN
      api/mp3/1051.mp3
  87. BIN
      api/mp3/1052.mp3
  88. BIN
      api/mp3/1053.mp3
  89. BIN
      api/mp3/1054.mp3
  90. BIN
      api/mp3/1055.mp3
  91. BIN
      api/mp3/1056.mp3
  92. BIN
      api/mp3/1057.mp3
  93. BIN
      api/mp3/1058.mp3
  94. BIN
      api/mp3/1059.mp3
  95. BIN
      api/mp3/106.mp3
  96. BIN
      api/mp3/1060.mp3
  97. BIN
      api/mp3/1061.mp3
  98. BIN
      api/mp3/1062.mp3
  99. BIN
      api/mp3/1063.mp3
  100. BIN
      api/mp3/1064.mp3

BIN
api/16445517353270257.mp4


BIN
api/16445518357382975.mp4


BIN
api/16448196560575469.mp4


BIN
api/16448200617815137.mp4


BIN
api/1644820433917736.mp4


BIN
api/16448206223113022.mp4


BIN
api/16448209424334617.mp4


BIN
api/16448211702621484.mp4


BIN
api/16448214070772307.mp4


BIN
api/164551908123599.mp4


BIN
api/16455192161435413.mp4


BIN
api/16455197168074334.mp4


BIN
api/16455197853134997.mp4


BIN
api/16455197865516844.mp4


BIN
api/16455199105679839.mp4


BIN
api/1645520312325568.mp4


BIN
api/16455203870237365.mp4


BIN
api/16455205504511318.mp4


BIN
api/16455208246712224.mp4


BIN
api/16455211552634325.mp4


BIN
api/__pycache__/gSlide.cpython-36.pyc


BIN
api/__pycache__/mailer.cpython-36.pyc


BIN
api/__pycache__/main.cpython-36.pyc


+ 28 - 13
api/main.py

@@ -287,6 +287,9 @@ async def register_old(request: Request):
 @app.post("/register")
 async def register(request: util.models.register_req):
     db_check()
+    user_obj = first(db.query('SELECT * FROM users where email ="' + str(request.email) + '"'))
+    if user_obj != None:
+        return {'msg':{'eng':user_obj['email']+' is duplicated email try another','zh':user_obj['email']+'重複,請更改'}} 
     user_obj = first(db.query('SELECT * FROM users where username ="'+str(request.username)+'"'))
     
     if user_obj == None:
@@ -295,6 +298,10 @@ async def register(request: util.models.register_req):
         udata = dict(id=id, left_time=60)
         db['users'].update(udata, ['id'])
         result = util.user.add_to_basic_role(id)
+        if '@mail.chihlee.edu.tw' in request.email:
+            db.query('insert into user_role (user_id,role_id) values('+str(id)+',10); ')
+            udata = dict(id=id, left_time=60*60)
+            db['users'].update(udata, ['id'])
         print(result)
         if type(id) is int:
             code = str(time.time()).replace('.','')
@@ -516,7 +523,7 @@ async def make_anchor_video_gSlide(req:util.models.gSlide_req,token: str = Depen
     return {"msg":"ok"} 
 
 @app.post("/make_anchor_video_long")
-async def make_anchor_video_long(req:util.models.request,token: str = Depends(oauth2_scheme)):
+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):
@@ -583,16 +590,19 @@ async def make_anchor_video(req:util.models.request,token: str = Depends(oauth2_
     user_id = get_user_id(token)
     video_id = save_history(req,name_hash,user_id)
     freeTrial = 0
+    student = 0
     if 6 in util.user.get_user_role_list(user_id):
         freeTrial = 1
+    if 10 in util.user.get_user_role_list(user_id):
+        student = 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 = 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, student))
     x.start()
-     
+    "www.choozmo.com:8168/"+video_sub_folder+name_hash+".mp4"
     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':'目前有多部影片處理中,煩請耐心等候'}}
+        return {'msg':{'eng':'There are many videos have been processing, please wait. www.choozmo.com:8168/'+video_sub_folder+name_hash+'.mp4','zh':'目前有' + str(first(db.query('SELECT COUNT(1) FROM video_queue'))['COUNT(1)']) + '部影片處理中,每部影片可能5~10分鐘,稍後再刷新以下連結 www.choozmo.com:8168/'+video_sub_folder+name_hash+'.mp4'}}
     else:
-        return {'msg':{'eng':'Processing video requires a few minutes, please wait for notification','zh':'影片處理需要數分鐘,請等待通知'}}
+        return {'msg':{'eng':'Processing video requires a few minutes, please wait for notification www.choozmo.com:8168/'+video_sub_folder+name_hash+'.mp4','zh':'影片處理需要數分鐘,每部影片可能5~10分鐘,稍後再刷新以下連結 www.choozmo.com:8168/'+video_sub_folder+name_hash+'.mp4'}}
     return {'msg':'ok'}
 #not auth 
 @app.post("/make_anchor_video_noAuth")
@@ -695,10 +705,13 @@ async def make_anchor_video_eng(req:util.models.request_eng,token: str = Depends
     user_id = get_user_id(token)
     video_id = save_history(req,name_hash, user_id)
     freeTrial = 0
+    student = 0
     if 6 in util.user.get_user_role_list(user_id):
         freeTrial = 1
+    if 10 in util.user.get_user_role_list(user_id):
+        student = 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 = 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, student))
     x.start()
      
     if first(db.query('SELECT COUNT(1) FROM video_queue'))['COUNT(1)'] >= 3:
@@ -728,7 +741,8 @@ async def make_anchor_video_eng(req:util.models.request_eng):
  
     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))
+    student = 0
+    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, student))
     x.start()
      
     if first(db.query('SELECT COUNT(1) FROM video_queue'))['COUNT(1)'] >= 3:
@@ -1063,7 +1077,7 @@ def gen_video_long_queue(name_hash,name,text_content, image_urls,avatar,multiLan
         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):
+def gen_video_queue(name_hash,name,text_content, image_urls,avatar,multiLang,video_id,user_id,freeTrial, student):
     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:
@@ -1082,7 +1096,7 @@ def gen_video_queue(name_hash,name,text_content, image_urls,avatar,multiLang,vid
         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})
+        ,'image_urls':img_urls_seperate_by_dot,'multiLang':multiLang,'video_type':'short','avatar':avatar,'timestamp':time_stamp,'freeTrial':freeTrial, 'student':student})
     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
@@ -1102,7 +1116,7 @@ def gen_video_queue(name_hash,name,text_content, image_urls,avatar,multiLang,vid
             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
+            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'], top1['student']) # 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
@@ -1142,7 +1156,7 @@ def gen_video_queue(name_hash,name,text_content, image_urls,avatar,multiLang,vid
         db.close()
     db.close()
 
-def gen_video_queue_eng(name_hash,name,text_content, image_urls,sub_titles,avatar,video_id,user_id,freeTrial):
+def gen_video_queue_eng(name_hash,name,text_content, image_urls,sub_titles,avatar,video_id,user_id,freeTrial, student):
     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:
@@ -1326,10 +1340,10 @@ def db_check():
 
 
 def clear_video_queue():
-    x = threading.Thread(target=gen_video_queue_eng, args=('keepRunning','', '', '','','','',-1,0))
+    x = threading.Thread(target=gen_video_queue_eng, args=('keepRunning','', '', '','','','',-1,0,0))
     x.start()
 
-    x2 = threading.Thread(target=gen_video_queue, args=('keepRunning','', '', '','','','',-1,0))
+    x2 = threading.Thread(target=gen_video_queue, args=('keepRunning','', '', '','','','',-1,0,0))
     x2.start()
 
     x3 = threading.Thread(target=gen_video_long_queue, args=('keepRunning','', '', '','','','',''))
@@ -1337,3 +1351,4 @@ def clear_video_queue():
 
 clear_video_queue()
 
+

+ 1339 - 0
api/main_bak.py

@@ -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()
+

BIN
api/mp3/0.mp3


BIN
api/mp3/1.mp3


BIN
api/mp3/10.mp3


BIN
api/mp3/100.mp3


BIN
api/mp3/1000.mp3


BIN
api/mp3/1001.mp3


BIN
api/mp3/1002.mp3


BIN
api/mp3/1003.mp3


BIN
api/mp3/1004.mp3


BIN
api/mp3/1005.mp3


BIN
api/mp3/1006.mp3


BIN
api/mp3/1007.mp3


BIN
api/mp3/1008.mp3


BIN
api/mp3/1009.mp3


BIN
api/mp3/101.mp3


BIN
api/mp3/1010.mp3


BIN
api/mp3/1011.mp3


BIN
api/mp3/1012.mp3


BIN
api/mp3/1013.mp3


BIN
api/mp3/1014.mp3


BIN
api/mp3/1015.mp3


BIN
api/mp3/1016.mp3


BIN
api/mp3/1017.mp3


BIN
api/mp3/1018.mp3


BIN
api/mp3/1019.mp3


BIN
api/mp3/102.mp3


BIN
api/mp3/1020.mp3


BIN
api/mp3/1021.mp3


BIN
api/mp3/1022.mp3


BIN
api/mp3/1023.mp3


BIN
api/mp3/1024.mp3


BIN
api/mp3/1025.mp3


BIN
api/mp3/1026.mp3


BIN
api/mp3/1027.mp3


BIN
api/mp3/1028.mp3


BIN
api/mp3/1029.mp3


BIN
api/mp3/103.mp3


BIN
api/mp3/1030.mp3


BIN
api/mp3/1031.mp3


BIN
api/mp3/1032.mp3


BIN
api/mp3/1033.mp3


BIN
api/mp3/1034.mp3


BIN
api/mp3/1035.mp3


BIN
api/mp3/1036.mp3


BIN
api/mp3/1037.mp3


BIN
api/mp3/1038.mp3


BIN
api/mp3/1039.mp3


BIN
api/mp3/104.mp3


BIN
api/mp3/1040.mp3


BIN
api/mp3/1041.mp3


BIN
api/mp3/1042.mp3


BIN
api/mp3/1043.mp3


BIN
api/mp3/1044.mp3


BIN
api/mp3/1045.mp3


BIN
api/mp3/1046.mp3


BIN
api/mp3/1047.mp3


BIN
api/mp3/1048.mp3


BIN
api/mp3/1049.mp3


BIN
api/mp3/105.mp3


BIN
api/mp3/1050.mp3


BIN
api/mp3/1051.mp3


BIN
api/mp3/1052.mp3


BIN
api/mp3/1053.mp3


BIN
api/mp3/1054.mp3


BIN
api/mp3/1055.mp3


BIN
api/mp3/1056.mp3


BIN
api/mp3/1057.mp3


BIN
api/mp3/1058.mp3


BIN
api/mp3/1059.mp3


BIN
api/mp3/106.mp3


BIN
api/mp3/1060.mp3


BIN
api/mp3/1061.mp3


BIN
api/mp3/1062.mp3


BIN
api/mp3/1063.mp3


BIN
api/mp3/1064.mp3


Some files were not shown because too many files changed in this diff