main.py 24 KB

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