main.py 25 KB

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