main2.py 10 KB

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