|
@@ -0,0 +1,682 @@
|
|
|
+from fastapi import FastAPI
|
|
|
+import openshot
|
|
|
+from os import listdir
|
|
|
+from os.path import isfile, isdir, join
|
|
|
+import threading
|
|
|
+from gtts import gTTS
|
|
|
+import os
|
|
|
+import urllib
|
|
|
+from typing import List
|
|
|
+import requests
|
|
|
+from pydantic import BaseModel
|
|
|
+from bs4 import BeautifulSoup
|
|
|
+import time
|
|
|
+from PIL import Image,ImageDraw,ImageFont
|
|
|
+import pyttsx3
|
|
|
+import rpyc
|
|
|
+import random
|
|
|
+import time
|
|
|
+import math
|
|
|
+import hashlib
|
|
|
+import re
|
|
|
+import urllib.request
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+app = FastAPI()
|
|
|
+dir_sound = 'mp3_track/'
|
|
|
+dir_photo = 'photo/'
|
|
|
+dir_text = 'text_file/'
|
|
|
+dir_video = 'video_material/'
|
|
|
+dir_title = 'title/'
|
|
|
+dir_subtitle = 'subtitle/'
|
|
|
+dir_anchor = 'anchor_raw/'
|
|
|
+
|
|
|
+class request(BaseModel):
|
|
|
+ name: str
|
|
|
+ text_content: str
|
|
|
+ image_urls: List[str]
|
|
|
+
|
|
|
+class request2(BaseModel):
|
|
|
+ name: str
|
|
|
+ text_content: List[str]
|
|
|
+ image_urls: List[str]
|
|
|
+
|
|
|
+class anchor_request(BaseModel):
|
|
|
+ name: str
|
|
|
+ text_content: str
|
|
|
+ image_urls: List[str]
|
|
|
+
|
|
|
+@app.get("/")
|
|
|
+async def root():
|
|
|
+ return {"message": "Hello, this is index"}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+@app.post("/make_video_req")
|
|
|
+async def make_video_req(req:request):
|
|
|
+ x = threading.Thread(target=make_video, args=(req.name, req.text_content, req.image_urls))
|
|
|
+ x.start()
|
|
|
+ return {"msg":"製作影片需要時間,請您耐心等候"}
|
|
|
+
|
|
|
+@app.post("/make_anchor_video")
|
|
|
+async def make_anchor_video(req:request):
|
|
|
+ x = threading.Thread(target=anchor_video, args=(req.name, req.text_content, req.image_urls))
|
|
|
+ x.start()
|
|
|
+ return {"msg":"製作影片需要時間,請您耐心等候 稍後可以在www.choozmo.com:8168/"+req.name+".mp4 中觀看"}
|
|
|
+
|
|
|
+@app.post("/make_anchor_video_v2")
|
|
|
+async def make_anchor_video_v2(req:request2):
|
|
|
+ x = threading.Thread(target=anchor_video_v2, args=(req.name, req.text_content, req.image_urls))
|
|
|
+ x.start()
|
|
|
+ return {"msg":"製作影片需要時間,請您耐心等候 稍後可以在www.choozmo.com:8168/"+req.name+".mp4 中觀看"}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+def notify_group(msg):
|
|
|
+ headers = {
|
|
|
+ "Authorization": "Bearer " + "WekCRfnAirSiSxALiD6gcm0B56EejsoK89zFbIaiZQD",
|
|
|
+ "Content-Type": "application/x-www-form-urlencoded"
|
|
|
+ }
|
|
|
+ params = {"message": msg}
|
|
|
+ r = requests.post("https://notify-api.line.me/api/notify",headers=headers, params=params)
|
|
|
+ #print(r)
|
|
|
+
|
|
|
+
|
|
|
+def make_video(name, text_content, image_urls):
|
|
|
+ #save image
|
|
|
+ try:
|
|
|
+ os.mkdir(dir_photo+name)
|
|
|
+ except FileExistsError:
|
|
|
+ print("Directory " , dir_photo+name , " already exists")
|
|
|
+ img_num = 1
|
|
|
+ for imgu in image_urls:
|
|
|
+ im = Image.open(requests.get(imgu, stream=True).raw)
|
|
|
+ im.save(dir_photo+name+"/"+str(img_num)+".jpg")
|
|
|
+ img_num+=1
|
|
|
+ #save text
|
|
|
+ text_file = open(dir_text+name+".txt", "w")
|
|
|
+ text_file.write(text_content)
|
|
|
+ text_file.close()
|
|
|
+ print("text file made")
|
|
|
+ #make mp3
|
|
|
+ language = 'zh-tw'
|
|
|
+ output = gTTS(text=text_content, lang=language, slow=False)
|
|
|
+ output.save(dir_sound+name+".mp3")
|
|
|
+ print("mp3 file made")
|
|
|
+ #make vido
|
|
|
+ t = openshot.Timeline(1280, 720, openshot.Fraction(30000, 1000), 44100, 2, openshot.LAYOUT_STEREO)
|
|
|
+ t.Open()
|
|
|
+ sound = openshot.FFmpegReader(dir_sound+name+".mp3")
|
|
|
+ sound.Open()
|
|
|
+ sound_track = openshot.Clip(sound)
|
|
|
+ t.AddClip(sound_track)
|
|
|
+ duration = sound.info.duration
|
|
|
+
|
|
|
+ w = openshot.FFmpegWriter("../html/"+name+".mp4")
|
|
|
+ w.SetAudioOptions(True, "libmp3lame", 44100, 2, openshot.LAYOUT_STEREO, 3000000)
|
|
|
+ w.SetVideoOptions(True, "libx264", openshot.Fraction(30000, 1000), 1280, 720,
|
|
|
+ openshot.Fraction(1, 1), False, False, 3000000)
|
|
|
+ w.Open()
|
|
|
+ p_num = len(listdir(dir_photo+name))
|
|
|
+ clip_list = [None]*p_num
|
|
|
+ img_list = [None]*p_num
|
|
|
+ single_duration = int(duration/p_num)
|
|
|
+ frame_cnt = 0
|
|
|
+ for p in listdir(dir_photo+name):
|
|
|
+ img_list[frame_cnt] = openshot.QtImageReader(dir_photo+name+"/"+p)
|
|
|
+ clip_list[frame_cnt] = openshot.Clip(img_list[frame_cnt])
|
|
|
+ clip_list[frame_cnt].has_audio=openshot.Keyframe(0)
|
|
|
+ clip_list[frame_cnt].Layer(1)
|
|
|
+ clip_list[frame_cnt].Position(frame_cnt*single_duration) # start from time 0 sec
|
|
|
+ t.AddClip(clip_list[frame_cnt])
|
|
|
+ frame_cnt+=1
|
|
|
+
|
|
|
+ t_op = openshot.Timeline(1280, 720, openshot.Fraction(30000, 1000), 44100, 2, openshot.LAYOUT_STEREO)
|
|
|
+ t_op.Open()
|
|
|
+ op_vid = openshot.FFmpegReader(dir_video+"LOGO_OP.mp4")
|
|
|
+ op_vid.Open()
|
|
|
+ op_clip = openshot.Clip(op_vid)
|
|
|
+ t_op.AddClip(op_clip)
|
|
|
+ duration_op = op_vid.info.duration
|
|
|
+
|
|
|
+ for n in range(int(t_op.info.fps)*int(duration_op)):
|
|
|
+ f=t_op.GetFrame(n)
|
|
|
+ w.WriteFrame(f)
|
|
|
+
|
|
|
+ for n in range(int(t.info.fps)*int(duration)):
|
|
|
+ f=t.GetFrame(n)
|
|
|
+ w.WriteFrame(f)
|
|
|
+
|
|
|
+ t_ed = openshot.Timeline(1280, 720, openshot.Fraction(30000, 1000), 44100, 2, openshot.LAYOUT_STEREO)
|
|
|
+ t_ed.Open()
|
|
|
+ ed_vid = openshot.FFmpegReader(dir_video+"LOGO_ED.avi")
|
|
|
+ ed_vid.Open()
|
|
|
+ ed_clip = openshot.Clip(ed_vid)
|
|
|
+ t_ed.AddClip(ed_clip)
|
|
|
+ duration_ed = ed_vid.info.duration
|
|
|
+
|
|
|
+ for n in range(int(t_ed.info.fps)*int(duration_ed)):
|
|
|
+ f=t_ed.GetFrame(n)
|
|
|
+ w.WriteFrame(f)
|
|
|
+
|
|
|
+
|
|
|
+ t_ed.Close()
|
|
|
+ t_op.Close()
|
|
|
+ t.Close()
|
|
|
+ w.Close()
|
|
|
+ sound.Close()
|
|
|
+
|
|
|
+ notify_group(name+"的影片已經產生完成囉! www.choozmo.com:8168/"+name+".mp4")
|
|
|
+
|
|
|
+def cKey(r,g,b,fuzz):
|
|
|
+ col=openshot.Color()
|
|
|
+ col.red=openshot.Keyframe(r)
|
|
|
+ col.green=openshot.Keyframe(g)
|
|
|
+ col.blue=openshot.Keyframe(b)
|
|
|
+ return openshot.ChromaKey(col, openshot.Keyframe(fuzz))
|
|
|
+
|
|
|
+def video_photo_clip(vid=None,layer=None, position=None, end=None
|
|
|
+ ,scale_x=1,scale_y=1,location_x=0,location_y=0,ck=None,audio=True):
|
|
|
+ clip = openshot.Clip(vid)
|
|
|
+ clip.Layer(layer)
|
|
|
+ clip.Position(position)
|
|
|
+ clip.End(end)
|
|
|
+ clip.scale_x=openshot.Keyframe(scale_x)
|
|
|
+ clip.scale_y=openshot.Keyframe(scale_y)
|
|
|
+ clip.location_x=openshot.Keyframe(location_x)
|
|
|
+ clip.location_y=openshot.Keyframe(location_y)
|
|
|
+
|
|
|
+ if ck!=None:
|
|
|
+ clip.AddEffect(ck)
|
|
|
+ if audio==True:
|
|
|
+ clip.has_audio=openshot.Keyframe(1)
|
|
|
+ else:
|
|
|
+ clip.has_audio=openshot.Keyframe(0)
|
|
|
+ return clip
|
|
|
+
|
|
|
+def myunichchar(unicode_char):
|
|
|
+ mb_string = unicode_char.encode('big5')
|
|
|
+ try:
|
|
|
+ unicode_char = unichr(ord(mb_string[0]) << 8 | ord(mb_string[1]))
|
|
|
+ except NameError:
|
|
|
+ unicode_char = chr(mb_string[0] << 8 | mb_string[1])
|
|
|
+ return unicode_char
|
|
|
+
|
|
|
+
|
|
|
+def file_prepare(name, name_hash,text_content,image_urls):
|
|
|
+ #save image
|
|
|
+ try:
|
|
|
+ os.mkdir(dir_photo+name_hash)
|
|
|
+ except FileExistsError:
|
|
|
+ print("Directory " , dir_photo+name_hash , " already exists")
|
|
|
+ img_num = 1
|
|
|
+ for imgu in image_urls:
|
|
|
+ im = Image.open(requests.get(imgu, stream=True).raw)
|
|
|
+ im.save(dir_photo+name_hash+"/"+str(img_num)+".jpg")
|
|
|
+ img_num+=1
|
|
|
+ #save text
|
|
|
+ text_file = open(dir_text+name_hash+".txt", "w")
|
|
|
+ text_file.write(text_content)
|
|
|
+ text_file.close()
|
|
|
+ print("text file made")
|
|
|
+ #make mp3
|
|
|
+ language = 'zh-tw'
|
|
|
+ output = gTTS(text=text_content, lang=language, slow=False)
|
|
|
+ output.save(dir_sound+name_hash+".mp3")
|
|
|
+ print("mp3 file made")
|
|
|
+ #make title as image
|
|
|
+ txt2image(name, dir_title+name_hash+".png")
|
|
|
+
|
|
|
+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 downloadfile(name,url):
|
|
|
+ name=name+".mp4"
|
|
|
+
|
|
|
+def make_dir(name_hash):
|
|
|
+ #save image
|
|
|
+ try:
|
|
|
+ os.mkdir(dir_photo+name_hash)
|
|
|
+ except FileExistsError:
|
|
|
+ print("~~~~~~Warning~~~~~~~~~Directory " , dir_photo+name_hash , " already exists")
|
|
|
+ try:
|
|
|
+ os.mkdir(dir_text+name_hash)
|
|
|
+ except FileExistsError:
|
|
|
+ print("~~~~~~Warning~~~~~~~~~Directory " , dir_text+name_hash , " already exists")
|
|
|
+ try:
|
|
|
+ os.mkdir(dir_sound+name_hash)
|
|
|
+ except FileExistsError:
|
|
|
+ print("~~~~~~Warning~~~~~~~~~Directory " , dir_sound+name_hash , " already exists")
|
|
|
+ try:
|
|
|
+ os.mkdir(dir_video+name_hash)
|
|
|
+ except FileExistsError:
|
|
|
+ print("~~~~~~Warning~~~~~~~~~Directory " , dir_video+name_hash , " already exists")
|
|
|
+ try:
|
|
|
+ os.mkdir(dir_anchor+name_hash)
|
|
|
+ except FileExistsError:
|
|
|
+ print("~~~~~~Warning~~~~~~~~~Directory " , dir_anchor+name_hash , " already exists")
|
|
|
+ try:
|
|
|
+ os.mkdir(dir_subtitle+name_hash)
|
|
|
+ except FileExistsError:
|
|
|
+ print("~~~~~~Warning~~~~~~~~~Directory " , dir_subtitle+name_hash , " already exists")
|
|
|
+
|
|
|
+def file_prepare_v2(name, name_hash,text_content,image_urls):
|
|
|
+ make_dir(name_hash)
|
|
|
+ img_num = 1
|
|
|
+ for imgu in image_urls:
|
|
|
+ if get_url_type(imgu) =='video/mp4':
|
|
|
+ r=requests.get(imgu)
|
|
|
+ f=open(dir_photo+name_hash+"/"+str(img_num)+".mp4",'wb');
|
|
|
+ for chunk in r.iter_content(chunk_size=255):
|
|
|
+ if chunk:
|
|
|
+ f.write(chunk)
|
|
|
+ f.close()
|
|
|
+ else:
|
|
|
+ im = Image.open(requests.get(imgu, stream=True).raw)
|
|
|
+ im.save(dir_photo+name_hash+"/"+str(img_num)+".jpg")
|
|
|
+ img_num+=1
|
|
|
+ #save text
|
|
|
+ txt_idx=0
|
|
|
+ for txt in text_content:
|
|
|
+ text_file = open(dir_text+name_hash+"/"+str(txt_idx)+".txt", "w")
|
|
|
+ text_file.write(txt)
|
|
|
+ text_file.close()
|
|
|
+ txt_idx+=1
|
|
|
+ print("text file made")
|
|
|
+ #make mp3
|
|
|
+ language = 'zh-tw'
|
|
|
+ txt_idx = 0
|
|
|
+ for txt in text_content:
|
|
|
+ output = gTTS(text=txt, lang=language, slow=False)
|
|
|
+ output.save(dir_sound+name_hash+"/"+str(txt_idx)+".mp3")
|
|
|
+ txt_idx+=1
|
|
|
+ print("mp3 file made")
|
|
|
+ #make title as image
|
|
|
+ txt2image(name, dir_title+name_hash+".png")
|
|
|
+
|
|
|
+def txt2image(content, save_target):
|
|
|
+ unicode_text = content
|
|
|
+ font = ImageFont.truetype("font.ttf", 40,encoding='big5')
|
|
|
+ text_width, text_height = font.getsize(unicode_text)
|
|
|
+ canvas = Image.new('RGBA', (500, 500), (255, 0, 0, 0) )
|
|
|
+ draw = ImageDraw.Draw(canvas)
|
|
|
+ text=''
|
|
|
+ for c in unicode_text:
|
|
|
+ if len(re.findall(r'[\u4e00-\u9fff]+', c))>0:
|
|
|
+ text+=myunichchar(c)
|
|
|
+ else:
|
|
|
+ text+=c
|
|
|
+ draw.text((5,5), text, (255, 255, 255), font)
|
|
|
+ canvas.save(save_target, "PNG")
|
|
|
+
|
|
|
+def call_achor_video_v2(fileName):
|
|
|
+ conn = rpyc.classic.connect("192.168.1.105",18812)
|
|
|
+ ros = conn.modules.os
|
|
|
+ rsys = conn.modules.sys
|
|
|
+ fr=open(dir_sound+fileName+".mp3",'rb')# voice
|
|
|
+ #warning!!! file my be replaced by other process
|
|
|
+ fw=conn.builtins.open('/tmp/output.mp3','wb')
|
|
|
+
|
|
|
+ while True:
|
|
|
+ b=fr.read(1024)
|
|
|
+ if b:
|
|
|
+ fw.write(b)
|
|
|
+ else:
|
|
|
+ break
|
|
|
+
|
|
|
+ fr.close()
|
|
|
+ fw.close()
|
|
|
+
|
|
|
+ val=random.randint(1000000,9999999)
|
|
|
+ ros.chdir('/home/jared/to_video')
|
|
|
+ ros.system('./p6.sh '+str(val)+' &')
|
|
|
+
|
|
|
+ while True:
|
|
|
+ print('waiting...')
|
|
|
+ if ros.path.exists('/tmp/results/'+str(val)):
|
|
|
+ break
|
|
|
+ time.sleep(5)
|
|
|
+ print('waiting...')
|
|
|
+
|
|
|
+ fr=conn.builtins.open('/tmp/results/'+str(val)+'.mp4','rb')
|
|
|
+ fw=open(dir_anchor+fileName+".mp4",'wb')#peggy1_1
|
|
|
+ while True:
|
|
|
+ b=fr.read(1024)
|
|
|
+ if b:
|
|
|
+ fw.write(b)
|
|
|
+ else:
|
|
|
+ break
|
|
|
+
|
|
|
+ fr.close()
|
|
|
+ fw.close()
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+def call_achor_video(name):
|
|
|
+ conn = rpyc.classic.connect("192.168.1.105",18812)
|
|
|
+ ros = conn.modules.os
|
|
|
+ rsys = conn.modules.sys
|
|
|
+ fr=open(dir_sound+name+".mp3",'rb')# voice
|
|
|
+ #warning!!! file my be replaced by other process
|
|
|
+ fw=conn.builtins.open('/tmp/output.mp3','wb')
|
|
|
+
|
|
|
+ while True:
|
|
|
+ b=fr.read(1024)
|
|
|
+ if b:
|
|
|
+ fw.write(b)
|
|
|
+ else:
|
|
|
+ break
|
|
|
+
|
|
|
+ fr.close()
|
|
|
+ fw.close()
|
|
|
+
|
|
|
+ val=random.randint(1000000,9999999)
|
|
|
+ ros.chdir('/home/jared/to_video')
|
|
|
+ ros.system('./p6.sh '+str(val)+' &')
|
|
|
+
|
|
|
+ while True:
|
|
|
+ print('waiting...')
|
|
|
+ if ros.path.exists('/tmp/results/'+str(val)):
|
|
|
+ break
|
|
|
+ time.sleep(15)
|
|
|
+ print('waiting...')
|
|
|
+
|
|
|
+ fr=conn.builtins.open('/tmp/results/'+str(val)+'.mp4','rb')
|
|
|
+ fw=open(dir_anchor+name+'.mp4','wb')#peggy1_1
|
|
|
+ while True:
|
|
|
+ b=fr.read(1024)
|
|
|
+ if b:
|
|
|
+ fw.write(b)
|
|
|
+ else:
|
|
|
+ break
|
|
|
+
|
|
|
+ fr.close()
|
|
|
+ fw.close()
|
|
|
+
|
|
|
+ print('called............................................')
|
|
|
+
|
|
|
+
|
|
|
+def generate_subtitle_image(name_hash,text_content):
|
|
|
+ sub_len = 10
|
|
|
+ img_list = [None]*len(text_content)
|
|
|
+ for idx in range(len(text_content)):
|
|
|
+ img_list[idx] = []
|
|
|
+ for step in range(math.ceil(len(text_content[idx])/sub_len)):
|
|
|
+ sv_path = dir_subtitle + name_hash +'/'+str(idx)+ str(step) +'.png'
|
|
|
+ sub = text_content[idx][step*sub_len:step*sub_len+sub_len]
|
|
|
+ txt2image(sub, sv_path)
|
|
|
+ img_list[idx] += [{"count":len(sub),"path":sv_path}]
|
|
|
+ return img_list
|
|
|
+
|
|
|
+
|
|
|
+def anchor_video(name,text_content, image_urls):
|
|
|
+ m = hashlib.md5()
|
|
|
+ m.update(name.encode("utf-8"))
|
|
|
+ name_hash = m.hexdigest()
|
|
|
+
|
|
|
+ file_prepare(name, name_hash, text_content,image_urls)
|
|
|
+ call_achor_video(name_hash)
|
|
|
+
|
|
|
+ ck=cKey(0,254,0,150)
|
|
|
+ ck_anchor=cKey(0,255,1,320)
|
|
|
+ duration = 0
|
|
|
+ current_time = 0
|
|
|
+ current_time_photo = 0
|
|
|
+ #average layer level is 3
|
|
|
+ t = openshot.Timeline(1280, 720, openshot.Fraction(30000, 1000), 44100, 2, openshot.LAYOUT_STEREO)
|
|
|
+ t.Open()
|
|
|
+
|
|
|
+ bg_head = openshot.FFmpegReader(dir_video+"bg_head.avi")
|
|
|
+ bg_head.Open()
|
|
|
+ bg_head_clip = video_photo_clip(vid=bg_head,layer=2,position=current_time,end=bg_head.info.duration,ck=ck)
|
|
|
+ t.AddClip(bg_head_clip)
|
|
|
+
|
|
|
+ LOGO_OP = openshot.FFmpegReader(dir_video+"LOGO_OP.mp4")
|
|
|
+ LOGO_OP.Open() # Open the reader
|
|
|
+ LOGO_OP_clip = video_photo_clip(vid=LOGO_OP,layer=4,position=current_time,end=bg_head.info.duration
|
|
|
+ ,location_y=-0.03,scale_x=0.8,scale_y=0.71)
|
|
|
+ t.AddClip(LOGO_OP_clip)
|
|
|
+ duration+=bg_head.info.duration
|
|
|
+ current_time += bg_head.info.duration
|
|
|
+ current_time_photo += bg_head.info.duration
|
|
|
+
|
|
|
+ sound = openshot.FFmpegReader(dir_sound+name_hash+".mp3")
|
|
|
+ sound.Open()
|
|
|
+ sound_clip = openshot.Clip(sound)
|
|
|
+ sound_clip.Position(current_time)
|
|
|
+ t.AddClip(sound_clip)
|
|
|
+ duration += sound.info.duration
|
|
|
+
|
|
|
+ bg = openshot.FFmpegReader(dir_video+"bg.mp4")
|
|
|
+ bg.Open()
|
|
|
+ bg_times = math.floor(sound.info.duration/bg.info.duration)
|
|
|
+ left_time = sound.info.duration % bg.info.duration
|
|
|
+ bg_clip_list = [None] * bg_times
|
|
|
+ bg_list = [None] * bg_times
|
|
|
+ bg.Close()
|
|
|
+ for idx in range(bg_times):
|
|
|
+ bg_list[idx] = openshot.FFmpegReader(dir_video+"bg.mp4")
|
|
|
+ bg_list[idx].Open()
|
|
|
+ bg_clip_list[idx] = video_photo_clip(bg_list[idx],layer=2,position=current_time
|
|
|
+ ,end=bg_list[idx].info.duration,ck=ck)
|
|
|
+ t.AddClip(bg_clip_list[idx])
|
|
|
+ current_time += bg_list[idx].info.duration
|
|
|
+ bg_list[idx].Close()
|
|
|
+
|
|
|
+ bg_left = openshot.FFmpegReader(dir_video+"bg.mp4")
|
|
|
+ bg_left.Open()
|
|
|
+ bg_left_clip = video_photo_clip(bg_left,layer=2,position=current_time,end=left_time,ck=ck)
|
|
|
+ t.AddClip(bg_left_clip)
|
|
|
+ current_time += left_time
|
|
|
+ bg_left.Close()
|
|
|
+
|
|
|
+
|
|
|
+ p_num = len(listdir(dir_photo+name_hash))
|
|
|
+ photo_clip_list = [None]*p_num
|
|
|
+ img_list = [None]*p_num
|
|
|
+ photo_idx = 0
|
|
|
+ photo_duration = sound.info.duration/p_num
|
|
|
+ for p in listdir(dir_photo+name_hash):
|
|
|
+ img_list[photo_idx] = openshot.QtImageReader(dir_photo+name_hash+'/'+p)
|
|
|
+ photo_clip_list[photo_idx] = video_photo_clip(vid=img_list[photo_idx],layer=3
|
|
|
+ ,scale_x=0.81,scale_y=0.68,location_y=-0.03,position=current_time_photo,end=photo_duration
|
|
|
+ ,audio=False)
|
|
|
+ t.AddClip(photo_clip_list[photo_idx])
|
|
|
+ current_time_photo+=photo_duration
|
|
|
+ photo_idx+=1
|
|
|
+
|
|
|
+ current_time_anchor = bg_head.info.duration
|
|
|
+ anchor = openshot.FFmpegReader(dir_anchor+name_hash+".mp4")
|
|
|
+ anchor.Open()
|
|
|
+ anchor_times = math.floor(sound.info.duration/anchor.info.duration)
|
|
|
+ left_time = sound.info.duration % anchor.info.duration
|
|
|
+ anchor_clip_list = [None] * anchor_times
|
|
|
+ anchor_list = [None] * anchor_times
|
|
|
+ anchor.Close()
|
|
|
+ for idx in range(anchor_times):
|
|
|
+ anchor_list[idx] = openshot.FFmpegReader(dir_anchor+name_hash+".mp4")
|
|
|
+ anchor_list[idx].Open()
|
|
|
+ anchor_clip_list[idx] = video_photo_clip(vid=anchor_list[idx],layer=4,scale_x=0.65,scale_y=0.65,
|
|
|
+ location_x=0.35,location_y=0.25,position=current_time_anchor, end=anchor_list[idx].info.duration,
|
|
|
+ ck=ck_anchor,audio=False)
|
|
|
+ t.AddClip(anchor_clip_list[idx])
|
|
|
+ current_time_anchor += anchor_list[idx].info.duration
|
|
|
+ anchor_list[idx].Close()
|
|
|
+ anchor = openshot.FFmpegReader(dir_anchor+"peggy1_1.mp4")
|
|
|
+ anchor.Open()
|
|
|
+ anchor_left_clip = video_photo_clip(vid=anchor,layer=4,scale_x=0.65,scale_y=0.65,location_x=0.35,location_y=0.25
|
|
|
+ , position=current_time_anchor,end=left_time,ck=ck_anchor)
|
|
|
+ t.AddClip(anchor_left_clip)
|
|
|
+ anchor.Close()
|
|
|
+
|
|
|
+ title = openshot.QtImageReader(dir_title+name_hash+".png")
|
|
|
+ title.Open() # Open the reader
|
|
|
+ title_clip = video_photo_clip(vid=title, layer=4, location_y=0.9,position=0,end=duration)
|
|
|
+ t.AddClip(title_clip)
|
|
|
+
|
|
|
+ ####start building
|
|
|
+ w = openshot.FFmpegWriter("../html/"+name_hash+".mp4")
|
|
|
+ w.SetAudioOptions(True, "libmp3lame", 44100, 2, openshot.LAYOUT_STEREO, 3000000)
|
|
|
+ w.SetVideoOptions(True, "libx264", openshot.Fraction(30000, 1000), 1280, 720,
|
|
|
+ openshot.Fraction(1, 1), False, False, 3000000)
|
|
|
+ w.Open()
|
|
|
+
|
|
|
+ #may change duration into t.info.duration
|
|
|
+ for n in range(int(t.info.fps)*int(duration)):
|
|
|
+ f=t.GetFrame(n)
|
|
|
+ w.WriteFrame(f)
|
|
|
+
|
|
|
+ t.Close()
|
|
|
+ w.Close()
|
|
|
+ sound.Close()
|
|
|
+
|
|
|
+ print("It's fine")
|
|
|
+ notify_group(name+"的影片已經產生完成囉! www.choozmo.com:8168/"+name_hash+".mp4")
|
|
|
+
|
|
|
+
|
|
|
+def anchor_video_v2(name,text_content, image_urls):
|
|
|
+ m = hashlib.md5()
|
|
|
+ m.update(name.encode("utf-8"))
|
|
|
+ name_hash = m.hexdigest()
|
|
|
+
|
|
|
+ print('sub image made')
|
|
|
+ file_prepare_v2(name, name_hash, text_content,image_urls)
|
|
|
+ sub_list=generate_subtitle_image(name_hash,text_content)
|
|
|
+ for fname in range(len(text_content)):
|
|
|
+ call_achor_video_v2(name_hash+"/"+str(fname))
|
|
|
+ print('step finish')
|
|
|
+ print('called............................................')
|
|
|
+
|
|
|
+ ck=cKey(0,254,0,150)
|
|
|
+ ck_anchor=cKey(0,255,1,320)
|
|
|
+ duration = 0
|
|
|
+ #average layer level is 3
|
|
|
+ t = openshot.Timeline(1280, 720, openshot.Fraction(30000, 1000), 44100, 2, openshot.LAYOUT_STEREO)
|
|
|
+ t.Open()
|
|
|
+
|
|
|
+ main_timer = 0
|
|
|
+
|
|
|
+ LOGO_OP = openshot.FFmpegReader(dir_video+"LOGO_OP.mp4")
|
|
|
+ LOGO_OP.Open() # Open the reader
|
|
|
+ LOGO_OP_clip = video_photo_clip(vid=LOGO_OP,layer=4,position=0,end=LOGO_OP.info.duration
|
|
|
+ ,location_y=-0.03,scale_x=0.8,scale_y=0.71)
|
|
|
+ t.AddClip(LOGO_OP_clip)
|
|
|
+ bg_head = openshot.FFmpegReader(dir_video+"bg_head.avi")
|
|
|
+ bg_head.Open()
|
|
|
+ bg_head_clip = video_photo_clip(vid=bg_head,layer=2,position=0,end=LOGO_OP.info.duration,ck=ck)
|
|
|
+ t.AddClip(bg_head_clip)
|
|
|
+ main_timer += LOGO_OP.info.duration
|
|
|
+ head_duration = LOGO_OP.info.duration
|
|
|
+ bg_head.Close()
|
|
|
+ LOGO_OP.Close()
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ clip_duration=0
|
|
|
+ photo_clip_list = [None]*len(text_content)
|
|
|
+ img_list = [None]*len(text_content)
|
|
|
+ anchor_clip_list = [None] * len(text_content)
|
|
|
+ anchor_list = [None] * len(text_content)
|
|
|
+ audio_clip_list = [None] * len(text_content)
|
|
|
+ audio_list = [None] * len(text_content)
|
|
|
+ idx = 0
|
|
|
+ #mp4 also
|
|
|
+ for p in listdir(dir_photo+name_hash):
|
|
|
+
|
|
|
+ anchor_list[idx] = openshot.FFmpegReader(dir_anchor+name_hash+"/"+str(idx)+".mp4")
|
|
|
+ clip_duration = anchor_list[idx].info.duration-0.5
|
|
|
+ anchor_list[idx].Open()
|
|
|
+ anchor_clip_list[idx] = video_photo_clip(vid=anchor_list[idx],layer=4,scale_x=0.65,scale_y=0.65,
|
|
|
+ location_x=0.35,location_y=0.25,position=main_timer, end=clip_duration,ck=ck_anchor,audio=False)
|
|
|
+ t.AddClip(anchor_clip_list[idx])
|
|
|
+
|
|
|
+ img_list[idx] = openshot.FFmpegReader(dir_photo+name_hash+'/'+p)
|
|
|
+ img_list[idx].Open()
|
|
|
+ photo_clip_list[idx] = video_photo_clip(vid=img_list[idx],layer=3
|
|
|
+ ,scale_x=0.81,scale_y=0.68,location_y=-0.03,position=main_timer,end=clip_duration,audio=False)
|
|
|
+ t.AddClip(photo_clip_list[idx])
|
|
|
+ img_list[idx].Close()
|
|
|
+
|
|
|
+ audio_list[idx] = openshot.FFmpegReader(dir_sound+name_hash+"/"+str(idx)+".mp3")
|
|
|
+ audio_list[idx].Open()
|
|
|
+ audio_clip_list[idx] = openshot.Clip(audio_list[idx])
|
|
|
+ audio_clip_list[idx].Position(main_timer)
|
|
|
+ audio_clip_list[idx].End(clip_duration)
|
|
|
+ t.AddClip(audio_clip_list[idx])
|
|
|
+
|
|
|
+ img_list[idx].Close()
|
|
|
+ anchor_list[idx].Close()
|
|
|
+ audio_list[idx].Close()
|
|
|
+
|
|
|
+ for sub_idx in range(len(sub_list[idx])):
|
|
|
+ sub = openshot.QtImageReader(sub_list[idx][sub_idx]['path'])
|
|
|
+ sub.Open()
|
|
|
+ sub_duration = 0.3*sub_list[idx][sub_idx]['count']
|
|
|
+ sub_clip = video_photo_clip(vid=sub, layer=5, location_y=0.8,position=main_timer+sub_duration*sub_idx,end=sub_duration)
|
|
|
+ t.AddClip(sub_clip)
|
|
|
+
|
|
|
+ main_timer += clip_duration
|
|
|
+ idx+=1
|
|
|
+
|
|
|
+
|
|
|
+ LOGO_ED = openshot.FFmpegReader(dir_video+"LOGO_ED.avi")
|
|
|
+ LOGO_ED.Open()
|
|
|
+ LOGO_ED_clip = video_photo_clip(vid=LOGO_ED,layer=4,position=main_timer,end=LOGO_ED.info.duration
|
|
|
+ ,location_y=-0.03,scale_x=0.8,scale_y=0.71)
|
|
|
+ t.AddClip(LOGO_ED_clip)
|
|
|
+ ED_duration = LOGO_ED.info.duration
|
|
|
+ LOGO_ED.Close()
|
|
|
+
|
|
|
+
|
|
|
+ bg = openshot.FFmpegReader(dir_video+"bg.mp4")
|
|
|
+ bg.Open()
|
|
|
+ bg_times = math.floor(main_timer+ED_duration/bg.info.duration)
|
|
|
+ left_time = (main_timer+ED_duration) % bg.info.duration
|
|
|
+ bg_clip_list = [None] * bg_times
|
|
|
+ bg_list = [None] * bg_times
|
|
|
+ bg.Close()
|
|
|
+ bg_timer = head_duration
|
|
|
+ for idx in range(bg_times):
|
|
|
+ bg_list[idx] = openshot.FFmpegReader(dir_video+"bg.mp4")
|
|
|
+ bg_list[idx].Open()
|
|
|
+ bg_clip_list[idx] = video_photo_clip(bg_list[idx],layer=2,position=bg_timer
|
|
|
+ ,end=bg_list[idx].info.duration,ck=ck)
|
|
|
+ t.AddClip(bg_clip_list[idx])
|
|
|
+ bg_timer += bg_list[idx].info.duration
|
|
|
+ bg_list[idx].Close()
|
|
|
+ bg_left = openshot.FFmpegReader(dir_video+"bg.mp4")
|
|
|
+ bg_left.Open()
|
|
|
+ bg_left_clip = video_photo_clip(bg_left,layer=2,position=bg_timer,end=left_time,ck=ck)
|
|
|
+ t.AddClip(bg_left_clip)
|
|
|
+ bg_left.Close()
|
|
|
+
|
|
|
+ title = openshot.QtImageReader(dir_title+name_hash+".png")
|
|
|
+ title.Open() # Open the reader
|
|
|
+ title_clip = video_photo_clip(vid=title, layer=4, location_y=0.9,position=0,end=head_duration+main_timer)
|
|
|
+ t.AddClip(title_clip)
|
|
|
+
|
|
|
+ ####start building
|
|
|
+ w = openshot.FFmpegWriter("../html/"+name_hash+".mp4")
|
|
|
+ w.SetAudioOptions(True, "libmp3lame", 44100, 2, openshot.LAYOUT_STEREO, 3000000)
|
|
|
+ w.SetVideoOptions(True, "libx264", openshot.Fraction(30000, 1000), 1280, 720,
|
|
|
+ openshot.Fraction(1, 1), False, False, 3000000)
|
|
|
+ w.Open()
|
|
|
+
|
|
|
+ #may change duration into t.info.duration
|
|
|
+ for n in range(int(t.info.fps)*int(head_duration+main_timer+ED_duration)):
|
|
|
+ f=t.GetFrame(n)
|
|
|
+ w.WriteFrame(f)
|
|
|
+
|
|
|
+ t.Close()
|
|
|
+ w.Close()
|
|
|
+ print("Raw Video done")
|
|
|
+ print("video at : www.choozmo.com:8168/"+name_hash+".mp4")
|
|
|
+
|
|
|
+ #notify_group(name+"的影片已經產生完成囉! www.choozmo.com:8168/"+name_hash+".mp4")
|
|
|
+
|
|
|
+
|
|
|
+
|