main.py 23 KB

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