main2.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. import openshot
  2. import re
  3. from PIL import Image,ImageDraw,ImageFont
  4. import pandas as pd
  5. import os
  6. import cv2
  7. import numpy as np
  8. # import moviepy.editor as mp
  9. import time
  10. import pysrt
  11. import shutil
  12. import rpyc
  13. import random
  14. import string
  15. import requests
  16. from bs4 import BeautifulSoup
  17. import zipfile
  18. import csv
  19. from datetime import datetime
  20. import gspread
  21. from oauth2client.service_account import ServiceAccountCredentials
  22. import fire
  23. def auth_gss_client(path, scopes):
  24. credentials = ServiceAccountCredentials.from_json_keyfile_name(path, scopes)
  25. return gspread.authorize(credentials)
  26. auth_json_path = 'noted-tesla-348011-74f70c9caeda.json' #由剛剛建立出的憑證,放置相同目錄以供引入
  27. gss_scopes = ['https://spreadsheets.google.com/feeds'] #我們想要取用的範圍
  28. gss_client = auth_gss_client(auth_json_path, gss_scopes) #呼叫我們的函式
  29. #從剛剛建立的sheet,把網址中 https://docs.google.com/spreadsheets/d/〔key〕/edit 的 〔key〕的值代入
  30. spreadsheet_key_path = '1LU5O8-oAotIFGPI9STPbElO0NHGA6eynuv9sYz81aOw'
  31. wks = gss_client.open_by_key(spreadsheet_key_path).sheet1
  32. def cKey(r,g,b,fuzz):
  33. col=openshot.Color()
  34. col.red=openshot.Keyframe(r)
  35. col.green=openshot.Keyframe(g)
  36. col.blue=openshot.Keyframe(b)
  37. return openshot.ChromaKey(col, openshot.Keyframe(fuzz))
  38. def video_writer_init(path):
  39. w = openshot.FFmpegWriter(path)
  40. w.SetAudioOptions(True, "aac", 44100, 2, openshot.LAYOUT_STEREO, 3000000)
  41. w.SetVideoOptions(True, "libx264", openshot.Fraction(30000, 1000), 1280, 720,
  42. openshot.Fraction(1, 1), False, False, 3000000)
  43. return w
  44. def video_photo_clip(video=None,layer=None, position=None, end=None
  45. ,scale_x=1,scale_y=1,location_x=0,location_y=0,ck=None,audio=True):
  46. clip = openshot.Clip(video)
  47. clip.Layer(layer)
  48. clip.Position(position)
  49. clip.End(end)
  50. clip.scale_x=openshot.Keyframe(scale_x)
  51. clip.scale_y=openshot.Keyframe(scale_y)
  52. clip.location_x=openshot.Keyframe(location_x)
  53. clip.location_y=openshot.Keyframe(location_y)
  54. if ck!=None:
  55. clip.AddEffect(ck)
  56. if audio==True:
  57. clip.has_audio=openshot.Keyframe(1)
  58. else:
  59. clip.has_audio=openshot.Keyframe(0)
  60. return clip
  61. def trim_punctuation(s):
  62. pat_block = u'[^\u4e00-\u9fff0-9a-zA-Z]+'
  63. pattern = u'([0-9]+{0}[0-9]+)|{0}'.format(pat_block)
  64. res = re.sub(pattern, lambda x: x.group(1) if x.group(1) else u" " ,s)
  65. return res
  66. def randomString(stringLength=10):
  67. letters = string.ascii_lowercase
  68. return ''.join(random.choice(letters) for i in range(stringLength))
  69. #文字轉圖片
  70. def txt2image(content, save_target,lang='zh',size=26,fon="input_self/font/DFT_B7.ttc"):
  71. unicode_text = trim_punctuation(content)
  72. font = ''
  73. if lang=='zh':
  74. font = ImageFont.truetype(font=fon, size=size)
  75. else :
  76. font = ImageFont.truetype(font="input_self/font/arial.ttf", size=size)
  77. W, H = (1280,500)
  78. canvas = Image.new('RGB', (W, H), "#00FF00")
  79. draw = ImageDraw.Draw(canvas)
  80. text= content
  81. if "\n" in text:
  82. w, h = draw.textsize(text.split("\n")[0],font = font)
  83. #draw.text(((W-w)/2,0), text[0:18],'black', font)
  84. text_border(draw,(W-w)/2,0,text.split("\n")[0],font,'black','white')
  85. w, h = draw.textsize(text.split("\n")[1],font = font)
  86. #draw.text(((W-w)/2,h+2), text[18:],'black', font)
  87. text_border(draw,(W-w)/2,h+2,text.split("\n")[1],font,'black','white')
  88. else:
  89. w, h = draw.textsize(content,font = font)
  90. #draw.text(((W-w)/2,0), text,'black', font)
  91. text_border(draw,(W-w)/2,0,text,font,'black','white')
  92. canvas.save(save_target, "PNG")
  93. def text_border(draw,x,y,text,font,shadowcolor,fillcolor):
  94. draw.text((x-1, y), text, font=font, fill=shadowcolor)
  95. draw.text((x+1, y), text, font=font, fill=shadowcolor)
  96. draw.text((x, y-1), text, font=font, fill=shadowcolor)
  97. draw.text((x, y+1), text, font=font, fill=shadowcolor)
  98. draw.text((x-1, y+1), text, font=font, fill=shadowcolor)
  99. draw.text((x+1, y-1), text, font=font, fill=shadowcolor)
  100. draw.text((x-1, y-1), text, font=font, fill=shadowcolor)
  101. draw.text((x+1, y+1), text, font=font, fill=shadowcolor)
  102. # thicker border
  103. draw.text((x-2, y-2), text, font=font, fill=shadowcolor)
  104. draw.text((x+2, y-2), text, font=font, fill=shadowcolor)
  105. draw.text((x-2, y+2), text, font=font, fill=shadowcolor)
  106. draw.text((x+2, y+2), text, font=font, fill=shadowcolor)
  107. # now draw the text over it
  108. draw.text((x, y), text, font=font, fill=fillcolor)
  109. def srt_to_csv(srt_file):
  110. subs = pysrt.open(srt_file)
  111. csv_file = srt_file.split('.')[0] + ".csv"
  112. with open(csv_file, 'w', newline='',encoding="big5") as csvfile:
  113. # 建立 CSV 檔寫入器
  114. writer = csv.writer(csvfile)
  115. j=0
  116. for context in subs:
  117. writer.writerow([context.index, context.start,context.end, context.text])
  118. j+=1
  119. return csv_file
  120. def csv_to_text(csv_file,text_font):
  121. text_form = []
  122. with open(csv_file, newline='',encoding="big5") as csvfile:
  123. # 讀取 CSV 檔案內容
  124. rows = csv.reader(csvfile)
  125. j=0
  126. # 以迴圈輸出每一列
  127. for row in rows:
  128. if j==0:
  129. j = 1
  130. continue
  131. start = datetime.strptime(row[1], "%H:%M:%S,%f")
  132. end = datetime.strptime(row[2], "%H:%M:%S,%f") - datetime.strptime(row[1], "%H:%M:%S,%f")
  133. end_timeStamp=end.seconds+0.000001*end.microseconds
  134. start_timeStamp=start.minute*60+start.second+ 0.000001*start.microsecond
  135. text_form.append({'text':row[3],'start':start_timeStamp,'end':end_timeStamp,'size':36,'font':text_font})
  136. return text_form
  137. def text_to_short_vedio(
  138. mp4_file = "output/no_captions/test.mp4",
  139. sound_file ='output/no_captions/test.mp4',
  140. output_filename="output/finally_output/demo.mp4",
  141. text_font ="input_self/font/DFT_R7.ttc"):
  142. t = openshot.Timeline(1280, 720, openshot.Fraction(30000, 1000), 44100, 2, openshot.LAYOUT_STEREO)
  143. t.Open()
  144. # 去背參數
  145. ck = cKey(0, 254, 0, 270)
  146. ck_anchor = cKey(0, 255, 0, 320)
  147. anchor = openshot.FFmpegReader(mp4_file)
  148. anchor.Open()
  149. anchor_clip = video_photo_clip(video=anchor,layer=2,scale_x=1,scale_y=1,
  150. location_x=0,location_y=0,position=0, end=anchor.info.duration,audio=True)
  151. t.AddClip(anchor_clip)
  152. anchor.Close()
  153. number = 0
  154. # sound_srt_file = ""
  155. # #音檔自動產生srt(逐字稿)
  156. # if ".srt" in sound_file:
  157. # sound_srt_file = sound_file
  158. # elif not sound_file is None:
  159. # cmd = "autosub -S zh-TW -D zh-TW " + sound_file
  160. # os.system(cmd)
  161. # sound_srt_file = sound_file.split('.')[0] + ".srt"
  162. # csv_file = srt_to_csv(sound_srt_file)
  163. csv_file = "output/csv_produce/test.csv"
  164. text_form = csv_to_text(csv_file,text_font)
  165. # text_form = sheet_to_text(text_font)
  166. # print(text_form)
  167. # print(sound_srt_file)
  168. #開啟srt檔
  169. try:
  170. number = 0
  171. for text_tmp in text_form:
  172. file_name = "input_self/tmp/save_target_" + str(number) + ".png"
  173. txt2image(text_tmp['text'], file_name,lang='zh',size = text_tmp['size'],fon = text_tmp['font'])
  174. exec('text_anchor_{} = openshot.QtImageReader("input_self/tmp/save_target_{}.png")'.format(number,number))
  175. exec('text_anchor_{}.Open()'.format(number))
  176. exec('text_anchor_{}.Open()'.format(number))
  177. exec('text_anchor_clip_{} = video_photo_clip(video=text_anchor_{},layer=4,scale_x=1,scale_y=1,\
  178. location_x=0,location_y=0.78,position=text_tmp["start"], end=text_tmp["end"],ck=ck_anchor,audio=True)'.format(number,number))
  179. exec('t.AddClip(text_anchor_clip_{})'.format(number))
  180. exec('text_anchor_{}.Close()'.format(number))
  181. number = number+1
  182. except:
  183. print("無法開啟srt檔案(字幕產生失敗)")
  184. w = video_writer_init(output_filename)
  185. w.Open()
  186. frames = int(t.info.fps)*int(anchor.info.duration)
  187. for n in range(frames):
  188. f=t.GetFrame(n)
  189. w.WriteFrame(f)
  190. t.Close()
  191. w.Close()
  192. # 刪除暫存檔案
  193. shutil.rmtree('input_self/tmp')
  194. os.mkdir('input_self/tmp')
  195. # shutil.rmtree('input_self/tmp1')
  196. # os.mkdir('input_self/tmp1')
  197. def csv_to_text2(csv_file,text_font):
  198. text_form = []
  199. csv_use=pd.read_csv("input/主播檔.csv")
  200. b=""
  201. for i in range(len(csv_use)):
  202. # for i in range(3):
  203. b+=str(csv_use.loc[i,['字幕']].values[0])
  204. print(b)
  205. print(len(b))
  206. out = re.sub(r'[^\w\s]','',b)
  207. print(out)
  208. print(len(out))
  209. with open(csv_file, newline='',encoding="big5") as csvfile:
  210. # 讀取 CSV 檔案內容
  211. rows = csv.reader(csvfile)
  212. j=0
  213. # 以迴圈輸出每一列
  214. a = ""
  215. for row in rows:
  216. if j==0:
  217. j = 1
  218. continue
  219. start = datetime.strptime(row[1], "%H:%M:%S,%f")
  220. end = datetime.strptime(row[2], "%H:%M:%S,%f") - datetime.strptime(row[1], "%H:%M:%S,%f")
  221. end_timeStamp=end.seconds+0.000001*end.microseconds
  222. start_timeStamp=start.minute*60+start.second+ 0.000001*start.microsecond
  223. text_form.append({'text':row[3],'start':start_timeStamp,'end':end_timeStamp,'size':36,'font':text_font})
  224. a+=row[3]
  225. print(a)
  226. print(len(a))
  227. return text_form
  228. def sheet_to_text(text_font):
  229. ck_anchor = cKey(0, 255, 0, 320)
  230. text_form = []
  231. for context in wks.get_all_values():
  232. #print(context.start.minutes*60+context.start.seconds+ 0.001*context.start.milliseconds)
  233. start = datetime.strptime(context[0], "%H:%M:%S,%f")
  234. end = datetime.strptime(context[1], "%H:%M:%S,%f") - datetime.strptime(context[0], "%H:%M:%S,%f")
  235. end_timeStamp=end.seconds+0.000001*end.microseconds
  236. start_timeStamp=start.minute*60+start.second+ 0.000001*start.microsecond
  237. text_form.append({'text':context[2],'start':start_timeStamp,'end':end_timeStamp,'size':36,'font':text_font})
  238. return text_form
  239. if __name__ == '__main__':
  240. fire.Fire(text_to_short_vedio)
  241. # fire.Fire(text_to_short_vedio(
  242. # mp4_file = "output/no_captions/test.mp4",
  243. # sound_file ='output/no_captions/test.mp4',
  244. # output_filename="output/finally_output/demo.mp4",
  245. # text_font ="input_self/font/DFT_R7.ttc"))
  246. # text_to_short_vedio(
  247. # mp4_file = "output/no_captions/test.mp4",
  248. # sound_file ='output/no_captions/test.mp4',
  249. # output_filename="output/finally_output/demo.mp4",
  250. # text_font ="input_self/font/DFT_R7.ttc")
  251. # csv_to_text2("output/csv_produce/test.csv","input_self/font/DFT_R7.ttc")