main.py 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711
  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_title(name, dir_title+name_hash+".png")
  264. def txt2image(content, save_target):
  265. unicode_text = content
  266. font = ImageFont.truetype(font="msjh.ttf", size=26)
  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= content
  271. '''
  272. for c in unicode_text:
  273. if len(re.findall(r'[\u4e00-\u9fff]+', c))>0:
  274. text+=myunichchar(c)
  275. else:
  276. text+=c
  277. '''
  278. draw.text((5,5), text, (255, 255, 255), font)
  279. canvas.save(save_target, "PNG")
  280. def txt2image_title(content, save_target):
  281. unicode_text = content
  282. font = ImageFont.truetype("font.ttf", 40,encoding='big5')
  283. text_width, text_height = font.getsize(unicode_text)
  284. canvas = Image.new('RGBA', (500, 500), (255, 0, 0, 0) )
  285. draw = ImageDraw.Draw(canvas)
  286. text=''
  287. for c in unicode_text:
  288. if len(re.findall(r'[\u4e00-\u9fff]+', c))>0:
  289. text+=myunichchar(c)
  290. else:
  291. text+=c
  292. draw.text((5,5), text, (0, 0, 0), font)
  293. canvas.save(save_target, "PNG")
  294. def call_achor_video_v2(fileName):
  295. conn = rpyc.classic.connect("192.168.1.105",18812)
  296. ros = conn.modules.os
  297. rsys = conn.modules.sys
  298. fr=open(dir_sound+fileName+".mp3",'rb')# voice
  299. #warning!!! file my be replaced by other process
  300. fw=conn.builtins.open('/tmp/output.mp3','wb')
  301. while True:
  302. b=fr.read(1024)
  303. if b:
  304. fw.write(b)
  305. else:
  306. break
  307. fr.close()
  308. fw.close()
  309. val=random.randint(1000000,9999999)
  310. ros.chdir('/home/jared/to_video')
  311. ros.system('./p6.sh '+str(val)+' &')
  312. while True:
  313. print('waiting...')
  314. if ros.path.exists('/tmp/results/'+str(val)):
  315. break
  316. time.sleep(5)
  317. print('waiting...')
  318. fr=conn.builtins.open('/tmp/results/'+str(val)+'.mp4','rb')
  319. fw=open(dir_anchor+fileName+".mp4",'wb')#peggy1_1
  320. while True:
  321. b=fr.read(1024)
  322. if b:
  323. fw.write(b)
  324. else:
  325. break
  326. fr.close()
  327. fw.close()
  328. def call_achor_video(name):
  329. conn = rpyc.classic.connect("192.168.1.105",18812)
  330. ros = conn.modules.os
  331. rsys = conn.modules.sys
  332. fr=open(dir_sound+name+".mp3",'rb')# voice
  333. #warning!!! file my be replaced by other process
  334. fw=conn.builtins.open('/tmp/output.mp3','wb')
  335. while True:
  336. b=fr.read(1024)
  337. if b:
  338. fw.write(b)
  339. else:
  340. break
  341. fr.close()
  342. fw.close()
  343. val=random.randint(1000000,9999999)
  344. ros.chdir('/home/jared/to_video')
  345. ros.system('./p6.sh '+str(val)+' &')
  346. while True:
  347. print('waiting...')
  348. if ros.path.exists('/tmp/results/'+str(val)):
  349. break
  350. time.sleep(15)
  351. print('waiting...')
  352. fr=conn.builtins.open('/tmp/results/'+str(val)+'.mp4','rb')
  353. fw=open(dir_anchor+name+'.mp4','wb')#peggy1_1
  354. while True:
  355. b=fr.read(1024)
  356. if b:
  357. fw.write(b)
  358. else:
  359. break
  360. fr.close()
  361. fw.close()
  362. print('called............................................')
  363. def generate_subtitle_image(name_hash,text_content):
  364. sub_len = 10
  365. img_list = [None]*len(text_content)
  366. for idx in range(len(text_content)):
  367. img_list[idx] = []
  368. for step in range(math.ceil(len(text_content[idx])/sub_len)):
  369. sv_path = dir_subtitle + name_hash +'/'+str(idx)+ str(step) +'.png'
  370. sub = text_content[idx][step*sub_len:step*sub_len+sub_len]
  371. txt2image(sub, sv_path)
  372. img_list[idx] += [{"count":len(sub),"path":sv_path}]
  373. print(sub+':'+sv_path)
  374. return img_list
  375. def anchor_video(name,text_content, image_urls):
  376. m = hashlib.md5()
  377. m.update(name.encode("utf-8"))
  378. name_hash = m.hexdigest()
  379. file_prepare(name, name_hash, text_content,image_urls)
  380. call_achor_video(name_hash)
  381. ck=cKey(0,254,0,150)
  382. ck_anchor=cKey(0,255,1,320)
  383. duration = 0
  384. current_time = 0
  385. current_time_photo = 0
  386. #average layer level is 3
  387. t = openshot.Timeline(1280, 720, openshot.Fraction(30000, 1000), 44100, 2, openshot.LAYOUT_STEREO)
  388. t.Open()
  389. bg_head = openshot.FFmpegReader(dir_video+"bg_head.avi")
  390. bg_head.Open()
  391. bg_head_clip = video_photo_clip(vid=bg_head,layer=2,position=current_time,end=bg_head.info.duration,ck=ck)
  392. t.AddClip(bg_head_clip)
  393. LOGO_OP = openshot.FFmpegReader(dir_video+"LOGO_OP.mp4")
  394. LOGO_OP.Open() # Open the reader
  395. LOGO_OP_clip = video_photo_clip(vid=LOGO_OP,layer=4,position=current_time,end=bg_head.info.duration
  396. ,location_y=-0.03,scale_x=0.8,scale_y=0.71)
  397. t.AddClip(LOGO_OP_clip)
  398. duration+=bg_head.info.duration
  399. current_time += bg_head.info.duration
  400. current_time_photo += bg_head.info.duration
  401. sound = openshot.FFmpegReader(dir_sound+name_hash+".mp3")
  402. sound.Open()
  403. sound_clip = openshot.Clip(sound)
  404. sound_clip.Position(current_time)
  405. t.AddClip(sound_clip)
  406. duration += sound.info.duration
  407. bg = openshot.FFmpegReader(dir_video+"bg.mp4")
  408. bg.Open()
  409. bg_times = math.floor(sound.info.duration/bg.info.duration)
  410. left_time = sound.info.duration % bg.info.duration
  411. bg_clip_list = [None] * bg_times
  412. bg_list = [None] * bg_times
  413. bg.Close()
  414. for idx in range(bg_times):
  415. bg_list[idx] = openshot.FFmpegReader(dir_video+"bg.mp4")
  416. bg_list[idx].Open()
  417. bg_clip_list[idx] = video_photo_clip(bg_list[idx],layer=2,position=current_time
  418. ,end=bg_list[idx].info.duration,ck=ck)
  419. t.AddClip(bg_clip_list[idx])
  420. current_time += bg_list[idx].info.duration
  421. bg_list[idx].Close()
  422. bg_left = openshot.FFmpegReader(dir_video+"bg.mp4")
  423. bg_left.Open()
  424. bg_left_clip = video_photo_clip(bg_left,layer=2,position=current_time,end=left_time,ck=ck)
  425. t.AddClip(bg_left_clip)
  426. current_time += left_time
  427. bg_left.Close()
  428. p_num = len(listdir(dir_photo+name_hash))
  429. photo_clip_list = [None]*p_num
  430. img_list = [None]*p_num
  431. photo_idx = 0
  432. photo_duration = sound.info.duration/p_num
  433. for p in listdir(dir_photo+name_hash):
  434. img_list[photo_idx] = openshot.QtImageReader(dir_photo+name_hash+'/'+p)
  435. photo_clip_list[photo_idx] = video_photo_clip(vid=img_list[photo_idx],layer=3
  436. ,scale_x=0.81,scale_y=0.68,location_y=-0.03,position=current_time_photo,end=photo_duration
  437. ,audio=False)
  438. t.AddClip(photo_clip_list[photo_idx])
  439. current_time_photo+=photo_duration
  440. photo_idx+=1
  441. current_time_anchor = bg_head.info.duration
  442. anchor = openshot.FFmpegReader(dir_anchor+name_hash+".mp4")
  443. anchor.Open()
  444. anchor_times = math.floor(sound.info.duration/anchor.info.duration)
  445. left_time = sound.info.duration % anchor.info.duration
  446. anchor_clip_list = [None] * anchor_times
  447. anchor_list = [None] * anchor_times
  448. anchor.Close()
  449. for idx in range(anchor_times):
  450. anchor_list[idx] = openshot.FFmpegReader(dir_anchor+name_hash+".mp4")
  451. anchor_list[idx].Open()
  452. anchor_clip_list[idx] = video_photo_clip(vid=anchor_list[idx],layer=4,scale_x=0.65,scale_y=0.65,
  453. location_x=0.35,location_y=0.25,position=current_time_anchor, end=anchor_list[idx].info.duration,
  454. ck=ck_anchor,audio=False)
  455. t.AddClip(anchor_clip_list[idx])
  456. current_time_anchor += anchor_list[idx].info.duration
  457. anchor_list[idx].Close()
  458. anchor = openshot.FFmpegReader(dir_anchor+"peggy1_1.mp4")
  459. anchor.Open()
  460. 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
  461. , position=current_time_anchor,end=left_time,ck=ck_anchor)
  462. t.AddClip(anchor_left_clip)
  463. anchor.Close()
  464. title = openshot.QtImageReader(dir_title+name_hash+".png")
  465. title.Open() # Open the reader
  466. title_clip = video_photo_clip(vid=title, layer=4, location_y=0.9,position=0,end=duration)
  467. t.AddClip(title_clip)
  468. ####start building
  469. w = openshot.FFmpegWriter("../html/"+name_hash+".mp4")
  470. w.SetAudioOptions(True, "libmp3lame", 44100, 2, openshot.LAYOUT_STEREO, 3000000)
  471. w.SetVideoOptions(True, "libx264", openshot.Fraction(30000, 1000), 1280, 720,
  472. openshot.Fraction(1, 1), False, False, 3000000)
  473. w.Open()
  474. #may change duration into t.info.duration
  475. for n in range(int(t.info.fps)*int(duration)):
  476. f=t.GetFrame(n)
  477. w.WriteFrame(f)
  478. t.Close()
  479. w.Close()
  480. sound.Close()
  481. print("It's fine")
  482. notify_group(name+"的影片已經產生完成囉! www.choozmo.com:8168/"+name_hash+".mp4")
  483. def anchor_video_v2(name,text_content, image_urls):
  484. m = hashlib.md5()
  485. m.update(name.encode("utf-8"))
  486. name_hash = m.hexdigest()
  487. print('sub image made')
  488. file_prepare_v2(name, name_hash, text_content,image_urls)
  489. sub_list=generate_subtitle_image(name_hash,text_content)
  490. for fname in range(len(text_content)):
  491. call_achor_video_v2(name_hash+"/"+str(fname))
  492. print('step finish')
  493. print('called............................................')
  494. ck=cKey(0,254,0,150)
  495. ck_anchor=cKey(0,255,1,320)
  496. duration = 0
  497. #average layer level is 3
  498. t = openshot.Timeline(1280, 720, openshot.Fraction(30000, 1000), 44100, 2, openshot.LAYOUT_STEREO)
  499. t.Open()
  500. main_timer = 0
  501. LOGO_OP = openshot.FFmpegReader(dir_video+"LOGO_OP.mp4")
  502. LOGO_OP.Open() # Open the reader
  503. LOGO_OP_clip = video_photo_clip(vid=LOGO_OP,layer=4,position=0,end=LOGO_OP.info.duration
  504. ,location_y=-0.03,scale_x=0.8,scale_y=0.71)
  505. t.AddClip(LOGO_OP_clip)
  506. bg_head = openshot.FFmpegReader(dir_video+"bg_head.avi")
  507. bg_head.Open()
  508. bg_head_clip = video_photo_clip(vid=bg_head,layer=2,position=0,end=LOGO_OP.info.duration,ck=ck)
  509. t.AddClip(bg_head_clip)
  510. main_timer += LOGO_OP.info.duration
  511. head_duration = LOGO_OP.info.duration
  512. bg_head.Close()
  513. LOGO_OP.Close()
  514. clip_duration=0
  515. photo_clip_list = [None]*len(text_content)
  516. img_list = [None]*len(text_content)
  517. anchor_clip_list = [None] * len(text_content)
  518. anchor_list = [None] * len(text_content)
  519. audio_clip_list = [None] * len(text_content)
  520. audio_list = [None] * len(text_content)
  521. sub_clip_list = [None] * len(text_content)
  522. sub_img_list = [None] * len(text_content)
  523. idx = 0
  524. #mp4 also
  525. for p in listdir(dir_photo+name_hash):
  526. anchor_list[idx] = openshot.FFmpegReader(dir_anchor+name_hash+"/"+str(idx)+".mp4")
  527. clip_duration = anchor_list[idx].info.duration-0.3
  528. anchor_list[idx].Open()
  529. anchor_clip_list[idx] = video_photo_clip(vid=anchor_list[idx],layer=4,scale_x=0.65,scale_y=0.65,
  530. location_x=0.35,location_y=0.25,position=main_timer, end=clip_duration,ck=ck_anchor,audio=False)
  531. t.AddClip(anchor_clip_list[idx])
  532. img_list[idx] = openshot.FFmpegReader(dir_photo+name_hash+'/'+p)
  533. img_list[idx].Open()
  534. photo_clip_list[idx] = video_photo_clip(vid=img_list[idx],layer=3
  535. ,scale_x=0.81,scale_y=0.68,location_y=-0.03,position=main_timer,end=clip_duration,audio=False)
  536. t.AddClip(photo_clip_list[idx])
  537. img_list[idx].Close()
  538. audio_list[idx] = openshot.FFmpegReader(dir_sound+name_hash+"/"+str(idx)+".mp3")
  539. audio_list[idx].Open()
  540. audio_clip_list[idx] = openshot.Clip(audio_list[idx])
  541. audio_clip_list[idx].Position(main_timer)
  542. audio_clip_list[idx].End(clip_duration)
  543. t.AddClip(audio_clip_list[idx])
  544. img_list[idx].Close()
  545. anchor_list[idx].Close()
  546. audio_list[idx].Close()
  547. sub_img_list[idx] = [None] * len(sub_list[idx])
  548. sub_clip_list[idx] = [None] * len(sub_list[idx])
  549. sub_timer = 0
  550. for sub_idx in range(len(sub_list[idx])):
  551. sub_img_list[idx][sub_idx] = openshot.QtImageReader(sub_list[idx][sub_idx]['path'])
  552. sub_img_list[idx][sub_idx].Open()
  553. sub_duration = 0.3*sub_list[idx][sub_idx]['count']
  554. sub_clip_list[idx][sub_idx] = video_photo_clip(vid=sub_img_list[idx][sub_idx], layer=5, location_y=0.88,position=main_timer+sub_timer,end=sub_duration)
  555. t.AddClip(sub_clip_list[idx][sub_idx])
  556. sub_img_list[idx][sub_idx].Close()
  557. sub_timer += sub_duration
  558. print(sub_list[idx][sub_idx]['path'])
  559. main_timer += clip_duration
  560. idx+=1
  561. LOGO_ED = openshot.FFmpegReader(dir_video+"LOGO_ED.avi")
  562. LOGO_ED.Open()
  563. LOGO_ED_clip = video_photo_clip(vid=LOGO_ED,layer=4,position=main_timer,end=LOGO_ED.info.duration
  564. ,location_y=-0.03,scale_x=0.8,scale_y=0.71)
  565. t.AddClip(LOGO_ED_clip)
  566. ED_duration = LOGO_ED.info.duration
  567. LOGO_ED.Close()
  568. bg = openshot.FFmpegReader(dir_video+"bg.mp4")
  569. bg.Open()
  570. bg_times = math.floor(main_timer+ED_duration/bg.info.duration)
  571. left_time = (main_timer+ED_duration) % bg.info.duration
  572. bg_clip_list = [None] * bg_times
  573. bg_list = [None] * bg_times
  574. bg.Close()
  575. bg_timer = head_duration
  576. for idx in range(bg_times):
  577. bg_list[idx] = openshot.FFmpegReader(dir_video+"bg.mp4")
  578. bg_list[idx].Open()
  579. bg_clip_list[idx] = video_photo_clip(bg_list[idx],layer=2,position=bg_timer
  580. ,end=bg_list[idx].info.duration,ck=ck)
  581. t.AddClip(bg_clip_list[idx])
  582. bg_timer += bg_list[idx].info.duration
  583. bg_list[idx].Close()
  584. bg_left = openshot.FFmpegReader(dir_video+"bg.mp4")
  585. bg_left.Open()
  586. bg_left_clip = video_photo_clip(bg_left,layer=2,position=bg_timer,end=left_time,ck=ck)
  587. t.AddClip(bg_left_clip)
  588. bg_left.Close()
  589. title = openshot.QtImageReader(dir_title+name_hash+".png")
  590. title.Open() # Open the reader
  591. title_clip = video_photo_clip(vid=title, layer=4, location_y=0.80,position=0,end=head_duration+main_timer)
  592. t.AddClip(title_clip)
  593. ####start building
  594. w = openshot.FFmpegWriter("../html/"+name_hash+".mp4")
  595. w.SetAudioOptions(True, "libmp3lame", 44100, 2, openshot.LAYOUT_STEREO, 3000000)
  596. w.SetVideoOptions(True, "libx264", openshot.Fraction(30000, 1000), 1280, 720,
  597. openshot.Fraction(1, 1), False, False, 3000000)
  598. w.Open()
  599. #may change duration into t.info.duration
  600. for n in range(int(t.info.fps)*int(head_duration+main_timer+ED_duration)):
  601. f=t.GetFrame(n)
  602. w.WriteFrame(f)
  603. t.Close()
  604. w.Close()
  605. print("Raw Video done")
  606. print("video at : www.choozmo.com:8168/"+name_hash+".mp4")
  607. #line notifs
  608. #notify_group(name+"的影片已經產生完成囉! www.choozmo.com:8168/"+name_hash+".mp4")