Python音頻處理庫pydub的使用示例詳解
以前我們介紹過 moviepy,它是一個(gè)處理視頻的第三方庫,基于 ffmpeg。那么本次來分享一個(gè)處理音頻的庫 pydub,它同樣是對(duì) ffmpeg 進(jìn)行的一個(gè)封裝。
既然是封裝,那就說明實(shí)際處理音頻的還是 ffmpeg,所以 pip install pydub 之后,我們還要安裝 ffmpeg,直接去官網(wǎng)下載即可。
然后將這些可執(zhí)行文件所在的目錄配置到環(huán)境變量中就可以了。
打開音頻文件
音頻有很多種格式,比如 wav、mp3、ogg 等等,只要是 ffmpeg 支持的文件格式都可以打開,而 ffmpeg 基本支持所有主流的音頻格式。
from pydub import AudioSegment # 打開 mp3 文件 AudioSegment.from_mp3("1.mp3") # 打開 wav 文件 AudioSegment.from_wav("1.wav") # 打開 ogg 文件 AudioSegment.from_ogg("1.ogg") # 以上所有方法都調(diào)用了 from_file,等價(jià)于 AudioSegment.from_file("1.mp3", "mp3") AudioSegment.from_file("1.wav", "wav") AudioSegment.from_file("1.ogg", "ogg") # 由于 mp3、wav、ogg 文件很常見,所以有單獨(dú)的方法 # 但還有不常見的音頻格式,比如蘋果手機(jī)自帶的錄音軟件導(dǎo)出的就是 m4a 格式 # 此時(shí)就只能使用 from_file 打開了 AudioSegment.from_file("1.m4a", "m4a")
注意:在讀取文件的時(shí)候,格式一定要匹配,否則報(bào)錯(cuò)。舉個(gè)例子:
from pydub import AudioSegment try: AudioSegment.from_wav("高梨康治 - 百鬼夜行.mp3") except Exception as e: print(e) """ Decoding failed. ffmpeg returned error code: 1 Output from ffmpeg/avlib: b'...Invalid data found when processing input\r\n """
我們的音頻是 mp3 格式的,但是卻調(diào)用了 from_wav,所以會(huì)報(bào)錯(cuò)。當(dāng)然也不要覺得將文件擴(kuò)展名改成 wav 就萬事大吉了,因?yàn)槲募念愋腿Q于它存儲(chǔ)的字節(jié)流,而不是擴(kuò)展名。
from pydub import AudioSegment song = AudioSegment.from_mp3("高梨康治 - 百鬼夜行.mp3") print(song) """ <pydub.audio_segment.AudioSegment object at 0x0000021782910C40> """
返回的是一個(gè) AudioSegment 對(duì)象,它就是音頻讀取之后的結(jié)果,通過該對(duì)象我們可以對(duì)音頻進(jìn)行各種操作,比如增加音量、淡入淡出等等。
并且這些操作都是鏈?zhǔn)降?,每一個(gè)操作都會(huì)返回一個(gè)新的對(duì)象,不會(huì)修改原來的對(duì)象。所以我們在操作的時(shí)候,可以一直寫下去,比如 song.xxx.xxx,不用每一次操作都重新賦值一個(gè)變量。
注意:pydub 做的任何操作,只要和時(shí)間相關(guān),那么單位都是毫秒。
下面我們來看看它都支持哪些操作。
截取某一個(gè)片段
對(duì)音頻進(jìn)行切片,這是一個(gè)非常常用的操作,一個(gè)長音頻,我們可能只要前 5 秒,或者后 5 秒等等。
# 截取前 5 秒 first_5_seconds = song[: 5 * 1000] # 截取后 5 秒 last_5_seconds = song[-5000:]
返回的都是新的 AudioSegment 對(duì)象,保存之后正好是原始音頻文件的前 5 秒和后 5 秒,關(guān)于保存文件后面會(huì)說。
音量增加和減小
我們可以讓音量放大和縮小,并且實(shí)現(xiàn)起來也非常簡單。
# 聲音增大 9 分貝 first_5_seconds = first_5_seconds + 9 # 聲音減小 7 分貝 last_5_seconds = last_5_seconds - 7
怎么樣,是不是非常簡單呢?
音頻拼接
估計(jì)有人猜到做法了,沒錯(cuò),直接相加即可。
song_first_last = first_5_seconds + last_5_seconds
此時(shí) song_first_last 就是由原始音頻的前 5 秒放大 9 分貝,和原始音頻的后 5 秒減小 7 分貝組合而成的新的音頻(AudioSegment 對(duì)象)。
淡入淡出
song_first_last = first_5_seconds.append(last_5_seconds, crossfade=1500)
調(diào)用 append 也相當(dāng)于將音頻組合在一起,但是這種方式可以增加一些淡入淡出的效果。當(dāng)然我們也可以手動(dòng)實(shí)現(xiàn):
song_first_last = first_5_seconds.fade_in(2000) + last_5_seconds.fade_out(3000)
前 5 秒和后 5 秒拼接起來得到 10 秒鐘的音頻,并且前 2 秒淡入,后 3 秒淡出。
片段重復(fù)
將一個(gè)片段重復(fù) n 遍。
repeat_5 = song[: 3000] * 5
將前 3 秒重復(fù)了 5 遍,等于把 song[: 3000] 重復(fù)相加 5 次。
反轉(zhuǎn)音頻
說白了就是倒放。
song_reverse = song.reverse()
兩個(gè)音頻重疊播放
比如你有兩個(gè)音頻,一個(gè)是臺(tái)詞,一個(gè)是背景音樂,你需要將它們合并為一個(gè)音頻。
from pydub import AudioSegment song1 = AudioSegment.from_ogg("臺(tái)詞.ogg") song2 = AudioSegment.from_ogg("背景音樂.ogg") # 將 song1 和 song2 合并在一起 # 并且在 song1 的 5 秒后,開始播放 song2,position 默認(rèn)為 0 song1.overlay(song2, position=5000)
聲道分離
關(guān)于聲道,我們一會(huì)兒解釋。
from pydub import AudioSegment song = AudioSegment.from_ogg("高梨康治 - 百鬼夜行.mp3") # 聲道的分離,得到兩個(gè)不同聲道對(duì)應(yīng)的 AudioSegment 對(duì)象 left_channel, right_channel = song.split_to_mono()
獲取音頻的某一幀
song.get_frame(1) # 獲取第一幀
獲取音頻屬性
下面我們來獲取音頻的一些屬性,不過在獲取之前,先介紹一下音頻屬性的一些細(xì)節(jié)。
采樣頻率:又被稱作取樣頻率,是單位時(shí)間內(nèi)的采樣次數(shù),決定了數(shù)字化音頻的質(zhì)量。采樣頻率越高,數(shù)字化音頻的質(zhì)量越好,還原的波形越完整,播放的聲音越真實(shí),當(dāng)然所占的大小也就越大。根據(jù)奎特采樣定理,要從采樣中完全恢復(fù)原始信號(hào)的波形,采樣頻率要高于聲音中最高頻率的兩倍。人耳可聽到的聲音的頻率范圍是在 16 赫茲到 20 千赫茲之間,因此要將聽到的原聲音真實(shí)地還原出來,采樣頻率必須大于 40千赫茲。而 44千赫茲 的音頻可以達(dá)到 CD 的音質(zhì),當(dāng)然可以更高,只不過高于 48 千赫茲 的采樣頻率人耳很難分別,沒有實(shí)際意義。
采樣位數(shù):也叫量化位數(shù)(單位:比特),是存儲(chǔ)每個(gè)采樣值所用的二進(jìn)制位數(shù),采樣值反映了聲音的波動(dòng)狀態(tài),采樣位數(shù)決定了量化精度。采樣位數(shù)越長,量化的精度就越高,還原的波形曲線越真實(shí),產(chǎn)生的量化噪音越小,回放的效果越真實(shí)。常用的量化位數(shù)有 4、8、12、16、24等等,量化位數(shù)與聲卡的位數(shù)和編碼有關(guān)。
聲道數(shù):使用的聲音通道的個(gè)數(shù),也是采樣時(shí)所產(chǎn)生的聲音波形個(gè)數(shù)。播放聲音時(shí),單聲道的 wav 一般使用一個(gè)喇叭發(fā)聲,立體聲的 wav 可以使用兩個(gè)喇叭發(fā)聲。記錄聲音時(shí),單聲道每次產(chǎn)生一個(gè)波形的數(shù)據(jù);雙聲道每次產(chǎn)生兩個(gè)波形的數(shù)據(jù),當(dāng)然最終音頻所占的存儲(chǔ)空間也會(huì)增加一倍。
比特率:比特率是指每秒傳送的比特(bit)數(shù),單位為 bps(Bit Per Second),比特率越高,傳送的數(shù)據(jù)越大。在音頻、視頻領(lǐng)域,比特率又被稱為碼率、位率、位速(這四個(gè)老鐵是同一個(gè)東西,只是不同領(lǐng)域、不同翻譯造就了這么多的名詞)。比特率表示經(jīng)過編碼(壓縮)后的音、視頻數(shù)據(jù)每秒鐘需要用多少個(gè)比特來表示。比特率與音、視頻壓縮的關(guān)系,簡單來說就是比特率越高,音頻、視頻的質(zhì)量就越好,但編碼后的文件就越大;如果比特率越少則情況剛好相反,比特率 = 采樣頻率 * 采樣位數(shù) * 聲道數(shù)。
from pydub import AudioSegment song = AudioSegment.from_mp3("高梨康治 - 百鬼夜行.mp3") # 聲道數(shù), 1 表示單聲道, 2 表示雙聲道 print(song.channels) # 2 # 采樣寬度, 采樣位數(shù)除以 8 就是采樣寬度了, 因?yàn)橐粋€(gè)字節(jié)有 8 位 # 同理采樣寬度乘以 8 就是采樣位數(shù),當(dāng)前音頻是 16 位的 print(song.sample_width) # 2 print(song.sample_width * 8) # 16 # 采樣頻率, 采樣頻率等于幀速率 print(song.frame_rate) # 44100 # 塊對(duì)齊之后的大小, 或者一幀的字節(jié)數(shù) # 等于 通道數(shù) * 采樣位數(shù) / 8, 或者 通道數(shù) * 采樣寬度 print(song.frame_width) # 4 print(song.channels * song.sample_width) # 4 # 字節(jié)率, 等于 采樣頻率 * 聲道數(shù)量 * 采樣寬度(采樣位數(shù) / 8), 可以直接計(jì)算得到 print(song.frame_rate * song.channels * song.sample_width) # 176400 # 時(shí)長(單位秒) print(song.duration_seconds) # 87.8225850340136 # 幀數(shù)目 print(song.frame_count()) # 3872976.0 # 原始的音頻數(shù)據(jù), 不打印了 song.raw_data
音頻導(dǎo)出
我們對(duì)音頻進(jìn)行了一些操作之后,怎么保存到本地呢?這也是關(guān)鍵的一部分,不然你處理完了沒有用啊。很簡單,直接調(diào)用 AudioSegment 對(duì)象的 export 方法即可。
from pydub import AudioSegment song = AudioSegment.from_mp3("高梨康治 - 百鬼夜行.mp3") song.export("百鬼夜行.wav", "wav")
指定文件名和保存的類型即可,注意:第二個(gè)參數(shù)表示保存的音頻的類型,必須要指定正確。如果不指定那么默認(rèn)是 mp3,即便我們第一個(gè)參數(shù)的文件名結(jié)尾是 .wav,但是保存的時(shí)候仍是 mp3。
所以基于 pydub 可以很容易地實(shí)現(xiàn)音頻格式轉(zhuǎn)換。
修改屬性
有時(shí)我們需要改變文件的格式,但有時(shí)也需要改變文件的屬性。比如某個(gè) MP3 文件的采樣頻率有點(diǎn)高,我們需要降低一些,或者雙聲道變成單聲道等等,這個(gè)時(shí)候該怎么做呢?
from pydub import AudioSegment song = AudioSegment.from_mp3("高梨康治 - 百鬼夜行.mp3") print(song.channels) # 2 # 將通道設(shè)置為 1, 然后導(dǎo)出 song.set_channels(1).export("高梨康治 - 百鬼夜行_1.mp3", "mp3") # 重新讀取, 查看通道 print( AudioSegment.from_mp3(r"高梨康治 - 百鬼夜行_1.mp3").channels ) # 1
1 表示單聲道,2 表示雙聲道,從單聲道轉(zhuǎn)成雙聲道不會(huì)有任何的改變,但從雙聲道轉(zhuǎn)成單聲道可能會(huì)導(dǎo)致質(zhì)量損失(當(dāng)左右聲道不同時(shí))。
單聲道:只用一條音頻通道記錄聲音,是最古老、最基礎(chǔ)的聲音記錄方式。單聲道因?yàn)橹挥幸粭l音頻通道,所以我們的大腦接收的左右耳的信息沒有差異,聽覺系統(tǒng)就不會(huì)產(chǎn)生心理聲學(xué)的定位,所以不會(huì)有寬度及深度的差異。只能感受到聲音、音樂的前后位置及音色、音量的大小,而不能感受到聲音從左到右等橫向的移動(dòng)。效果相對(duì)于真實(shí)的自然聲來說,是簡單化的,是失真了的。所以聽出來的聲音干澀,沒有層次感,沒有現(xiàn)場感,一般用來聽新聞廣播,因?yàn)閱温暤佬盘?hào)簡單不易丟失。原理是把來自不同方位的音頻信號(hào)混合后統(tǒng)一由錄音器材把它記錄下來,再由一只音箱進(jìn)行重放。
雙聲道:人們聽到聲音時(shí)可以根據(jù)左耳和右耳對(duì)聲音的相位差來判斷聲源的具體位置,在電路上它們往往各自傳遞的電信號(hào)是不一樣的。相當(dāng)于實(shí)現(xiàn)立體聲的原理,在空間放置兩個(gè)互成一定角度的揚(yáng)聲器,每個(gè)揚(yáng)聲器單獨(dú)由一個(gè)聲道提供信號(hào)。而每個(gè)聲道的信號(hào)在錄制的時(shí)候就經(jīng)過了處理,有些音樂就跟氣流一樣,從左到右再從右到左,因?yàn)槭莾蓚€(gè)不同的聲道,當(dāng)一個(gè)聲道的響度比另一個(gè)聲道大的時(shí)候,我們就感覺聲音好像有了方向一樣。雙聲道立體感強(qiáng),有音場,多用于音樂、CD 等專輯。基本上音樂都是雙聲道,如果是單聲道的音樂,只能說明音質(zhì)非常非常差。
注意:設(shè)置的話不要通過下面這種方式來設(shè)置。
from pydub import AudioSegment song = AudioSegment.from_mp3("高梨康治 - 百鬼夜行.mp3") song.channels = 1
因?yàn)橐粋€(gè)屬性變了,可能會(huì)影響其它的屬性,比如:幀大小,它等于 通道數(shù) 乘上 采樣寬度(采樣位數(shù) / 8),如果通道變了,那么幀大小也會(huì)受到影響。所以我們應(yīng)該通過 pydub 提供的 API 來設(shè)置,內(nèi)部會(huì)自動(dòng)幫我們處理。
from pydub import AudioSegment song = AudioSegment.from_mp3("高梨康治 - 百鬼夜行.mp3") print(song.frame_rate) # 44100 # 更改采樣頻率, 一般都是 44100, 我們可以修改為其它的值 # 注意: 并不是任意值都可以, 只能是 8000 12000 16000 24000 32000 44100 48000 之一 # 如果不是這些值當(dāng)中的一個(gè), 那么會(huì)當(dāng)中選擇與設(shè)置的值最接近的一個(gè) # 比如我們設(shè)置 18000, 那么會(huì)自動(dòng)變成 16000 song.set_frame_rate(18000).export("高梨康治 - 百鬼夜行_1.mp3", "mp3") print( AudioSegment.from_mp3(r"高梨康治 - 百鬼夜行_1.mp3").frame_rate ) # 16000
采樣頻率等于幀速率,以赫茲為單位。增大這個(gè)值通常不會(huì)導(dǎo)致質(zhì)量的下降,但降低這個(gè)值一定會(huì)導(dǎo)致質(zhì)量的下降,因?yàn)楦叩膸俾室馕吨蟮念l響特征(即可以表示更高的頻率)。
除了通道數(shù)、采樣頻率之外,我們還可以設(shè)置采樣寬度(采樣位數(shù)除以 8),對(duì)于一個(gè)音頻而言能設(shè)置這些屬性已經(jīng)足夠了。像很多大廠提供的音頻識(shí)別服務(wù),也會(huì)對(duì)音頻屬性有嚴(yán)格的限制,而限制的屬性也基本上就這些。無非是通道、采樣頻率、采樣位數(shù)等等。
from pydub import AudioSegment song = AudioSegment.from_mp3("高梨康治 - 百鬼夜行.mp3") print(song.sample_width) # 2 song.set_sample_width(3).export("高梨康治 - 百鬼夜行_1.mp3", "mp3") print( AudioSegment.from_mp3(r"高梨康治 - 百鬼夜行_1.mp3").sample_width ) # 2
從打印的結(jié)果上來看,我們似乎沒有設(shè)置成功,因?yàn)檫@和音頻本身也是有相應(yīng)關(guān)系的??赡芤纛l本身的采樣寬度就只能是 2,不過絕大部分音頻的采樣寬度都是 2,即采樣位數(shù)為 16。
export 的其它參數(shù)
我們導(dǎo)出音頻的時(shí)候使用的是 export 方法,這里面還可以接收其它參數(shù),先來看看我們導(dǎo)出的音頻的原始的音頻之間的差異。
我們看到原始的音頻有很多其它信息,比如作曲人、專輯等等,但是我們導(dǎo)出的沒有,那么可不可以設(shè)置呢。答案是可以的,在導(dǎo)出的時(shí)候加上一個(gè) tags 參數(shù)即可。
from pydub import AudioSegment song = AudioSegment.from_mp3(r"高梨康治 - 百鬼夜行.mp3") song.export("高梨康治 - 百鬼夜行_1.mp3", "mp3", tags={"artist": "古明地覺", "album": "地靈殿專輯", "title": "好聽的百鬼夜行", "comments": "媽耶, 真好聽"})
再來看看效果。
其它的屬性可以單擊右鍵,然后點(diǎn)擊屬性查看。對(duì)了還有圖片,如果在導(dǎo)出的時(shí)候想要自定義封面的話,可以通過 cover 參數(shù),傳遞一個(gè)圖片文件地址即可。
另外,我們這里導(dǎo)出的文件要比原始文件小很多,原因在于比特率不一樣。原始的音頻的比特率是 320kbps,而我們導(dǎo)出的音頻的比特率要小很多。因?yàn)楸忍芈时硎疽纛l一秒所需的比特?cái)?shù),比特率越小,顯然文件就越小。而我們在導(dǎo)出的時(shí)候也是可以修改比特率的:
song.export("高梨康治 - 百鬼夜行_1.mp3", "mp3", bitrate="320k")
以上就是Python音頻處理庫pydub的使用示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Python pydub的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
python中關(guān)于property的最詳細(xì)使用方法
這篇文章主要介紹了python中關(guān)于property的最詳細(xì)使用方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04詳解Python實(shí)現(xiàn)字典合并的四種方法
這篇文章主要為大家詳細(xì)介紹了Python的合并字典的四種方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-03-03python實(shí)現(xiàn)將代碼轉(zhuǎn)成不可反編譯的pyd文件
pyc文件用于提高加載速度,部分源碼可讀,而pyd文件提供更好的保密性,是編譯后的二進(jìn)制動(dòng)態(tài)鏈接庫,當(dāng)有些模塊的代碼需要一定的保密性,這個(gè)時(shí)候就需要考慮pyc和pyd文件了,本文給大家介紹了python實(shí)現(xiàn)將代碼轉(zhuǎn)成不可反編譯的pyd文件,需要的朋友可以參考下2024-11-11