1、需要安裝opencv,直接安裝pipinstallopencv-python
2、需要安裝ffmpeg,直接解壓免安裝,下載傳送門;將ffmpeg.exe的路徑復制,替換代碼開頭的ffmpeg=r'G:\ffmpeg\bin\ffmpeg.exe‘
二、源代碼
復制代碼
importos
importsubprocess
importshutil
importcv2
fromPILimportImage,ImageFont,ImageDraw
FFMPEG=r'D:\ffmpeg\bin\ffmpeg.exe'
classCodeVideo:
def__init__(self,**kwargs):
"""
:paramkwargs:
vediopath:輸入視頻文件路徑
gray:輸出視頻的顏色True灰色False彩色默認True
style:輸出視頻的代碼風格可選有0,1,2,3種默認0
clean:是否刪除臨時文件True刪除False不刪除默認True
cut:是否先對原視頻做截取處理True截取False不截取默認False
start:視頻截取開始時間點,默認00:00:00僅當iscut=True時有效
end:視頻截取結束時間點,默認00:00:14僅當iscut=True時有效
"""
self.vediopath=kwargs.get('vediopath')
self.code_color=(169,169,169)ifkwargs.get('gray',True)elseNone
self.clean=kwargs.get('clean',True)
self.cut=kwargs.get('cut',False)
self.cut_start=kwargs.get('start','00:00:00')
self.cut_end=kwargs.get('end','00:00:14')
self.ascii_char=(
list("MNHQ$OC67)oa+>!:+."),
list("MNHQ$OC67+>!:-."),
list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:oa+>!:+."),
['.',',',':',';','+','*','?','%','S','#','@'],
)[kwargs.get('style',0)]#像素對應ascii碼
defmain(self):
file_cut=self.vediopath.split('.')[0]+'_cut.mp4'
file_mp3=self.vediopath.split('.')[0]+'.mp3'
file_temp_avi=self.vediopath.split('.')[0]+'_temp.avi'
outfile_name=self.vediopath.split('.')[0]+'_code.mp4'
print("開始生成...")
ifself.cut:
print("正在截取視頻...")
self.vediocut(self.vediopath,file_cut,self.cut_start,self.cut_end)
self.vediopath=file_cut
print("正在轉換代碼圖片...")
vc=self.video2txt_jpg(self.vediopath)#視頻轉圖片,圖片轉代碼圖片
FPS=vc.get(cv2.CAP_PROP_FPS)#獲取幀率
vc.release()
print("正在分離音頻...")
self.video2mp3(self.vediopath,file_mp3)#從原視頻分離出音頻mp3
print("正在轉換代碼視頻...")
self.jpg2video(file_temp_avi,FPS)#代碼圖片轉視頻
print("正在合成目標視頻...")
self.video_add_mp3(file_temp_avi,file_mp3,outfile_name)#將音頻合成到代碼視頻
ifself.clean:#移除臨時文件
print("正在移除臨時文件...")
shutil.rmtree("Cache")
forfilein[file_cut,file_mp3,file_temp_avi]:
ifos.path.exists(file):
os.remove(file)
print("生成成功:{0}".format(outfile_name))
#將視頻拆分成圖片
defvideo2txt_jpg(self,file_name):
vc=cv2.VideoCapture(file_name)
c=1
ifvc.isOpened():
r,frame=vc.read()
ifnotos.path.exists('Cache'):
os.mkdir('Cache')
os.chdir('Cache')
else:
r=False
whiler:
cv2.imwrite(str(c)+'.jpg',frame)
self.txt2image(str(c)+'.jpg')#同時轉換為ascii圖
r,frame=vc.read()
c+=1
os.chdir('..')
returnvc
#將txt轉換為圖片
deftxt2image(self,file_name):
im=Image.open(file_name).convert('RGB')
#gif拆分后的圖像,需要轉換,否則報錯,由于gif分割后保存的是索引顏色
raw_width=im.width
raw_height=im.height
width=int(raw_width/6)
height=int(raw_height/15)
im=im.resize((width,height),Image.NEAREST)
txt=""
colors=[]
foriinrange(height):
forjinrange(width):
pixel=im.getpixel((j,i))
colors.append((pixel[0],pixel[1],pixel[2]))
if(len(pixel)==4):
txt+=self.get_char(pixel[0],pixel[1],pixel[2],pixel[3])
else:
txt+=self.get_char(pixel[0],pixel[1],pixel[2])
txt+='\n'
colors.append((255,255,255))
im_txt=Image.new("RGB",(raw_width,raw_height),(255,255,255))
dr=ImageDraw.Draw(im_txt)
#font=ImageFont.truetype(os.path.join("fonts","漢儀楷體簡.ttf"),18)
font=ImageFont.load_default().font
x=y=0
#獲取字體的寬高
font_w,font_h=font.getsize(txt[1])
font_h*=1.37#調整后更佳
#ImageDraw為每個ascii碼進行上色
foriinrange(len(txt)):
if(txt[i]=='\n'):
x+=font_h
y=-font_w
ifself.code_color:
dr.text((y,x),txt[i],fill=self.code_color)#fill=colors[i]彩色
else:
dr.text((y,x),txt[i],fill=colors[i])#fill=colors[i]彩色
y+=font_w
im_txt.save(file_name)
#將像素轉換為ascii碼
defget_char(self,r,g,b,alpha=256):
ifalpha==0:
return''
gray=int(0.2126*r+0.7152*g+0.0722*b)
unit=(256.0+1)/len(self.ascii_char)
returnself.ascii_char[int(gray/unit)]
#代碼圖片轉視頻
@staticmethod
defjpg2video(outfile_name,fps):
fourcc=cv2.VideoWriter_fourcc(*"MJPG")
images=os.listdir('Cache')
im=Image.open('Cache/'+images[0])
vw=cv2.VideoWriter(outfile_name,fourcc,fps,im.size)
os.chdir('Cache')
forimageinrange(len(images)):
frame=cv2.imread(str(image+1)+'.jpg')
vw.write(frame)
os.chdir('..')
vw.release()
#調用ffmpeg分離音頻
@staticmethod
defvideo2mp3(file_name,outfile_name):
cmdstr=f'{FFMPEG}-i{file_name}-fmp3{outfile_name}-y'
subprocess.call(cmdstr,shell=True,creationflags=0x08000000)
#調用ffmpeg給視頻添加音頻
@staticmethod
defvideo_add_mp3(file_name,mp3_file,outfile_name):
cmdstr=f'{FFMPEG}-i{file_name}-i{mp3_file}-strict-2-fmp4{outfile_name}-y'
subprocess.call(cmdstr,shell=True,creationflags=0x08000000)
#調用ffmpeg截取視頻
@staticmethod
defvediocut(file_name,outfile_name,start,end):
cmdstr=f'{FFMPEG}-i{file_name}-vcodeccopy-acodeccopy-ss{start}-to{end}{outfile_name}-y'
subprocess.call(cmdstr,shell=True,creationflags=0x08000000)
if__name__=='__main__':
vediopath=r"C:\Users\Administrator\Desktop\test.mp4"
CodeVideo(vediopath=vediopath).main()