test.py 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992
  1. from os import listdir
  2. from os.path import isfile, isdir, join
  3. import openshot
  4. import threading
  5. import zhtts
  6. import os
  7. import urllib
  8. from typing import List
  9. import requests
  10. from pydantic import BaseModel
  11. from bs4 import BeautifulSoup
  12. from PIL import Image,ImageDraw,ImageFont
  13. import pyttsx3
  14. import rpyc
  15. import random
  16. import re
  17. import time
  18. import math
  19. import dataset
  20. from datetime import datetime
  21. from gtts import gTTS
  22. import ffmpy
  23. from difflib import SequenceMatcher
  24. import difflib
  25. from autosub import DEFAULT_CONCURRENCY
  26. from autosub import DEFAULT_SUBTITLE_FORMAT
  27. from pytranscriber.control.ctr_main import Ctr_Main
  28. from pytranscriber.control.ctr_autosub import Ctr_Autosub
  29. import multiprocessing
  30. from itertools import groupby
  31. from operator import itemgetter
  32. from util.parser import parser
  33. dir_sound = 'mp3_track/'
  34. dir_photo = 'photo/'
  35. dir_text = 'text_file/'
  36. dir_video = 'video_material/'
  37. dir_title = 'title/'
  38. dir_subtitle = 'subtitle/'
  39. dir_anchor = 'anchor_raw/'
  40. tmp_video_dir = 'tmp_video/'
  41. video_sub_folder = 'ai_anchor_video/'
  42. dir_list = [dir_sound,dir_photo,dir_text,dir_video,dir_title,dir_subtitle,dir_anchor,tmp_video_dir]
  43. def cKey(r,g,b,fuzz):
  44. col=openshot.Color()
  45. col.red=openshot.Keyframe(r)
  46. col.green=openshot.Keyframe(g)
  47. col.blue=openshot.Keyframe(b)
  48. return openshot.ChromaKey(col, openshot.Keyframe(fuzz))
  49. def video_photo_clip(vid=None,layer=None, position=None, end=None
  50. ,scale_x=1,scale_y=1,location_x=0,location_y=0,ck=None,audio=True):
  51. clip = openshot.Clip(vid)
  52. clip.Layer(layer)
  53. clip.Position(position)
  54. clip.End(end)
  55. clip.scale_x=openshot.Keyframe(scale_x)
  56. clip.scale_y=openshot.Keyframe(scale_y)
  57. clip.location_x=openshot.Keyframe(location_x)
  58. clip.location_y=openshot.Keyframe(location_y)
  59. if ck!=None:
  60. clip.AddEffect(ck)
  61. if audio==True:
  62. clip.has_audio=openshot.Keyframe(1)
  63. else:
  64. clip.has_audio=openshot.Keyframe(0)
  65. return clip
  66. def listener_progress(string, percent):
  67. True
  68. def myunichchar(unicode_char):
  69. mb_string = unicode_char.encode('big5')
  70. try:
  71. unicode_char = unichr(ord(mb_string[0]) << 8 | ord(mb_string[1]))
  72. except NameError:
  73. unicode_char = chr(mb_string[0] << 8 | mb_string[1])
  74. return unicode_char
  75. def get_url_type(url):
  76. print('---------------------------------------------')
  77. print(url)
  78. req = urllib.request.Request(url, method='HEAD', headers={'User-Agent': 'Mozilla/5.0'})
  79. r = urllib.request.urlopen(req)
  80. contentType = r.getheader('Content-Type')
  81. print(contentType)
  82. print('-------------------------------------------------')
  83. return contentType
  84. def make_dir(name_hash):
  85. for direct in dir_list:
  86. if not os.path.isdir(direct):
  87. os.mkdir(direct)
  88. try:
  89. os.mkdir(dir_photo+name_hash)
  90. except FileExistsError:
  91. print("~~~~~~Warning~~~~~~~~~Directory " , dir_photo+name_hash , " already exists")
  92. try:
  93. os.mkdir(dir_text+name_hash)
  94. except FileExistsError:
  95. print("~~~~~~Warning~~~~~~~~~Directory " , dir_text+name_hash , " already exists")
  96. try:
  97. os.mkdir(dir_sound+name_hash)
  98. except FileExistsError:
  99. print("~~~~~~Warning~~~~~~~~~Directory " , dir_sound+name_hash , " already exists")
  100. try:
  101. os.mkdir(dir_anchor+name_hash)
  102. except FileExistsError:
  103. print("~~~~~~Warning~~~~~~~~~Directory " , dir_anchor+name_hash , " already exists")
  104. try:
  105. os.mkdir(dir_subtitle+name_hash)
  106. except FileExistsError:
  107. print("~~~~~~Warning~~~~~~~~~Directory " , dir_subtitle+name_hash , " already exists")
  108. def file_prepare(name, name_hash,text_content,image_urls,multiLang,lang='zh'):
  109. make_dir(name_hash)
  110. img_num = 1
  111. for imgu in image_urls:
  112. if get_url_type(imgu) =='video/mp4':
  113. r=requests.get(imgu)
  114. f=open(dir_photo+name_hash+"/"+str(img_num)+".mp4",'wb')
  115. for chunk in r.iter_content(chunk_size=255):
  116. if chunk:
  117. f.write(chunk)
  118. f.close()
  119. else:
  120. im = Image.open(requests.get(imgu, stream=True).raw)
  121. im= im.convert("RGB")
  122. im.save(dir_photo+name_hash+"/"+str(img_num)+".jpg")
  123. img_num+=1
  124. #save text
  125. txt_idx=0
  126. for txt in text_content:
  127. text_file = open(dir_text+name_hash+"/"+str(txt_idx)+".txt", "w")
  128. text_file.write(txt)
  129. text_file.close()
  130. txt_idx+=1
  131. print("text file made")
  132. #make mp3
  133. txt_idx = 0
  134. for txt in text_content:
  135. if lang!='zh' or multiLang==1:
  136. if lang!='zh':
  137. tts = gTTS(txt)
  138. tts.save(dir_sound+name_hash+"/"+str(txt_idx)+"raw.mp3")
  139. else:
  140. tts = gTTS(txt,lang='zh-tw')
  141. tts.save(dir_sound+name_hash+"/"+str(txt_idx)+"raw.mp3")
  142. #speed up
  143. ff = ffmpy.FFmpeg(inputs={dir_sound+name_hash+"/"+str(txt_idx)+"raw.mp3": None}
  144. , outputs={dir_sound+name_hash+"/"+str(txt_idx)+".mp3": ["-filter:a", "atempo=1.2"]})
  145. ff.run()
  146. os.remove(dir_sound+name_hash+"/"+str(txt_idx)+"raw.mp3")
  147. else:
  148. print('use zhtts')
  149. tts = zhtts.TTS()
  150. tts.text2wav(txt,dir_sound+name_hash+"/"+str(txt_idx)+".mp3")
  151. txt_idx+=1
  152. print("mp3 file made")
  153. #make title as image
  154. txt2image_title(name, dir_title+name_hash+".png",lang)
  155. def file_prepare_long(name, name_hash,text_content,image_urls,multiLang,lang='zh'):
  156. make_dir(name_hash)
  157. img_num = 1
  158. for imgu in image_urls:
  159. if get_url_type(imgu) =='video/mp4':
  160. r=requests.get(imgu)
  161. f=open(dir_photo+name_hash+"/"+str(img_num)+".mp4",'wb')
  162. for chunk in r.iter_content(chunk_size=255):
  163. if chunk:
  164. f.write(chunk)
  165. f.close()
  166. else:
  167. im = Image.open(requests.get(imgu, stream=True).raw)
  168. im= im.convert("RGB")
  169. im.save(dir_photo+name_hash+"/"+str(img_num)+".jpg")
  170. img_num+=1
  171. #make mp3
  172. text_parser = parser()
  173. txt_idx = 0
  174. for txt in text_content:
  175. rep_list = text_parser.replace_list(txt)
  176. for reptxt in rep_list:
  177. txt = txt.replace(reptxt,'')
  178. if lang!='zh' or multiLang==1:
  179. if lang!='zh':
  180. tts = gTTS(txt)
  181. tts.save(dir_sound+name_hash+"/"+str(txt_idx)+"raw.mp3")
  182. else:
  183. tts = gTTS(txt,lang='zh-tw')
  184. tts.save(dir_sound+name_hash+"/"+str(txt_idx)+"raw.mp3")
  185. #speed up
  186. ff = ffmpy.FFmpeg(inputs={dir_sound+name_hash+"/"+str(txt_idx)+"raw.mp3": None}
  187. , outputs={dir_sound+name_hash+"/"+str(txt_idx)+".mp3": ["-filter:a", "atempo=1.2"]})
  188. ff.run()
  189. os.remove(dir_sound+name_hash+"/"+str(txt_idx)+"raw.mp3")
  190. else:
  191. print('use zhtts')
  192. tts = zhtts.TTS()
  193. tts.text2wav(txt,dir_sound+name_hash+"/"+str(txt_idx)+".mp3")
  194. txt_idx+=1
  195. print("mp3 file made")
  196. #make title as image
  197. txt2image_title(name, dir_title+name_hash+".png",lang)
  198. def txt2image(content, save_target,lang='zh'):
  199. unicode_text = trim_punctuation(content)
  200. font = ''
  201. if lang=='zh':
  202. font = ImageFont.truetype(font="font/DFT_B7.ttc", size=38)
  203. else :
  204. font = ImageFont.truetype(font="font/arial.ttf", size=38)
  205. text_width, text_height = font.getsize(unicode_text)
  206. canvas = Image.new('RGBA', (700, 500), (255, 0, 0, 0) )
  207. draw = ImageDraw.Draw(canvas)
  208. text= unicode_text
  209. draw.text((5,5), text, (255, 255, 0), font)
  210. canvas.save(save_target, "PNG")
  211. def txt2image_title(content, save_target, lang='zh'):
  212. unicode_text = trim_punctuation(content)
  213. font = ''
  214. if lang=='zh':
  215. font = ImageFont.truetype(font="font/DFT_B7.ttc", size=22)
  216. else :
  217. font = ImageFont.truetype(font="font/arial.ttf", size=22)
  218. text_width, text_height = font.getsize(unicode_text)
  219. canvas = Image.new('RGBA', (510, 500), (255, 0, 0, 0) )
  220. draw = ImageDraw.Draw(canvas)
  221. text= unicode_text
  222. draw.text((5,5), text, (17, 41, 167), font)
  223. canvas.save(save_target, "PNG")
  224. def call_anchor(fileName,avatar):
  225. conn = rpyc.classic.connect("192.168.1.105",18812)
  226. ros = conn.modules.os
  227. rsys = conn.modules.sys
  228. fr=open(dir_sound+fileName+".mp3",'rb')# voice
  229. #warning!!! file my be replaced by other process
  230. fw=conn.builtins.open('/tmp/output.mp3','wb')
  231. while True:
  232. b=fr.read(1024)
  233. if b:
  234. fw.write(b)
  235. else:
  236. break
  237. fr.close()
  238. fw.close()
  239. val=random.randint(1000000,9999999)
  240. ros.chdir('/home/jared/to_video')
  241. ros.system('./p'+str(avatar)+'.sh '+str(val)+' &')
  242. while True:
  243. print('waiting...')
  244. if ros.path.exists('/tmp/results/'+str(val)):
  245. break
  246. time.sleep(5)
  247. print('waiting...')
  248. fr=conn.builtins.open('/tmp/results/'+str(val)+'.mp4','rb')
  249. fw=open(dir_anchor+fileName+".mp4",'wb')
  250. while True:
  251. b=fr.read(1024)
  252. if b:
  253. fw.write(b)
  254. else:
  255. break
  256. fr.close()
  257. fw.close()
  258. def syllable_count(word):
  259. word = word.lower()
  260. count = 0
  261. vowels = "aeiouy"
  262. if word[0] in vowels:
  263. count += 1
  264. for index in range(1, len(word)):
  265. if word[index] in vowels and word[index - 1] not in vowels:
  266. count += 1
  267. if word.endswith("e"):
  268. count -= 1
  269. if count == 0:
  270. count += 1
  271. return count
  272. def split_sentence(in_str, maxLen):
  273. re.findall(r'[\u4e00-\u9fff]+', in_str)
  274. zh_idx = []
  275. eng_idx= []
  276. for i in range(len(in_str)):
  277. if in_str[i] > u'\u4e00' and in_str[i] < u'\u9fff':
  278. zh_idx.append(i)
  279. else:
  280. eng_idx.append(i)
  281. space_index = [m.start() for m in re.finditer(' ', in_str)]
  282. for idx in space_index:
  283. eng_idx.remove(idx)
  284. eng_range_list = []
  285. for k, g in groupby(enumerate(eng_idx), lambda ix : ix[0] - ix[1]):
  286. eng_range = list(map(itemgetter(1), g))
  287. eng_range_list.append(eng_range)
  288. total_syllable = 0
  289. for i in range(len(eng_range_list)):
  290. total_syllable += (syllable_count(in_str[eng_range_list[i][0]:eng_range_list[i][-1]+1])+0.5)
  291. for i in range(len(zh_idx)):
  292. total_syllable+=1
  293. #final chchchchchc[en][en][en]
  294. #[en] is a vocabulary dict with occurence of image
  295. zh_eng_idx_list = []
  296. i = 0
  297. while i < len(in_str):
  298. if in_str[i]==' ':
  299. i+=1
  300. if i in zh_idx:
  301. zh_eng_idx_list.append(i)
  302. i+=1
  303. if i in eng_idx:
  304. for ls in eng_range_list:
  305. if i in ls:
  306. zh_eng_idx_list.append(ls)
  307. i = ls[-1]+1
  308. break
  309. zh_eng_dict_list = [{'content':'','time_ratio':0}]
  310. idx = 0
  311. current_len = 0
  312. sen_idx = 0
  313. while idx < len(zh_eng_idx_list):
  314. str_from_idx = ''
  315. sylla_cnt = 1
  316. if type(zh_eng_idx_list[idx])==type([]):
  317. str_from_idx = in_str[zh_eng_idx_list[idx][0]:zh_eng_idx_list[idx][-1]+1]+' '
  318. sylla_cnt = syllable_count(str_from_idx)
  319. else:
  320. str_from_idx = in_str[zh_eng_idx_list[idx]]
  321. if len(zh_eng_dict_list[sen_idx]['content'])+sylla_cnt>=maxLen:
  322. zh_eng_dict_list[sen_idx]['time_ratio'] = current_len/total_syllable
  323. zh_eng_dict_list.append({'content':'','time_ratio':0})
  324. sen_idx+=1
  325. current_len = 0
  326. else:
  327. current_len += sylla_cnt
  328. zh_eng_dict_list[sen_idx]['content'] += str_from_idx
  329. idx+=1
  330. total_ratio = 0
  331. for obj in zh_eng_dict_list:
  332. total_ratio+=obj['time_ratio']
  333. zh_eng_dict_list[-1]['time_ratio'] = 1-total_ratio
  334. return zh_eng_dict_list
  335. def parse_script(file_path,gt_list):
  336. with open(file_path, 'r',encoding="utf-8") as f:
  337. raw_lines = [line.strip() for line in f]
  338. lines = adjustSub_by_text_similarity(gt_list,raw_lines)
  339. text_parser = parser()
  340. #make dict
  341. dict_list = []
  342. for idx in range(len(lines)):
  343. script={}
  344. rep_ls = text_parser.replace_list(lines[idx])
  345. line_content = lines[idx]
  346. for reptxt in rep_ls:
  347. line_content = line_content.replace(reptxt,'')
  348. if len(rep_ls)!=0:
  349. script['image_idx'] = int(rep_ls[0].replace('{','').replace('}',''))
  350. script['content'] = line_content
  351. time_raw = raw_lines[idx * 4 +1 ].split(' --> ')
  352. start = time_raw[0].split(':')
  353. stop = time_raw[1].split(':')
  354. script['start'] = float(start[0])*3600 + float(start[1])*60 + float(start[2].replace(',','.'))
  355. script['stop'] = float(stop[0])*3600 + float(stop[1])*60 + float(stop[2].replace(',','.'))
  356. dict_list.append(script)
  357. #merge duplicated sentences
  358. skip_list = []
  359. script_not_dup_list = []
  360. for idx in range(len(dict_list)):
  361. if idx not in skip_list:
  362. dup_list = []
  363. found = 0
  364. for idx_inner in range(len(dict_list)):
  365. if dict_list[idx_inner]['content'] == dict_list[idx]['content'] and idx <= idx_inner:
  366. dup_list.append(idx_inner)
  367. skip_list.append(idx_inner)
  368. found += 1
  369. if found != 0 and dict_list[idx_inner]['content']!=dict_list[idx]['content'] and idx <= idx_inner:
  370. found = 0
  371. break
  372. for dup_idx in dup_list:
  373. if dup_idx == min(dup_list):
  374. dict_list[dup_idx]['type'] = 'lead_sentence'
  375. else:
  376. dict_list[dup_idx]['type'] = 'duplicated'
  377. dict_list[dup_list[0]]['stop'] = dict_list[dup_list[-1]]['stop']
  378. if dict_list[idx]['type'] == 'lead_sentence':
  379. script_not_dup_list.append(dict_list[idx])
  380. new_idx = 0
  381. splitted_dict = []
  382. for dic in script_not_dup_list:
  383. dic_idx = 0
  384. accumulated_duration = 0
  385. duration = dic['stop']-dic['start']
  386. for sub_dic in split_sentence(dic['content'],13):
  387. new_dic = {}
  388. new_dic['index'] = new_idx
  389. if 'image_idx' in dic:
  390. new_dic['image_obj'] = {'start':dic['start'],'idx':dic['image_idx']}
  391. new_idx+=1
  392. ind_duration = duration * sub_dic['time_ratio']
  393. new_dic['start'] = dic['start'] + accumulated_duration
  394. accumulated_duration += ind_duration
  395. new_dic['content'] = sub_dic['content']
  396. new_dic['duration'] = ind_duration*0.7
  397. splitted_dict.append(new_dic)
  398. return splitted_dict
  399. def adjustSub_by_text_similarity(gts_in,gens_raw):
  400. #call by value only
  401. gts = gts_in[:]
  402. text_parser = parser()
  403. for i in range(len(gts)):
  404. rep_ls = text_parser.replace_list(gts[i])
  405. for reptxt in rep_ls:
  406. gts[i] = gts[i].replace(reptxt,'')
  407. gens = []
  408. for idx in range(int((len(gens_raw)+1)/4)):
  409. gens.append(gens_raw[idx*4+2])
  410. combine2 = [''.join([i,j]) for i,j in zip(gts, gts[1:])]
  411. combine3 = [''.join([i,j,k]) for i,j,k in zip(gts, gts[1:], gts[2:])]
  412. alls = gts #+ combine2 + combine3
  413. adjusted = [None]*len(gens)
  414. duplicated_list = []
  415. for idx in range(len(gens)):
  416. match_text = difflib.get_close_matches(gens[idx], alls, cutoff=0.1)
  417. if len(match_text) != 0:
  418. if match_text[0] not in duplicated_list:
  419. adjusted[idx] = match_text[0]
  420. duplicated_list.append(match_text[0])
  421. else:
  422. if match_text[0] == adjusted[idx-1]:
  423. adjusted[idx] = match_text[0]
  424. else:
  425. found = 0
  426. for mt in match_text:
  427. if mt not in duplicated_list:
  428. adjusted[idx] = mt
  429. found += 1
  430. break
  431. if found ==0:
  432. adjusted[idx] = ' '
  433. else :
  434. adjusted[idx] = ' '
  435. combine2_tag = [''.join([i,j]) for i,j in zip(gts_in, gts_in[1:])]
  436. combine3_tag = [''.join([i,j,k]) for i,j,k in zip(gts_in, gts_in[1:], gts_in[2:])]
  437. alls_tag = gts_in #+ combine2_tag + combine3_tag
  438. for idx in range(len(adjusted)):
  439. match_text = difflib.get_close_matches(adjusted[idx], alls_tag, cutoff=0.1)
  440. adjusted[idx] = match_text[0]
  441. return adjusted
  442. def trim_punctuation(s):
  443. pat_block = u'[^\u4e00-\u9fff0-9a-zA-Z]+';
  444. pattern = u'([0-9]+{0}[0-9]+)|{0}'.format(pat_block)
  445. res = re.sub(pattern, lambda x: x.group(1) if x.group(1) else u" " ,s)
  446. return res
  447. def splitter(s):
  448. for sent in re.findall(u'[^!?,。\!\?]+[!? 。\!\?]?', s, flags=re.U):
  449. yield sent
  450. def split_by_pun(s):
  451. res = list(splitter(s))
  452. return res
  453. def generate_subtitle_image_from_dict(name_hash, sub_dict):
  454. for script in sub_dict:
  455. sv_path = dir_subtitle + name_hash + '/' + str(script['index'])+'.png'
  456. sub = script['content']
  457. txt2image(sub,sv_path)
  458. def generate_subtitle_image(name_hash,text_content):
  459. img_list = [None]*len(text_content)
  460. for idx in range(len(text_content)):
  461. img_list[idx]=[]
  462. senList = split_by_pun(text_content[idx])
  463. for inner_idx in range(len(senList)):
  464. sv_path = dir_subtitle + name_hash +'/'+str(idx)+ str(inner_idx) +'.png'
  465. sub = senList[inner_idx]
  466. txt2image(sub,sv_path)
  467. img_list[idx]+=[{"count":len(sub),"path":sv_path}]
  468. return img_list
  469. def generate_subtitle_image_ENG(name_hash,text_content):
  470. img_list = [None]*len(text_content)
  471. for idx in range(len(text_content)):
  472. sv_path = dir_subtitle + name_hash +'/'+str(idx)+'.png'
  473. sub = text_content[idx]
  474. txt2image(sub, sv_path,lang='eng')
  475. img_list[idx] = sv_path
  476. return img_list
  477. def video_writer_init(path):
  478. w = openshot.FFmpegWriter(path)
  479. w.SetAudioOptions(True, "aac", 44100, 2, openshot.LAYOUT_STEREO, 3000000)
  480. w.SetVideoOptions(True, "libx264", openshot.Fraction(30000, 1000), 1280, 720,
  481. openshot.Fraction(1, 1), False, False, 3000000)
  482. return w
  483. def video_gen(name_hash,name,text_content, image_urls,multiLang,avatar):
  484. file_prepare_long(name, name_hash, text_content,image_urls,multiLang)
  485. for fname in range(len(text_content)):
  486. call_anchor(name_hash+"/"+str(fname),avatar)
  487. print('called............................................')
  488. ck=cKey(0,254,0,270)
  489. ck_anchor=cKey(0,255,1,320)
  490. t = openshot.Timeline(1280, 720, openshot.Fraction(30000, 1000), 44100, 2, openshot.LAYOUT_STEREO)
  491. t.Open()
  492. main_timer = 0
  493. LOGO_OP = openshot.FFmpegReader(dir_video+"LOGO_OP_4.mp4")
  494. LOGO_OP.Open() # Open the reader
  495. head_duration = LOGO_OP.info.duration
  496. LOGO_OP_clip = video_photo_clip(vid=LOGO_OP,layer=4,position=0,end=head_duration
  497. ,location_y=-0.03,scale_x=0.8,scale_y=0.704)
  498. t.AddClip(LOGO_OP_clip)
  499. bg_head = openshot.FFmpegReader(dir_video+"complete_head_aispokesgirl.mp4")
  500. bg_head.Open()
  501. bg_head_clip = video_photo_clip(vid=bg_head,layer=2,position=0,end=LOGO_OP.info.duration,ck=ck)
  502. t.AddClip(bg_head_clip)
  503. main_timer += head_duration
  504. bg_head.Close()
  505. LOGO_OP.Close()
  506. anchor = openshot.FFmpegReader(dir_anchor+name_hash+"/0.mp4")
  507. anchor.Open()
  508. #anchor_clip = video_photo_clip(vid=anchor,layer=4,scale_x=0.65,scale_y=0.65,
  509. # location_x=0.35,location_y=0.25,position=main_timer, end=anchor.info.duration,ck=ck_anchor,audio=False)
  510. #t.AddClip(anchor_clip)
  511. speech = openshot.FFmpegReader(dir_sound+name_hash+"/0.mp3")
  512. speech.Open()
  513. speech_clip = openshot.Clip(speech)
  514. speech_clip.Position(main_timer)
  515. speech_clip.End(anchor.info.duration)
  516. t.AddClip(speech_clip)
  517. main_timer += anchor.info.duration
  518. anchor.Close()
  519. speech.Close()
  520. LOGO_ED = openshot.FFmpegReader(dir_video+"LOGO_ED.avi")
  521. LOGO_ED.Open()
  522. LOGO_ED_clip = video_photo_clip(vid=LOGO_ED,layer=4,position=main_timer,end=LOGO_ED.info.duration
  523. ,location_x=0.005,location_y=-0.031, scale_x=0.8,scale_y=0.6825)
  524. t.AddClip(LOGO_ED_clip)
  525. main_timer += LOGO_ED.info.duration
  526. LOGO_ED.Close()
  527. bg = openshot.FFmpegReader(dir_video+"complete_double_aispokesgirl.mp4")
  528. bg.Open()
  529. bg_times = math.floor(main_timer/bg.info.duration)
  530. left_time = (main_timer) % bg.info.duration
  531. bg_clip_list = [None] * bg_times
  532. bg_list = [None] * bg_times
  533. bg.Close()
  534. bg_timer = head_duration
  535. for idx in range(bg_times):
  536. bg_list[idx] = openshot.FFmpegReader(dir_video+"complete_double_aispokesgirl.mp4")
  537. bg_list[idx].Open()
  538. bg_clip_list[idx] = video_photo_clip(bg_list[idx],layer=2,position=bg_timer,end=bg_list[idx].info.duration,ck=ck)
  539. t.AddClip(bg_clip_list[idx])
  540. bg_timer += bg_list[idx].info.duration
  541. bg_list[idx].Close()
  542. bg_left = openshot.FFmpegReader(dir_video+"complete_double_aispokesgirl.mp4")
  543. bg_left.Open()
  544. bg_left_clip = video_photo_clip(bg_left,layer=2,position=bg_timer,end=left_time,ck=ck)
  545. t.AddClip(bg_left_clip)
  546. bg_left.Close()
  547. title = openshot.QtImageReader(dir_title+name_hash+".png")
  548. title.Open() # Open the reader
  549. title_clip = video_photo_clip(vid=title, layer=4,location_x=-0.047, location_y=0.801,position=0,end=head_duration+main_timer)
  550. t.AddClip(title_clip)
  551. w = video_writer_init(tmp_video_dir+name_hash+"raw.mp4")
  552. w.Open()
  553. frames = int(t.info.fps)*int(main_timer)
  554. for n in range(frames):
  555. f=t.GetFrame(n)
  556. w.WriteFrame(f)
  557. t.Close()
  558. w.Close()
  559. print(name+"RAW DONE : www.choozmo.com:8168/"+tmp_video_dir+name_hash+"raw.mp4")
  560. #start adding sub
  561. #add sub
  562. Ctr_Autosub.init()
  563. Ctr_Autosub.generate_subtitles(tmp_video_dir+name_hash+"raw.mp4",'zh',listener_progress,output=tmp_video_dir+name_hash+"script.txt",concurrency=DEFAULT_CONCURRENCY,subtitle_file_format=DEFAULT_SUBTITLE_FORMAT)
  564. sub_dict = parse_script(tmp_video_dir+name_hash+"script.txt",split_by_pun(text_content[0]))
  565. for subd in sub_dict:
  566. print(subd)
  567. generate_subtitle_image_from_dict(name_hash, sub_dict)
  568. #sv_path = dir_subtitle + name_hash + '/' + str(script['index'])+'.png'
  569. t = openshot.Timeline(1280, 720, openshot.Fraction(30000, 1000), 44100, 2, openshot.LAYOUT_STEREO)
  570. t.Open()
  571. raw = openshot.FFmpegReader(tmp_video_dir+name_hash+"raw.mp4")
  572. raw.Open()
  573. raw_clip = video_photo_clip(vid=raw,layer=2,position=0, end=raw.info.duration)
  574. t.AddClip(raw_clip)
  575. sub_img_list = [None] * len(sub_dict)
  576. sub_clip_list = [None] * len(sub_dict)
  577. for sub_obj in sub_dict:
  578. idx = int(sub_obj['index'])
  579. sub_img_list[idx] = openshot.QtImageReader(dir_subtitle + name_hash + '/' + str(idx)+'.png')
  580. sub_img_list[idx].Open()
  581. #if sub_obj['duration']>3:
  582. # print('warning')
  583. #print('start:',sub_obj['start'],', duration :', sub_obj['duration'],' content',sub_obj['content'],'idx:',sub_obj['index'])
  584. sub_clip_list[idx] = video_photo_clip(vid=sub_img_list[idx], layer=6,location_x=0.069, location_y=0.89,position=sub_obj['start'],end=math.ceil(sub_obj['duration']))
  585. t.AddClip(sub_clip_list[idx])
  586. sub_img_list[idx].Close()
  587. tp = parser()
  588. img_dict_ls = tp.image_clip_info(sub_dict)
  589. img_clip_list = [None]*len(listdir(dir_photo+name_hash))
  590. img_list = [None]*len(img_clip_list)
  591. img_file_ls = listdir(dir_photo+name_hash)
  592. for img_idx in range(len(img_file_ls)):
  593. img_list[img_idx] = openshot.FFmpegReader(dir_photo+name_hash+'/'+img_file_ls[img_idx])
  594. img_list[img_idx].Open()
  595. img_clip_list[img_idx] = video_photo_clip(vid=img_list[img_idx],layer=3
  596. ,scale_x=0.81,scale_y=0.68,location_y=-0.03,position=img_dict_ls[img_idx]['start'],end=img_dict_ls[img_idx]['duration'],audio=False)
  597. t.AddClip(img_clip_list[img_idx])
  598. img_list[img_idx].Close()
  599. anchor = openshot.FFmpegReader(dir_anchor+name_hash+"/0.mp4")
  600. anchor.Open()
  601. anchor_clip = video_photo_clip(vid=anchor,layer=4,scale_x=0.65,scale_y=0.65,
  602. location_x=0.35,location_y=0.25,position=head_duration, end=anchor.info.duration,ck=ck_anchor,audio=False)
  603. t.AddClip(anchor_clip)
  604. w = video_writer_init(tmp_video_dir+name_hash+".mp4")
  605. w.Open()
  606. frames = int(t.info.fps)*int(main_timer)
  607. for n in range(frames):
  608. f=t.GetFrame(n)
  609. w.WriteFrame(f)
  610. t.Close()
  611. w.Close()
  612. os.remove(tmp_video_dir+name_hash+"raw.mp4")
  613. os.remove(tmp_video_dir+name_hash+"script.txt")
  614. print(name+"ALL DONE : www.choozmo.com:8168/"+video_sub_folder+name_hash+"raw.mp4")
  615. def anchor_video_v2(name_hash,name,text_content, image_urls,multiLang,avatar):
  616. file_prepare(name, name_hash, text_content,image_urls,multiLang)
  617. sub_list=generate_subtitle_image(name_hash,text_content)
  618. for fname in range(len(text_content)):
  619. call_anchor(name_hash+"/"+str(fname),avatar)
  620. print('step finish')
  621. print('called............................................')
  622. ck=cKey(0,254,0,270)
  623. ck_anchor=cKey(0,255,1,320)
  624. duration = 0
  625. #average layer level is 3
  626. t = openshot.Timeline(1280, 720, openshot.Fraction(30000, 1000), 44100, 2, openshot.LAYOUT_STEREO)
  627. t.Open()
  628. main_timer = 0
  629. LOGO_OP = openshot.FFmpegReader(dir_video+"LOGO_OP_4.mp4")
  630. LOGO_OP.Open() # Open the reader
  631. LOGO_OP_clip = video_photo_clip(vid=LOGO_OP,layer=4,position=0,end=LOGO_OP.info.duration
  632. ,location_y=-0.03,scale_x=0.8,scale_y=0.704)
  633. t.AddClip(LOGO_OP_clip)
  634. bg_head = openshot.FFmpegReader(dir_video+"complete_head_aispokesgirl.mp4")
  635. bg_head.Open()
  636. bg_head_clip = video_photo_clip(vid=bg_head,layer=2,position=0,end=LOGO_OP.info.duration,ck=ck)
  637. t.AddClip(bg_head_clip)
  638. main_timer += LOGO_OP.info.duration
  639. head_duration = LOGO_OP.info.duration
  640. bg_head.Close()
  641. LOGO_OP.Close()
  642. clip_duration=0
  643. photo_clip_list = [None]*len(text_content)
  644. img_list = [None]*len(text_content)
  645. anchor_clip_list = [None] * len(text_content)
  646. anchor_list = [None] * len(text_content)
  647. audio_clip_list = [None] * len(text_content)
  648. audio_list = [None] * len(text_content)
  649. sub_clip_list = [None] * len(text_content)
  650. sub_img_list = [None] * len(text_content)
  651. idx = 0
  652. for p in listdir(dir_photo+name_hash):
  653. anchor_list[idx] = openshot.FFmpegReader(dir_anchor+name_hash+"/"+str(idx)+".mp4")
  654. clip_duration = anchor_list[idx].info.duration
  655. anchor_list[idx].Open()
  656. anchor_clip_list[idx] = video_photo_clip(vid=anchor_list[idx],layer=4,scale_x=0.65,scale_y=0.65,
  657. location_x=0.35,location_y=0.25,position=main_timer, end=clip_duration,ck=ck_anchor,audio=False)
  658. t.AddClip(anchor_clip_list[idx])
  659. img_list[idx] = openshot.FFmpegReader(dir_photo+name_hash+'/'+p)
  660. img_list[idx].Open()
  661. photo_clip_list[idx] = video_photo_clip(vid=img_list[idx],layer=3
  662. ,scale_x=0.8,scale_y=0.704,location_y=-0.03,position=main_timer,end=clip_duration,audio=False)
  663. t.AddClip(photo_clip_list[idx])
  664. img_list[idx].Close()
  665. audio_list[idx] = openshot.FFmpegReader(dir_sound+name_hash+"/"+str(idx)+".mp3")
  666. audio_list[idx].Open()
  667. audio_clip_list[idx] = openshot.Clip(audio_list[idx])
  668. audio_clip_list[idx].Position(main_timer)
  669. audio_clip_list[idx].End(clip_duration)
  670. t.AddClip(audio_clip_list[idx])
  671. img_list[idx].Close()
  672. anchor_list[idx].Close()
  673. audio_list[idx].Close()
  674. sub_img_list[idx] = [None] * len(sub_list[idx])
  675. sub_clip_list[idx] = [None] * len(sub_list[idx])
  676. sub_timer = 0
  677. for sub_idx in range(len(sub_list[idx])):
  678. sub_img_list[idx][sub_idx] = openshot.QtImageReader(sub_list[idx][sub_idx]['path'])
  679. sub_img_list[idx][sub_idx].Open()
  680. sub_duration = 0.205*sub_list[idx][sub_idx]['count']
  681. sub_clip_list[idx][sub_idx] = video_photo_clip(vid=sub_img_list[idx][sub_idx], layer=6,location_x=0.069, location_y=0.89,position=main_timer+sub_timer,end=sub_duration)
  682. t.AddClip(sub_clip_list[idx][sub_idx])
  683. sub_img_list[idx][sub_idx].Close()
  684. sub_timer += sub_duration
  685. print(sub_list[idx][sub_idx]['path'])
  686. main_timer += clip_duration
  687. idx+=1
  688. LOGO_ED = openshot.FFmpegReader(dir_video+"LOGO_ED.avi")
  689. LOGO_ED.Open()
  690. LOGO_ED_clip = video_photo_clip(vid=LOGO_ED,layer=4,position=main_timer,end=LOGO_ED.info.duration+2
  691. ,location_x=0.005,location_y=-0.031
  692. ,scale_x=0.8,scale_y=0.6825)
  693. t.AddClip(LOGO_ED_clip)
  694. ED_duration = LOGO_ED.info.duration
  695. LOGO_ED.Close()
  696. bg = openshot.FFmpegReader(dir_video+"complete_double_aispokesgirl.mp4")
  697. bg.Open()
  698. bg_times = math.floor(main_timer+ED_duration/bg.info.duration)
  699. left_time = (main_timer+ED_duration) % bg.info.duration
  700. bg_clip_list = [None] * bg_times
  701. bg_list = [None] * bg_times
  702. bg.Close()
  703. bg_timer = head_duration
  704. for idx in range(bg_times):
  705. bg_list[idx] = openshot.FFmpegReader(dir_video+"complete_double_aispokesgirl.mp4")
  706. bg_list[idx].Open()
  707. bg_clip_list[idx] = video_photo_clip(bg_list[idx],layer=2,position=bg_timer
  708. ,end=bg_list[idx].info.duration,ck=ck)
  709. t.AddClip(bg_clip_list[idx])
  710. bg_timer += bg_list[idx].info.duration
  711. bg_list[idx].Close()
  712. bg_left = openshot.FFmpegReader(dir_video+"complete_double_aispokesgirl.mp4")
  713. bg_left.Open()
  714. bg_left_clip = video_photo_clip(bg_left,layer=2,position=bg_timer,end=left_time,ck=ck)
  715. t.AddClip(bg_left_clip)
  716. bg_left.Close()
  717. title = openshot.QtImageReader(dir_title+name_hash+".png")
  718. title.Open() # Open the reader
  719. title_clip = video_photo_clip(vid=title, layer=4,location_x=-0.047, location_y=0.801,position=0,end=head_duration+main_timer)
  720. t.AddClip(title_clip)
  721. ####start building
  722. w = openshot.FFmpegWriter(tmp_video_dir+name_hash+".mp4")
  723. w.SetAudioOptions(True, "aac", 44100, 2, openshot.LAYOUT_STEREO, 3000000)
  724. w.SetVideoOptions(True, "libx264", openshot.Fraction(30000, 1000), 1280, 720,
  725. openshot.Fraction(1, 1), False, False, 3000000)
  726. w.Open()
  727. #may change duration into t.info.duration
  728. frames = int(t.info.fps)*int(head_duration+main_timer+ED_duration)
  729. for n in range(frames):
  730. f=t.GetFrame(n)
  731. w.WriteFrame(f)
  732. #notify_group(name+"的影片已經產生完成囉! www.choozmo.com:8168/"+video_sub_folder+name_hash+".mp4")
  733. t.Close()
  734. w.Close()
  735. print("video at : www.choozmo.com:8168/"+video_sub_folder+name_hash+".mp4")
  736. def anchor_video_eng(name_hash,name,text_content, image_urls,sub_titles,avatar):
  737. file_prepare(name, name_hash, text_content,image_urls,'eng')
  738. sub_list=generate_subtitle_image_ENG(name_hash,sub_titles)
  739. for fname in range(len(text_content)):
  740. call_anchor(name_hash+"/"+str(fname),avatar)
  741. print('step finish')
  742. print('called............................................')
  743. ck=cKey(0,254,0,270)
  744. ck_anchor=cKey(0,255,1,320)
  745. duration = 0
  746. #average layer level is 3
  747. t = openshot.Timeline(1280, 720, openshot.Fraction(30000, 1000), 44100, 2, openshot.LAYOUT_STEREO)
  748. t.Open()
  749. main_timer = 0
  750. #add logo
  751. LOGO_OP = openshot.FFmpegReader(dir_video+"LOGO_OP_4.mp4")
  752. LOGO_OP.Open() # Open the reader
  753. LOGO_OP_clip = video_photo_clip(vid=LOGO_OP,layer=4,position=0,end=LOGO_OP.info.duration
  754. ,location_y=-0.03,scale_x=0.8,scale_y=0.704)
  755. t.AddClip(LOGO_OP_clip)
  756. #add background video (head is different)
  757. bg_head = openshot.FFmpegReader(dir_video+"complete_head_aispokesgirl.mp4")
  758. bg_head.Open()
  759. bg_head_clip = video_photo_clip(vid=bg_head,layer=2,position=0,end=LOGO_OP.info.duration,ck=ck)
  760. t.AddClip(bg_head_clip)
  761. main_timer += LOGO_OP.info.duration
  762. head_duration = LOGO_OP.info.duration
  763. bg_head.Close()
  764. LOGO_OP.Close()
  765. #prepare empty list
  766. clip_duration=0
  767. photo_clip_list = [None]*len(text_content)
  768. img_list = [None]*len(text_content)
  769. anchor_clip_list = [None] * len(text_content)
  770. anchor_list = [None] * len(text_content)
  771. audio_clip_list = [None] * len(text_content)
  772. audio_list = [None] * len(text_content)
  773. sub_clip_list = [None] * len(text_content)
  774. #openshot image holder
  775. sub_img_list = [None] * len(text_content)
  776. idx = 0
  777. for p in listdir(dir_photo+name_hash):
  778. anchor_list[idx] = openshot.FFmpegReader(dir_anchor+name_hash+"/"+str(idx)+".mp4")
  779. clip_duration = anchor_list[idx].info.duration
  780. anchor_list[idx].Open()
  781. anchor_clip_list[idx] = video_photo_clip(vid=anchor_list[idx],layer=4,scale_x=0.65,scale_y=0.65,
  782. location_x=0.35,location_y=0.25,position=main_timer, end=clip_duration,ck=ck_anchor,audio=False)
  783. t.AddClip(anchor_clip_list[idx])
  784. #insert image
  785. img_list[idx] = openshot.FFmpegReader(dir_photo+name_hash+'/'+p)
  786. img_list[idx].Open()
  787. photo_clip_list[idx] = video_photo_clip(vid=img_list[idx],layer=3
  788. ,scale_x=0.81,scale_y=0.68,location_y=-0.03,position=main_timer,end=clip_duration,audio=False)
  789. t.AddClip(photo_clip_list[idx])
  790. img_list[idx].Close()
  791. #insert audio (speech)
  792. audio_list[idx] = openshot.FFmpegReader(dir_sound+name_hash+"/"+str(idx)+".mp3")
  793. audio_list[idx].Open()
  794. audio_clip_list[idx] = openshot.Clip(audio_list[idx])
  795. audio_clip_list[idx].Position(main_timer)
  796. audio_clip_list[idx].End(clip_duration)
  797. t.AddClip(audio_clip_list[idx])
  798. #insert subtitle
  799. sub_img_list[idx] = openshot.QtImageReader(sub_list[idx])
  800. sub_img_list[idx].Open()
  801. sub_clip_list[idx] = video_photo_clip(vid=sub_img_list[idx], layer=6,location_x=0.069, location_y=0.89,position=main_timer,end=clip_duration)
  802. t.AddClip(sub_clip_list[idx])
  803. img_list[idx].Close()
  804. anchor_list[idx].Close()
  805. audio_list[idx].Close()
  806. sub_img_list[idx].Close()
  807. main_timer += clip_duration
  808. idx+=1
  809. LOGO_ED = openshot.FFmpegReader(dir_video+"ED_ENG.mp4")
  810. LOGO_ED.Open()
  811. LOGO_ED_clip = video_photo_clip(vid=LOGO_ED,layer=4,position=main_timer,end=LOGO_ED.info.duration+2
  812. ,location_x=0.005,location_y=-0.031
  813. ,scale_x=0.8,scale_y=0.6825)
  814. t.AddClip(LOGO_ED_clip)
  815. ED_duration = LOGO_ED.info.duration
  816. LOGO_ED.Close()
  817. bg = openshot.FFmpegReader(dir_video+"complete_double_aispokesgirl.mp4")
  818. bg.Open()
  819. bg_times = math.floor(main_timer+ED_duration/bg.info.duration)
  820. left_time = (main_timer+ED_duration) % bg.info.duration
  821. bg_clip_list = [None] * bg_times
  822. bg_list = [None] * bg_times
  823. bg.Close()
  824. bg_timer = head_duration
  825. for idx in range(bg_times):
  826. bg_list[idx] = openshot.FFmpegReader(dir_video+"complete_double_aispokesgirl.mp4")
  827. bg_list[idx].Open()
  828. bg_clip_list[idx] = video_photo_clip(bg_list[idx],layer=2,position=bg_timer
  829. ,end=bg_list[idx].info.duration,ck=ck)
  830. t.AddClip(bg_clip_list[idx])
  831. bg_timer += bg_list[idx].info.duration
  832. bg_list[idx].Close()
  833. bg_left = openshot.FFmpegReader(dir_video+"complete_double_aispokesgirl.mp4")
  834. bg_left.Open()
  835. bg_left_clip = video_photo_clip(bg_left,layer=2,position=bg_timer,end=left_time,ck=ck)
  836. t.AddClip(bg_left_clip)
  837. bg_left.Close()
  838. title = openshot.QtImageReader(dir_title+name_hash+".png")
  839. title.Open() # Open the reader
  840. title_clip = video_photo_clip(vid=title, layer=4,location_x=-0.047, location_y=0.801,position=0,end=head_duration+main_timer)
  841. t.AddClip(title_clip)
  842. ####start building
  843. w = openshot.FFmpegWriter(tmp_video_dir+name_hash+".mp4")
  844. w.SetAudioOptions(True, "aac", 44100, 2, openshot.LAYOUT_STEREO, 3000000)
  845. w.SetVideoOptions(True, "libx264", openshot.Fraction(30000, 1000), 1280, 720,
  846. openshot.Fraction(1, 1), False, False, 3000000)
  847. w.Open()
  848. #may change duration into t.info.duration
  849. frames = int(t.info.fps)*int(head_duration+main_timer+ED_duration)
  850. for n in range(frames):
  851. f=t.GetFrame(n)
  852. w.WriteFrame(f)
  853. #notify_group(name+"(ENG)的影片已經產生完成囉! www.choozmo.com:8168/"+video_sub_folder+name_hash+".mp4")
  854. t.Close()
  855. w.Close()
  856. print("video at : www.choozmo.com:8168/"+video_sub_folder+name_hash+".mp4")
  857. #line notifs
  858. import pyttsx3
  859. def make_speech(text):
  860. engine = pyttsx3.init()
  861. #voices = engine.getProperty('voices')
  862. engine.setProperty('voice', 'Mandarin')
  863. engine.save_to_file(text, '/app/speech.mp3')
  864. engine.runAndWait()