123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754 |
- 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 models
- import pymysql
- from first import first
- import mailer
- from moviepy.editor import VideoFileClip
- import traceback
- import logging
- import gSlide
- import aiofiles
- import json
- pymysql.install_as_MySQLdb()
- app = FastAPI()
- app.add_middleware(
- CORSMiddleware,
- allow_origins=["*"],
- allow_credentials=True,
- allow_methods=["*"],
- allow_headers=["*"],
- )
- 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
- # @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("/", 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", 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 '請先登入帳號'
- 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 '請先登入帳號'
- 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 '請先登入帳號'
- 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 = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/AI_anchor?charset=utf8mb4')
- user_id = get_user_id(token)
- 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'])
- for row in db.query(statement):
- video_info_list.append({'id':row['id'],'title':row['name'],'duration':row['duration'],'url':row['url']})
- dic_return = {'user_info':{'userName':user_obj['username'],'email':user_obj['email'],'video_num':video_num,'total_sec':total_sec,'left_sec':user_obj['left_time']},'video_info':video_info_list}
- str_return = json.dumps(dic_return)
- return str_return
- # 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 = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/AI_anchor?charset=utf8mb4')
- 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'})
- return {"access_token": access_token, "token_type": "bearer"}
- @app.post("/token")
- async def access_token(form_data: OAuth2PasswordRequestForm = Depends(), Authorize: AuthJWT = Depends()):
- db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/AI_anchor?charset=utf8mb4')
- 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 = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/AI_anchor?charset=utf8mb4')
- user = models.User(**await request.form())
- user_obj = first(db.query('SELECT * FROM users where username ="'+str(user.username)+'"'))
- if user_obj == None:
- user_register(user)
- return '註冊成功! 請回到上頁登入帳號'
- #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':user.username+'重複,請更改'}
- @app.post("/register")
- async def register(request: models.register_req):
- db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/AI_anchor?charset=utf8mb4')
- user_obj = first(db.query('SELECT * FROM users where username ="'+str(request.username)+'"'))
- if user_obj == None:
- if user_register(request):
- return {'msg':'ok'}
- else:
- return {'msg': '內部錯誤'}
- else:
- return {'msg':request.username+':使用者名稱重複,請更改'}
- @app.get('/logout')
- def logout(request: Request, Authorize: AuthJWT = Depends()):
- Authorize.jwt_required()
- Authorize.unset_jwt_cookies()
- return {"msg": "ok"}
- @app.get("/gen_avatar")
- async def avatar():
- return FileResponse('static/gen_avatar.html')
- @app.post("/swapFace")
- async def swapFace(req: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':"無法辨別圖片網址"+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':'檔案無法使用'}
- @app.post("/upload_pttx/")
- async def upload_pttx(file: UploadFile = File(...)):
- try:
- if "_" in file.filename:
- return {'msg':'檔案無法使用檔名不能含有"_"符號'}
- else:
- pttx_name = file.filename+'_'+str(time.time()).replace('.','')
- 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':'檔案無法使用'}
- @app.post("/make_anchor_video_gSlide")
- async def make_anchor_video_gSlide(req: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':'副標題數量、圖片(影片)數量以及台詞數量必須一致'}
- for idx in range(len(image_urls)):
- if 'http' not in image_urls[idx]:
- image_urls[idx] = 'http://'+image_urls[idx]
- if req.multiLang==0:
- for txt in text_content:
- if re.search('[a-zA-Z]', txt) !=None:
- print('語言錯誤')
- return {'msg':'輸入字串不能包含英文字!'}
- name_hash = str(time.time()).replace('.','')
- 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:
- return {'msg':"無法辨別圖片網址"+imgu}
- user_id = get_user_id(token)
- proto_req = 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)
- x = threading.Thread(target=gen_video_queue, args=(name_hash,name, text_content, image_urls,int(req.avatar),req.multiLang,video_id,user_id))
- x.start()
- return {"msg":"製作影片需要時間,請您耐心等候,成果會傳送至LINE群組中"}
- @app.post("/make_anchor_video_long")
- async def make_anchor_video_long(req:models.request,token: str = Depends(oauth2_scheme)):
- left_tag = [m.start() for m in re.finditer('{', req.text_content[0])]
- if len(req.image_urls) != len(left_tag):
- return {'msg':'副標題數量、圖片(影片)數量以及台詞數量必須一致'}
- 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':'輸入字串不能包含英文字!'}
- 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':"無法辨別圖片網址"+imgu}
- 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()
- return {"msg":"ok"}
- @app.post("/make_anchor_video")
- async def make_anchor_video(req:models.request,token: str = Depends(oauth2_scheme)):
- if len(req.image_urls) != len(req.text_content):
- return {'msg':'副標題數量、圖片(影片)數量以及台詞數量必須一致'}
- 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':'輸入字串不能包含英文字!'}
- 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':"無法辨別圖片網址"+imgu}
- user_id = get_user_id(token)
- video_id = save_history(req,name_hash,user_id)
- 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))
- x.start()
- return {'msg':'ok'}
- @app.post("/make_anchor_video_eng")
- async def make_anchor_video_eng(req:models.request_eng):
- if len(req.image_urls) != len(req.sub_titles) or len(req.sub_titles) != len(req.text_content):
- return {'msg':'副標題數量、圖片(影片)數量以及台詞數量必須一致'}
- 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':"無法辨別圖片網址"+imgu}
- video_id = save_history(req,name_hash)
- 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))
- x.start()
- return {"msg":"ok"}
- @app.get("/history_input")
- async def history_input(request: Request, Authorize: AuthJWT = Depends()):
- Authorize.jwt_required()
- current_user = Authorize.get_jwt_subject()
- db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/AI_anchor?charset=utf8mb4')
- 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
- @AuthJWT.load_config
- def get_config():
- return 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 = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/AI_anchor?charset=utf8mb4')
- 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 = 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 = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/AI_anchor?charset=utf8mb4')
- 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):
- db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/AI_anchor?charset=utf8mb4')
- 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 = models.User(**user_dict)
- return user
-
- def user_register(user):
- db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/AI_anchor?charset=utf8mb4')
- table = db['users']
- user.password = get_password_hash(user.password)
- table.insert(dict(user))
- return True
- 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 = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/AI_anchor?charset=utf8mb4')
- 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 = 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 = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/AI_anchor?charset=utf8mb4')
- 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','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):
- 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 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')
- 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,'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'))['COUNT(1)'] == 0:
- print('all finish, leave loop')
- break
- top1 = first(db.query('SELECT * FROM video_queue'))
- 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.106: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')
- def gen_video_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')
- 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,'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'))['COUNT(1)'] == 0:
- print('all finish, leave loop')
- break
- top1 = first(db.query('SELECT * FROM video_queue'))
- 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(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.106: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
- 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')
- def gen_video_queue_eng(name_hash,name,text_content, image_urls,sub_titles,avatar,video_id):
- db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/AI_anchor?charset=utf8mb4')
- 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,'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')
- break
- if first(db.query('SELECT COUNT(1) FROM video_queue'))['COUNT(1)'] == 0:
- print('all finish, leave loop')
- break
- top1 = first(db.query('SELECT * FROM video_queue'))
- try:
- 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']) # 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')
- notify_group(name+"(ENG)的影片已經產生完成囉! www.choozmo.com:8168/"+video_sub_folder+name_hash+".mp4")
- except:
- print('video generation error')
- notify_group('影片錯誤')
- db['video_queue'].delete(id=top1['id'])
- db.query('UPDATE video_queue_status SET status = 0')
- def gen_avatar(name_hash, imgurl):
- db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/AI_anchor?charset=utf8mb4')
- 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):
- print(text)
- print(len(text))
- print(type(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()
-
-
-
-
-
-
-
|