Python玩轉各種多媒體,視頻、音頻到圖片

我們經常會遇到一些對於多媒體文件修改的操作,像是對視頻文件的操作:視頻剪輯、字幕編輯、分離音頻、視頻音頻混流等。又比如對音頻文件的操作:音頻剪輯,音頻格式轉換。再比如我們最常用的圖片文件,格式轉換、各個屬性的編輯等。因為多媒體文件的操作眾多,本文選取一些極具代表性的操作,以代碼的形式實現各個操作。

一、圖片操作

操作圖片的模塊有許多,其中比較常用的兩個就是Pillow和 opencv,兩個模塊各有優勢。其中opencv是計算機視覺處理的開源模塊,應用的範圍更加廣泛,從圖像處理到視頻處理,再到物體檢測等。而pillow相比直線就單純的多,其大多數操作都是圍繞圖像而展開的。

1.1、格式轉換

圖片格式有多種多樣,最直觀的感受就是圖片後綴。而格式之間的差異不僅僅是後綴的差異,最為明顯的就是png格式圖片,同其它圖片有著最為直觀的區別。下面我們就看看在Python中如何轉換格式,我們先安裝pillow模塊:

pip install pillow

然後看看如何導入模塊以及如何讀取圖像:

from PIL import Image

# 讀取圖像

img = Image.open('ycjc.jpg')

# 顯示圖像

img.show()

我們有了上面的基礎操作之後,就可以開始進行格式轉換了,我們用有村大妹子的圖片作為素材:

Python玩轉各種多媒體,視頻、音頻到圖片

我們可以看到這是一張白色背景的圖片,我們將它轉成png看看效果:

from PIL import Image

# 讀取圖像

img = Image.open('ycjc.jpg')

# 格式轉換,其中A為透明度

png = img.convert('RGBA')

# 保存圖像,因為是RGBA格式,所以後綴應該為png

png.save('ycjc.png')

輸出的圖片我就不放了,我們觀察輸出圖片會發現,白色背景好像變透明瞭。不要懷疑,這只是心理作用,其實圖片看上去是不會又任何變化的。但是實際上圖片從原來的RGB三個色道變成了RGBA四個色道,我們會發現,圖片變大了:

Python玩轉各種多媒體,視頻、音頻到圖片


雖然A色道的透明度全部都是0,但是實際上還是存在這個色道,所以大小方面有了明顯的增加。更多轉換模式可以產考超全Python圖像處理講解(多圖預警)。

1.2、圖片裁剪

圖片裁剪的操作也非常常用,我們來看看pillow如何裁剪圖片:

from PIL import Image

# 讀取圖像

img = Image.open('ycjc.jpg')

# 裁剪圖像,調用crop方法,傳入裁剪區域的元組

img_crop = img.crop((100, 100, 400, 400))

# 保存裁剪後的圖像

img_crop.save('ycjc_crop.jpg')

我們調用crop方法,傳入裁剪區域的元組進行裁剪,元組的內容為左上角的座標(前兩個參數)即右下角的座標(後兩個參數)。效果圖如下:

Python玩轉各種多媒體,視頻、音頻到圖片


1.3、截屏

雖然算不上是圖像操作,但是還是個非常實用的操作。我們實現截屏是通過ImageGrap類實現的:

from PIL import ImageGrab

# 截取全屏

im = ImageGrab.grab()

# 保存圖像

im.save('win.png')

除了截取全屏我們也可以區域截屏:

im =ImageGrab.grab((300, 100, 1400, 600))

參數元組含義與crop方法一致。

除了上述操作,還有更多像是添加濾鏡、對比度調節、亮度調節、色彩調節等,由於內容眾多,所以不在本文詳細討論。

二、音頻操作

音頻的操作也比較繁多,我們最常用到的就是音頻剪輯和音量調節了。我們這裡使用pydub模塊來進行音頻文件的操作。

2.1、pydub的安裝以及讀取音頻

安裝我們還是使用pip:

pip install pydub

然後我們來讀取一個wav文件:

from pydub import AudioSegment

# 讀取wav格式的音頻文件

music = AudioSegment.from_wav('百年孤獨.wav')

這樣我們就完成了音頻文件的讀取,wav文件是一種未經壓縮的文件,我們可以通過pydub直接讀取。讀取其它類型的文件pydub同樣提供了相應的方法:

music = AudioSegment.from_mp3('music.mp3')

music = AudioSegment.from_ogg("music.ogg")

music = AudioSegment.from_flv("music.flv")

因為在實際操作過程中遇到了一個未找明緣由的錯誤,所以本文的音頻操作只針對wav格式。

2.2、音頻剪切

音頻剪輯的實現我們是通過類似ndarray的中括號操作的:

# 截取前20秒

clip = music[:20*1000]

# 截取後20秒

clip = music[-20000:]

# 從第20秒截取到第40秒

clip = music[20*1000:40*1000]

剪切好的片段我們可以另外存一個文件:

# 保存文件為clip.mp3,格式為mp3

clip.export('clip.mp3', format='mp3')

3.3、增加/減少音量

音量的控制我們只需要用音頻對象加一個常數即可:

# 音量減5

music -= 5

# 音量加5

music += 5

3.4、音頻拼接

我們先看看重複拼接:

# 在音頻文件末尾重複拼接該音頻

music = music*2

拼接後的音頻的效果就是原音頻循環兩次。接下來我們看看拼接不同的音頻:

# 裁剪前20秒音頻

clip1 = music[:20*1000]

# 裁剪後20秒音頻

clip2 = music[-20*1000:]

# 拼接音頻

clip = clip1 + clip2

3.5、 交叉漸入漸出

交叉漸入漸出是一種比較柔和的音頻專場方式,在兩個音頻切換的間歇會有一個重合,用代碼實現如下:

# 截取前20秒

begin = music[20*1000:40*1000]

# 截取後20秒

end = music[-20*1000:]

# 添加交叉漸入漸出 效果

clip = begin.append(end, crossfade=1500)

我們可以看到我們一共裁剪了40秒,在生成的文件我們可以看到只有38秒,因為轉場的時候有個重合的效果。當然還有更多的操作,大家可以自己去了解。

三、視頻操作

視頻的操作可以通過moviepy和opencv進行,我們先分別安裝兩個模塊:

pip install opencv-python

pip install moviepy

3.1、視頻剪輯

相比之下moviepy操作視頻要更便利,我們看看使用moviepy如何剪輯視頻:

from moviepy.editor import *

# 剪切視屏bws.mp4中第50秒到第60秒

clip = VideoFileClip('bws.mp4').subclip(50, 60)

# 將剪切的片段保存

clip.write_videofile("clip.mp4")

3.2、提取音頻文件

在VideoFileClip類中,音頻文件作為其中的一個參數,我們可以直接獲取:

from moviepy.editor import *

# 讀取視頻文件

video = VideoFileClip('bws.mp4')

# 獲取其中音頻

audio = video.audio

# 保存音頻文件

audio.write_audiofile('audio.mp3')

3.3、混流

我們還可以將音頻同視頻混流,在moviepy中,提供了一個讀取音頻文件的類,我們設置視頻的音頻需要創建這個類的對象:

from moviepy.editor import *

# 讀取視頻

video = VideoFileClip('bws.mp4')

# 讀取音頻

audio = AudioFileClip('百年孤獨.mp3')

# 設置視頻的音頻

video = video.set_audio(audio)

# 保存新的視頻文件

video.write_videofile('bws_audio.mp4')

3.4、逐幀提取畫面

我們都知道,視頻是由一幀一幀的圖片組成的,我們也可以將畫面一幀一幀提取出來:

import cv2

# 讀取視頻

video = cv2.VideoCapture('bws.mp4')

# 逐幀讀取,當還有畫面時ret為True,frame為當前幀的ndarray對象

ret, frame = video.read()

i = 0

# 循環讀取

while ret:

i += 1

cv2.imwrite('v'+str(i) + '.jpg', frame)

ret, frame = video.read()

上述代碼就能將視屏的每一幀以圖片的形式保存下來。

3.5、截取gif

截取gif和截取視頻沒有什麼區別,不過為了減少gif的大小,我們通常會對視頻進行尺寸縮放:

from moviepy.editor import *

# 讀取視頻

video = VideoFileClip('bws.mp4')

# 裁剪視頻,並縮小一半

video = video.subclip(20, 30).resize((0.5))

# 保存gif圖片

video.write_gif('bws.gif')

在上面subclip方法中,我們可以傳入元組,例如:

video.subclip((1, 20), (2, 30))

其含義為從1分20秒截取到2分30秒。

關於多媒體的操作還有很多,到此就實現了一些比較常用,也比較實用的操作,另外還花掉了我幾個小時的時間。在排查環境中的錯誤是確實比較麻煩,但是總歸還是實驗的全部代碼,寫作不易啊


分享到:


相關文章: