main.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  1. from fastapi import FastAPI,Cookie, Depends, FastAPI, Query, WebSocket, status
  2. import openshot
  3. from os import listdir
  4. from os.path import isfile, isdir, join
  5. import threading
  6. import zhtts
  7. import os
  8. import urllib
  9. from typing import List
  10. import requests
  11. from pydantic import BaseModel
  12. from bs4 import BeautifulSoup
  13. import time
  14. from PIL import Image,ImageDraw,ImageFont
  15. import pyttsx3
  16. import rpyc
  17. import random
  18. import time
  19. import math
  20. import hashlib
  21. import re
  22. import urllib.request
  23. from fastapi.responses import FileResponse
  24. #service nginx restart
  25. #uvicorn main:app --host="0.0.0.0" --reload --port 8888
  26. app = FastAPI()
  27. dir_sound = 'mp3_track/'
  28. dir_photo = 'photo/'
  29. dir_text = 'text_file/'
  30. dir_video = 'video_material/'
  31. dir_title = 'title/'
  32. dir_subtitle = 'subtitle/'
  33. dir_anchor = 'anchor_raw/'
  34. class request(BaseModel):
  35. name: str
  36. text_content: str
  37. image_urls: List[str]
  38. class QQ(BaseModel):
  39. n1: str
  40. n2: str
  41. class request2(BaseModel):
  42. name: str
  43. text_content: List[str]
  44. image_urls: List[str]
  45. class anchor_request(BaseModel):
  46. name: str
  47. text_content: str
  48. image_urls: List[str]
  49. @app.get("/")
  50. async def root():
  51. return {"message": "Hello, this is index"}
  52. @app.get("/index2")
  53. async def index2():
  54. return FileResponse('index2.html')
  55. @app.get("/script_msg.js")
  56. async def index2():
  57. return FileResponse('script_msg.js')
  58. @app.get("/style.css")
  59. async def index2():
  60. return FileResponse('style.css')
  61. @app.post("/qqreq")
  62. async def qqreq(qq:QQ):
  63. print(qq.n1)
  64. print(qq.n2)
  65. return {"msg":"製作影片需要時間,請您耐心等候"}
  66. @app.post("/make_anchor_video_v2")
  67. async def make_anchor_video_v2(req:request2):
  68. x = threading.Thread(target=anchor_video_v2, args=(req.name, req.text_content, req.image_urls))
  69. x.start()
  70. return {"msg":"製作影片需要時間,請您耐心等候 稍後可以在www.choozmo.com:8168/"+req.name+".mp4 中觀看"}
  71. @app.post("/make_anchor_video_v3")
  72. async def make_anchor_video_v3(req:request2):
  73. x = threading.Thread(target=anchor_video_v3, args=(req.name, req.text_content, req.image_urls))
  74. x.start()
  75. return {"msg":"製作影片需要時間,請您耐心等候 稍後可以在www.choozmo.com:8168/"+req.name+".mp4 中觀看"}
  76. def notify_group(msg):
  77. headers = {
  78. "Authorization": "Bearer " + "WekCRfnAirSiSxALiD6gcm0B56EejsoK89zFbIaiZQD",
  79. "Content-Type": "application/x-www-form-urlencoded"
  80. }
  81. params = {"message": msg}
  82. r = requests.post("https://notify-api.line.me/api/notify",headers=headers, params=params)
  83. #print(r)
  84. def cKey(r,g,b,fuzz):
  85. col=openshot.Color()
  86. col.red=openshot.Keyframe(r)
  87. col.green=openshot.Keyframe(g)
  88. col.blue=openshot.Keyframe(b)
  89. return openshot.ChromaKey(col, openshot.Keyframe(fuzz))
  90. def video_photo_clip(vid=None,layer=None, position=None, end=None
  91. ,scale_x=1,scale_y=1,location_x=0,location_y=0,ck=None,audio=True):
  92. clip = openshot.Clip(vid)
  93. clip.Layer(layer)
  94. clip.Position(position)
  95. clip.End(end)
  96. clip.scale_x=openshot.Keyframe(scale_x)
  97. clip.scale_y=openshot.Keyframe(scale_y)
  98. clip.location_x=openshot.Keyframe(location_x)
  99. clip.location_y=openshot.Keyframe(location_y)
  100. if ck!=None:
  101. clip.AddEffect(ck)
  102. if audio==True:
  103. clip.has_audio=openshot.Keyframe(1)
  104. else:
  105. clip.has_audio=openshot.Keyframe(0)
  106. return clip
  107. def myunichchar(unicode_char):
  108. mb_string = unicode_char.encode('big5')
  109. try:
  110. unicode_char = unichr(ord(mb_string[0]) << 8 | ord(mb_string[1]))
  111. except NameError:
  112. unicode_char = chr(mb_string[0] << 8 | mb_string[1])
  113. return unicode_char
  114. def file_prepare(name, name_hash,text_content,image_urls):
  115. #save image
  116. try:
  117. os.mkdir(dir_photo+name_hash)
  118. except FileExistsError:
  119. print("Directory " , dir_photo+name_hash , " already exists")
  120. img_num = 1
  121. for imgu in image_urls:
  122. im = Image.open(requests.get(imgu, stream=True).raw)
  123. im.save(dir_photo+name_hash+"/"+str(img_num)+".jpg")
  124. img_num+=1
  125. #save text
  126. text_file = open(dir_text+name_hash+".txt", "w")
  127. text_file.write(text_content)
  128. text_file.close()
  129. print("text file made")
  130. #make mp3
  131. tts = zhtts.TTS()
  132. tts.text2wav(text_content,dir_sound+name_hash+".mp3")
  133. print("mp3 file made")
  134. #make title as image
  135. txt2image(name, dir_title+name_hash+".png")
  136. def get_url_type(url):
  137. req = urllib.request.Request(url, method='HEAD', headers={'User-Agent': 'Mozilla/5.0'})
  138. r = urllib.request.urlopen(req)
  139. contentType = r.getheader('Content-Type')
  140. return contentType
  141. def downloadfile(name,url):
  142. name=name+".mp4"
  143. def make_dir(name_hash):
  144. #save image
  145. try:
  146. os.mkdir(dir_photo+name_hash)
  147. except FileExistsError:
  148. print("~~~~~~Warning~~~~~~~~~Directory " , dir_photo+name_hash , " already exists")
  149. try:
  150. os.mkdir(dir_text+name_hash)
  151. except FileExistsError:
  152. print("~~~~~~Warning~~~~~~~~~Directory " , dir_text+name_hash , " already exists")
  153. try:
  154. os.mkdir(dir_sound+name_hash)
  155. except FileExistsError:
  156. print("~~~~~~Warning~~~~~~~~~Directory " , dir_sound+name_hash , " already exists")
  157. try:
  158. os.mkdir(dir_video+name_hash)
  159. except FileExistsError:
  160. print("~~~~~~Warning~~~~~~~~~Directory " , dir_video+name_hash , " already exists")
  161. try:
  162. os.mkdir(dir_anchor+name_hash)
  163. except FileExistsError:
  164. print("~~~~~~Warning~~~~~~~~~Directory " , dir_anchor+name_hash , " already exists")
  165. try:
  166. os.mkdir(dir_subtitle+name_hash)
  167. except FileExistsError:
  168. print("~~~~~~Warning~~~~~~~~~Directory " , dir_subtitle+name_hash , " already exists")
  169. def file_prepare_v2(name, name_hash,text_content,image_urls):
  170. make_dir(name_hash)
  171. img_num = 1
  172. for imgu in image_urls:
  173. if get_url_type(imgu) =='video/mp4':
  174. r=requests.get(imgu)
  175. f=open(dir_photo+name_hash+"/"+str(img_num)+".mp4",'wb')
  176. for chunk in r.iter_content(chunk_size=255):
  177. if chunk:
  178. f.write(chunk)
  179. f.close()
  180. else:
  181. im = Image.open(requests.get(imgu, stream=True).raw)
  182. im= im.convert("RGB")
  183. im.save(dir_photo+name_hash+"/"+str(img_num)+".jpg")
  184. img_num+=1
  185. #save text
  186. txt_idx=0
  187. for txt in text_content:
  188. text_file = open(dir_text+name_hash+"/"+str(txt_idx)+".txt", "w")
  189. text_file.write(txt)
  190. text_file.close()
  191. txt_idx+=1
  192. print("text file made")
  193. #make mp3
  194. language = 'zh-tw'
  195. txt_idx = 0
  196. for txt in text_content:
  197. tts = zhtts.TTS()
  198. tts.text2wav(txt,dir_sound+name_hash+"/"+str(txt_idx)+".mp3")
  199. txt_idx+=1
  200. print("mp3 file made")
  201. #make title as image
  202. txt2image_title(name, dir_title+name_hash+".png")
  203. def txt2image(content, save_target):
  204. unicode_text = trim_punctuation(content)
  205. font = ImageFont.truetype(font="DFT_B7.ttc", size=38)
  206. text_width, text_height = font.getsize(unicode_text)
  207. canvas = Image.new('RGBA', (700, 500), (255, 0, 0, 0) )
  208. draw = ImageDraw.Draw(canvas)
  209. text= unicode_text
  210. draw.text((5,5), text, (255, 255, 0), font)
  211. canvas.save(save_target, "PNG")
  212. def txt2image_title(content, save_target):
  213. unicode_text = trim_punctuation(content)
  214. font = ImageFont.truetype(font="DFT_B7.ttc", size=28)
  215. text_width, text_height = font.getsize(unicode_text)
  216. canvas = Image.new('RGBA', (510, 500), (255, 0, 0, 0) )
  217. draw = ImageDraw.Draw(canvas)
  218. text= unicode_text
  219. draw.text((5,5), text, (17, 41, 167), font)
  220. canvas.save(save_target, "PNG")
  221. '''
  222. def txt2image_title(content, save_target):
  223. unicode_text =content
  224. font = ImageFont.truetype("font.ttf", 23,encoding='big5')
  225. text_width, text_height = font.getsize(unicode_text)
  226. canvas = Image.new('RGBA', (500, 500), (255, 0, 0, 0) )
  227. draw = ImageDraw.Draw(canvas)
  228. text=''
  229. for c in unicode_text:
  230. if len(re.findall(r'[\u4e00-\u9fff]+', c))>0:
  231. text+=myunichchar(c)
  232. else:
  233. text+=c
  234. draw.text((5,5), text, (17, 41, 167), font)
  235. canvas.save(save_target, "PNG")
  236. '''
  237. def call_achor_video_v2(fileName):
  238. conn = rpyc.classic.connect("192.168.1.105",18812)
  239. ros = conn.modules.os
  240. rsys = conn.modules.sys
  241. fr=open(dir_sound+fileName+".mp3",'rb')# voice
  242. #warning!!! file my be replaced by other process
  243. fw=conn.builtins.open('/tmp/output.mp3','wb')
  244. while True:
  245. b=fr.read(1024)
  246. if b:
  247. fw.write(b)
  248. else:
  249. break
  250. fr.close()
  251. fw.close()
  252. val=random.randint(1000000,9999999)
  253. ros.chdir('/home/jared/to_video')
  254. ros.system('./p6.sh '+str(val)+' &')
  255. while True:
  256. print('waiting...')
  257. if ros.path.exists('/tmp/results/'+str(val)):
  258. break
  259. time.sleep(5)
  260. print('waiting...')
  261. fr=conn.builtins.open('/tmp/results/'+str(val)+'.mp4','rb')
  262. fw=open(dir_anchor+fileName+".mp4",'wb')#peggy1_1
  263. while True:
  264. b=fr.read(1024)
  265. if b:
  266. fw.write(b)
  267. else:
  268. break
  269. fr.close()
  270. fw.close()
  271. def call_achor_video(name):
  272. conn = rpyc.classic.connect("192.168.1.105",18812)
  273. ros = conn.modules.os
  274. rsys = conn.modules.sys
  275. fr=open(dir_sound+name+".mp3",'rb')# voice
  276. #warning!!! file my be replaced by other process
  277. fw=conn.builtins.open('/tmp/output.mp3','wb')
  278. while True:
  279. b=fr.read(1024)
  280. if b:
  281. fw.write(b)
  282. else:
  283. break
  284. fr.close()
  285. fw.close()
  286. val=random.randint(1000000,9999999)
  287. ros.chdir('/home/jared/to_video')
  288. ros.system('./p6.sh '+str(val)+' &')
  289. while True:
  290. print('waiting...')
  291. if ros.path.exists('/tmp/results/'+str(val)):
  292. break
  293. time.sleep(15)
  294. print('waiting...')
  295. fr=conn.builtins.open('/tmp/results/'+str(val)+'.mp4','rb')
  296. fw=open(dir_anchor+name+'.mp4','wb')#peggy1_1
  297. while True:
  298. b=fr.read(1024)
  299. if b:
  300. fw.write(b)
  301. else:
  302. break
  303. fr.close()
  304. fw.close()
  305. print('called..............................................')
  306. def trim_punctuation(s):
  307. pat_block = u'[^\u4e00-\u9fff0-9a-zA-Z]+';
  308. pattern = u'([0-9]+{0}[0-9]+)|{0}'.format(pat_block)
  309. res = re.sub(pattern, lambda x: x.group(1) if x.group(1) else u"" ,s)
  310. return res
  311. def splitter(s):
  312. for sent in re.findall(u'[^!?,。\!\?]+[!?。\!\?]?', s, flags=re.U):
  313. yield sent
  314. def split_by_pun(s):
  315. res = list(splitter(s))
  316. return res
  317. def generate_subtitle_image(name_hash,text_content):
  318. img_list = [None]*len(text_content)
  319. for idx in range(len(text_content)):
  320. img_list[idx]=[]
  321. senList = split_by_pun(text_content[idx])
  322. for inner_idx in range(len(senList)):
  323. sv_path = dir_subtitle + name_hash +'/'+str(idx)+ str(inner_idx) +'.png'
  324. sub = senList[inner_idx]
  325. txt2image(sub,sv_path)
  326. img_list[idx]+=[{"count":len(sub),"path":sv_path}]
  327. return img_list
  328. def anchor_video_v2(name,text_content, image_urls):
  329. m = hashlib.md5()
  330. m.update(name.encode("utf-8"))
  331. name_hash = m.hexdigest()
  332. print('sub image made')
  333. file_prepare_v2(name, name_hash, text_content,image_urls)
  334. sub_list=generate_subtitle_image(name_hash,text_content)
  335. for fname in range(len(text_content)):
  336. call_achor_video_v2(name_hash+"/"+str(fname))
  337. print('step finish')
  338. print('called............................................')
  339. ck=cKey(0,254,0,150)
  340. ck_anchor=cKey(0,255,1,320)
  341. duration = 0
  342. #average layer level is 3
  343. t = openshot.Timeline(1280, 720, openshot.Fraction(30000, 1000), 44100, 2, openshot.LAYOUT_STEREO)
  344. t.Open()
  345. main_timer = 0
  346. LOGO_OP = openshot.FFmpegReader(dir_video+"LOGO_OP.mp4")
  347. LOGO_OP.Open() # Open the reader
  348. LOGO_OP_clip = video_photo_clip(vid=LOGO_OP,layer=4,position=0,end=LOGO_OP.info.duration
  349. ,location_y=-0.03,scale_x=0.8,scale_y=0.71)
  350. t.AddClip(LOGO_OP_clip)
  351. bg_head = openshot.FFmpegReader(dir_video+"bg_head.avi")
  352. bg_head.Open()
  353. bg_head_clip = video_photo_clip(vid=bg_head,layer=2,position=0,end=LOGO_OP.info.duration,ck=ck)
  354. t.AddClip(bg_head_clip)
  355. main_timer += LOGO_OP.info.duration
  356. head_duration = LOGO_OP.info.duration
  357. bg_head.Close()
  358. LOGO_OP.Close()
  359. clip_duration=0
  360. photo_clip_list = [None]*len(text_content)
  361. img_list = [None]*len(text_content)
  362. anchor_clip_list = [None] * len(text_content)
  363. anchor_list = [None] * len(text_content)
  364. audio_clip_list = [None] * len(text_content)
  365. audio_list = [None] * len(text_content)
  366. sub_clip_list = [None] * len(text_content)
  367. sub_img_list = [None] * len(text_content)
  368. idx = 0
  369. for p in listdir(dir_photo+name_hash):
  370. anchor_list[idx] = openshot.FFmpegReader(dir_anchor+name_hash+"/"+str(idx)+".mp4")
  371. clip_duration = anchor_list[idx].info.duration
  372. anchor_list[idx].Open()
  373. anchor_clip_list[idx] = video_photo_clip(vid=anchor_list[idx],layer=4,scale_x=0.65,scale_y=0.65,
  374. location_x=0.35,location_y=0.25,position=main_timer, end=clip_duration,ck=ck_anchor,audio=False)
  375. t.AddClip(anchor_clip_list[idx])
  376. img_list[idx] = openshot.FFmpegReader(dir_photo+name_hash+'/'+p)
  377. img_list[idx].Open()
  378. photo_clip_list[idx] = video_photo_clip(vid=img_list[idx],layer=3
  379. ,scale_x=0.81,scale_y=0.68,location_y=-0.03,position=main_timer,end=clip_duration,audio=False)
  380. t.AddClip(photo_clip_list[idx])
  381. img_list[idx].Close()
  382. audio_list[idx] = openshot.FFmpegReader(dir_sound+name_hash+"/"+str(idx)+".mp3")
  383. audio_list[idx].Open()
  384. audio_clip_list[idx] = openshot.Clip(audio_list[idx])
  385. audio_clip_list[idx].Position(main_timer)
  386. audio_clip_list[idx].End(clip_duration)
  387. t.AddClip(audio_clip_list[idx])
  388. img_list[idx].Close()
  389. anchor_list[idx].Close()
  390. audio_list[idx].Close()
  391. sub_img_list[idx] = [None] * len(sub_list[idx])
  392. sub_clip_list[idx] = [None] * len(sub_list[idx])
  393. sub_timer = 0
  394. for sub_idx in range(len(sub_list[idx])):
  395. sub_img_list[idx][sub_idx] = openshot.QtImageReader(sub_list[idx][sub_idx]['path'])
  396. sub_img_list[idx][sub_idx].Open()
  397. sub_duration = 0.205*sub_list[idx][sub_idx]['count']
  398. sub_clip_list[idx][sub_idx] = video_photo_clip(vid=sub_img_list[idx][sub_idx], layer=6,location_x=0.069, location_y=0.89,position=main_timer+sub_timer,end=sub_duration)
  399. t.AddClip(sub_clip_list[idx][sub_idx])
  400. sub_img_list[idx][sub_idx].Close()
  401. sub_timer += sub_duration
  402. print(sub_list[idx][sub_idx]['path'])
  403. main_timer += clip_duration
  404. idx+=1
  405. LOGO_ED = openshot.FFmpegReader(dir_video+"LOGO_ED.avi")
  406. LOGO_ED.Open()
  407. LOGO_ED_clip = video_photo_clip(vid=LOGO_ED,layer=4,position=main_timer,end=LOGO_ED.info.duration
  408. ,location_y=-0.03,scale_x=0.8,scale_y=0.71)
  409. t.AddClip(LOGO_ED_clip)
  410. ED_duration = LOGO_ED.info.duration
  411. LOGO_ED.Close()
  412. bg = openshot.FFmpegReader(dir_video+"bg.mp4")
  413. bg.Open()
  414. bg_times = math.floor(main_timer+ED_duration/bg.info.duration)
  415. left_time = (main_timer+ED_duration) % bg.info.duration
  416. bg_clip_list = [None] * bg_times
  417. bg_list = [None] * bg_times
  418. bg.Close()
  419. bg_timer = head_duration
  420. for idx in range(bg_times):
  421. bg_list[idx] = openshot.FFmpegReader(dir_video+"bg.mp4")
  422. bg_list[idx].Open()
  423. bg_clip_list[idx] = video_photo_clip(bg_list[idx],layer=2,position=bg_timer
  424. ,end=bg_list[idx].info.duration,ck=ck)
  425. t.AddClip(bg_clip_list[idx])
  426. bg_timer += bg_list[idx].info.duration
  427. bg_list[idx].Close()
  428. bg_left = openshot.FFmpegReader(dir_video+"bg.mp4")
  429. bg_left.Open()
  430. bg_left_clip = video_photo_clip(bg_left,layer=2,position=bg_timer,end=left_time,ck=ck)
  431. t.AddClip(bg_left_clip)
  432. bg_left.Close()
  433. title = openshot.QtImageReader(dir_title+name_hash+".png")
  434. title.Open() # Open the reader
  435. title_clip = video_photo_clip(vid=title, layer=4,location_x=-0.047, location_y=0.801,position=0,end=head_duration+main_timer)
  436. t.AddClip(title_clip)
  437. ####start building
  438. w = openshot.FFmpegWriter("../html/"+name_hash+".mp4")
  439. w.SetAudioOptions(True, "libmp3lame", 44100, 2, openshot.LAYOUT_STEREO, 3000000)
  440. w.SetVideoOptions(True, "libx264", openshot.Fraction(30000, 1000), 1280, 720,
  441. openshot.Fraction(1, 1), False, False, 3000000)
  442. w.Open()
  443. #may change duration into t.info.duration
  444. for n in range(int(t.info.fps)*int(head_duration+main_timer+ED_duration)):
  445. f=t.GetFrame(n)
  446. w.WriteFrame(f)
  447. t.Close()
  448. w.Close()
  449. print("Raw Video done")
  450. print("video at : www.choozmo.com:8168/"+name_hash+".mp4")
  451. #line notifs
  452. notify_group(name+"的影片已經產生完成囉! www.choozmo.com:8168/"+name_hash+".mp4")
  453. ##test func
  454. def anchor_video_v3(name,text_content, image_urls):
  455. m = hashlib.md5()
  456. m.update(name.encode("utf-8"))
  457. name_hash = m.hexdigest()
  458. print('sub image made')
  459. file_prepare_v2(name, name_hash, text_content,image_urls)
  460. sub_list=generate_subtitle_image(name_hash,text_content)
  461. for fname in range(len(text_content)):
  462. call_achor_video_v2(name_hash+"/"+str(fname))
  463. print('step finish')
  464. print('called............................................')
  465. ck=cKey(0,254,0,150)
  466. ck_anchor=cKey(0,255,1,320)
  467. duration = 0
  468. #average layer level is 3
  469. t = openshot.Timeline(1280, 720, openshot.Fraction(30000, 1000), 44100, 2, openshot.LAYOUT_STEREO)
  470. t.Open()
  471. main_timer = 0
  472. LOGO_OP = openshot.FFmpegReader(dir_video+"LOGO_OP.mp4")
  473. LOGO_OP.Open() # Open the reader
  474. LOGO_OP_clip = video_photo_clip(vid=LOGO_OP,layer=4,position=0,end=LOGO_OP.info.duration
  475. ,location_y=-0.03,scale_x=0.8,scale_y=0.71)
  476. t.AddClip(LOGO_OP_clip)
  477. bg_head = openshot.FFmpegReader(dir_video+"bg_head.avi")
  478. bg_head.Open()
  479. bg_head_clip = video_photo_clip(vid=bg_head,layer=2,position=0,end=LOGO_OP.info.duration,ck=ck)
  480. t.AddClip(bg_head_clip)
  481. main_timer += LOGO_OP.info.duration
  482. head_duration = LOGO_OP.info.duration
  483. bg_head.Close()
  484. LOGO_OP.Close()
  485. clip_duration=0
  486. photo_clip_list = [None]*len(text_content)
  487. img_list = [None]*len(text_content)
  488. anchor_clip_list = [None] * len(text_content)
  489. anchor_list = [None] * len(text_content)
  490. audio_clip_list = [None] * len(text_content)
  491. audio_list = [None] * len(text_content)
  492. sub_clip_list = [None] * len(text_content)
  493. sub_img_list = [None] * len(text_content)
  494. idx = 0
  495. for p in listdir(dir_photo+name_hash):
  496. anchor_list[idx] = openshot.FFmpegReader(dir_anchor+name_hash+"/"+str(idx)+".mp4")
  497. clip_duration = anchor_list[idx].info.duration
  498. anchor_list[idx].Open()
  499. anchor_clip_list[idx] = video_photo_clip(vid=anchor_list[idx],layer=4,scale_x=0.65,scale_y=0.65,
  500. location_x=0.35,location_y=0.25,position=main_timer, end=clip_duration,ck=ck_anchor,audio=False)
  501. t.AddClip(anchor_clip_list[idx])
  502. img_list[idx] = openshot.FFmpegReader(dir_photo+name_hash+'/'+p)
  503. img_list[idx].Open()
  504. photo_clip_list[idx] = video_photo_clip(vid=img_list[idx],layer=3
  505. ,scale_x=0.81,scale_y=0.68,location_y=-0.03,position=main_timer,end=clip_duration,audio=False)
  506. t.AddClip(photo_clip_list[idx])
  507. img_list[idx].Close()
  508. audio_list[idx] = openshot.FFmpegReader(dir_sound+name_hash+"/"+str(idx)+".mp3")
  509. audio_list[idx].Open()
  510. audio_clip_list[idx] = openshot.Clip(audio_list[idx])
  511. audio_clip_list[idx].Position(main_timer)
  512. audio_clip_list[idx].End(clip_duration)
  513. t.AddClip(audio_clip_list[idx])
  514. img_list[idx].Close()
  515. anchor_list[idx].Close()
  516. audio_list[idx].Close()
  517. sub_img_list[idx] = [None] * len(sub_list[idx])
  518. sub_clip_list[idx] = [None] * len(sub_list[idx])
  519. sub_timer = 0
  520. for sub_idx in range(len(sub_list[idx])):
  521. sub_img_list[idx][sub_idx] = openshot.QtImageReader(sub_list[idx][sub_idx]['path'])
  522. sub_img_list[idx][sub_idx].Open()
  523. sub_duration = 0.205*sub_list[idx][sub_idx]['count']
  524. sub_clip_list[idx][sub_idx] = video_photo_clip(vid=sub_img_list[idx][sub_idx], layer=6,location_x=0.069, location_y=0.89,position=main_timer+sub_timer,end=sub_duration)
  525. t.AddClip(sub_clip_list[idx][sub_idx])
  526. sub_img_list[idx][sub_idx].Close()
  527. sub_timer += sub_duration
  528. print(sub_list[idx][sub_idx]['path'])
  529. main_timer += clip_duration
  530. idx+=1
  531. LOGO_ED = openshot.FFmpegReader(dir_video+"LOGO_ED.avi")
  532. LOGO_ED.Open()
  533. LOGO_ED_clip = video_photo_clip(vid=LOGO_ED,layer=4,position=main_timer,end=LOGO_ED.info.duration
  534. ,location_y=-0.03,scale_x=0.8,scale_y=0.71)
  535. t.AddClip(LOGO_ED_clip)
  536. ED_duration = LOGO_ED.info.duration
  537. LOGO_ED.Close()
  538. bg = openshot.FFmpegReader(dir_video+"bg.mp4")
  539. bg.Open()
  540. bg_times = math.floor(main_timer+ED_duration/bg.info.duration)
  541. left_time = (main_timer+ED_duration) % bg.info.duration
  542. bg_clip_list = [None] * bg_times
  543. bg_list = [None] * bg_times
  544. bg.Close()
  545. bg_timer = head_duration
  546. for idx in range(bg_times):
  547. bg_list[idx] = openshot.FFmpegReader(dir_video+"bg.mp4")
  548. bg_list[idx].Open()
  549. bg_clip_list[idx] = video_photo_clip(bg_list[idx],layer=2,position=bg_timer
  550. ,end=bg_list[idx].info.duration,ck=ck)
  551. t.AddClip(bg_clip_list[idx])
  552. bg_timer += bg_list[idx].info.duration
  553. bg_list[idx].Close()
  554. bg_left = openshot.FFmpegReader(dir_video+"bg.mp4")
  555. bg_left.Open()
  556. bg_left_clip = video_photo_clip(bg_left,layer=2,position=bg_timer,end=left_time,ck=ck)
  557. t.AddClip(bg_left_clip)
  558. bg_left.Close()
  559. title = openshot.QtImageReader(dir_title+name_hash+".png")
  560. title.Open() # Open the reader
  561. title_clip = video_photo_clip(vid=title, layer=4,location_x=-0.047, location_y=0.801,position=0,end=head_duration+main_timer)
  562. t.AddClip(title_clip)
  563. ####start building
  564. w = openshot.FFmpegWriter("../html/"+name_hash+".mp4")
  565. w.SetAudioOptions(True, "libfaac", 44100, 2, openshot.LAYOUT_STEREO, 3000000)
  566. w.SetVideoOptions(True, "libx264", openshot.Fraction(30000, 1000), 1280, 720,
  567. openshot.Fraction(1, 1), False, False, 3000000)
  568. w.Open()
  569. #may change duration into t.info.duration
  570. for n in range(int(t.info.fps)*int(head_duration+main_timer+ED_duration)):
  571. f=t.GetFrame(n)
  572. w.WriteFrame(f)
  573. t.Close()
  574. w.Close()
  575. print("Raw Video done")
  576. print("video at : www.choozmo.com:8168/"+name_hash+".mp4")
  577. #line notifs
  578. #notify_group(name+"的影片已經產生完成囉! www.choozmo.com:8168/"+name_hash+".mp4")