main.py 24 KB

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