自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

分享一個(gè) Python 處理音頻的庫(kù)

開發(fā) 前端
以前我們介紹過(guò) moviepy,它是一個(gè)處理視頻的第三方庫(kù),基于 ffmpeg。那么本次來(lái)分享一個(gè)處理音頻的庫(kù) pydub,它同樣是對(duì) ffmpeg 進(jìn)行的一個(gè)封裝。

以前我們介紹過(guò) moviepy,它是一個(gè)處理視頻的第三方庫(kù),基于 ffmpeg。那么本次來(lái)分享一個(gè)處理音頻的庫(kù) pydub,它同樣是對(duì) ffmpeg 進(jìn)行的一個(gè)封裝。

既然是封裝,那就說(shuō)明實(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 就萬(wàn)事大吉了,因?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é)果,通過(guò)該對(duì)象我們可以對(duì)音頻進(jìn)行各種操作,比如增加音量、淡入淡出等等。

并且這些操作都是鏈?zhǔn)降?,每一個(gè)操作都會(huì)返回一個(gè)新的對(duì)象,不會(huì)修改原來(lái)的對(duì)象。所以我們?cè)诓僮鞯臅r(shí)候,可以一直寫下去,比如 song.xxx.xxx,不用每一次操作都重新賦值一個(gè)變量。

注意:pydub 做的任何操作,只要和時(shí)間相關(guān),那么單位都是毫秒。

下面我們來(lái)看看它都支持哪些操作。

截取某一個(gè)片段

對(duì)音頻進(jìn)行切片,這是一個(gè)非常常用的操作,一個(gè)長(zhǎng)音頻,我們可能只要前 5 秒,或者后 5 秒等等。
# 截取前 5 秒
first_5_seconds = song[: 5 * 1000]

# 截取后 5 秒
last_5_seconds = song[-5000:]

返回的都是新的 AudioSegment 對(duì)象,保存之后正好是原始音頻文件的前 5 秒和后 5 秒,關(guān)于保存文件后面會(huì)說(shuō)。

音量增加和減小

我們可以讓音量放大和縮小,并且實(shí)現(xiàn)起來(lái)也非常簡(jiǎn)單。
# 聲音增大 9 分貝
first_5_seconds = first_5_seconds + 9

# 聲音減小 7 分貝
last_5_seconds = last_5_seconds - 7

怎么樣,是不是非常簡(jiǎn)單呢?

音頻拼接

估計(jì)有人猜到做法了,沒(méi)錯(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 秒拼接起來(lái)得到 10 秒鐘的音頻,并且前 2 秒淡入,后 3 秒淡出。

重復(fù)

將一個(gè)片段重復(fù) n 遍。
repeat_5 = song[: 3000] * 5

將前 3 秒重復(fù)了 5 遍,等于把 song[: 3000] 重復(fù)相加 5 次。

反轉(zhuǎn)音頻

說(shuō)白了就是倒放。
song_reverse = song.reverse()

兩個(gè)音頻重疊播放

比如你有兩個(gè)音頻,一個(gè)是臺(tái)詞,一個(gè)是背景音樂(lè),你需要將它們合并為一個(gè)音頻。
from pydub import AudioSegment

song1 = AudioSegment.from_ogg("臺(tái)詞.ogg")
song2 = AudioSegment.from_ogg("背景音樂(lè).ogg")
# 將 song1 和 song2 合并在一起
# 并且在 song1 的 5 秒后,開始播放 song2,position 默認(rèn)為 0
song1.overlay(song2, positinotallow=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)  # 獲取第一幀

獲取音頻屬性

下面我們來(lái)獲取音頻的一些屬性,不過(guò)在獲取之前,先介紹一下音頻屬性的一些細(xì)節(jié)。

采樣頻率:又被稱作取樣頻率,是單位時(shí)間內(nèi)的采樣次數(shù),決定了數(shù)字化音頻的質(zhì)量。采樣頻率越高,數(shù)字化音頻的質(zhì)量越好,還原的波形越完整,播放的聲音越真實(shí),當(dāng)然所占的大小也就越大。根據(jù)奎特采樣定理,要從采樣中完全恢復(fù)原始信號(hào)的波形,采樣頻率要高于聲音中最高頻率的兩倍。人耳可聽到的聲音的頻率范圍是在 16 赫茲到 20 千赫茲之間,因此要將聽到的原聲音真實(shí)地還原出來(lái),采樣頻率必須大于 40千赫茲。而 44千赫茲 的音頻可以達(dá)到 CD 的音質(zhì),當(dāng)然可以更高,只不過(guò)高于 48 千赫茲 的采樣頻率人耳很難分別,沒(méi)有實(shí)際意義。

采樣位數(shù):也叫量化位數(shù)(單位:比特),是存儲(chǔ)每個(gè)采樣值所用的二進(jìn)制位數(shù),采樣值反映了聲音的波動(dòng)狀態(tài),采樣位數(shù)決定了量化精度。采樣位數(shù)越長(zhǎng),量化的精度就越高,還原的波形曲線越真實(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)過(guò)編碼(壓縮)后的音、視頻數(shù)據(jù)每秒鐘需要用多少個(gè)比特來(lái)表示。比特率與音、視頻壓縮的關(guān)系,簡(jiǎn)單來(lái)說(shuō)就是比特率越高,音頻、視頻的質(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í)長(zhǎng)(單位秒)
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)鍵的一部分,不然你處理完了沒(méi)有用啊。很簡(jiǎ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音頻通道,所以我們的大腦接收的左右耳的信息沒(méi)有差異,聽覺系統(tǒng)就不會(huì)產(chǎn)生心理聲學(xué)的定位,所以不會(huì)有寬度及深度的差異。只能感受到聲音、音樂(lè)的前后位置及音色、音量的大小,而不能感受到聲音從左到右等橫向的移動(dòng)。效果相對(duì)于真實(shí)的自然聲來(lái)說(shuō),是簡(jiǎn)單化的,是失真了的。所以聽出來(lái)的聲音干澀,沒(méi)有層次感,沒(méi)有現(xiàn)場(chǎng)感,一般用來(lái)聽新聞廣播,因?yàn)閱温暤佬盘?hào)簡(jiǎn)單不易丟失。原理是把來(lái)自不同方位的音頻信號(hào)混合后統(tǒng)一由錄音器材把它記錄下來(lái),再由一只音箱進(jìn)行重放。

雙聲道:人們聽到聲音時(shí)可以根據(jù)左耳和右耳對(duì)聲音的相位差來(lái)判斷聲源的具體位置,在電路上它們往往各自傳遞的電信號(hào)是不一樣的。相當(dāng)于實(shí)現(xiàn)立體聲的原理,在空間放置兩個(gè)互成一定角度的揚(yáng)聲器,每個(gè)揚(yáng)聲器單獨(dú)由一個(gè)聲道提供信號(hào)。而每個(gè)聲道的信號(hào)在錄制的時(shí)候就經(jīng)過(guò)了處理,有些音樂(lè)就跟氣流一樣,從左到右再?gòu)挠业阶?,因?yàn)槭莾蓚€(gè)不同的聲道,當(dāng)一個(gè)聲道的響度比另一個(gè)聲道大的時(shí)候,我們就感覺聲音好像有了方向一樣。雙聲道立體感強(qiáng),有音場(chǎng),多用于音樂(lè)、CD 等專輯?;旧弦魳?lè)都是雙聲道,如果是單聲道的音樂(lè),只能說(shuō)明音質(zhì)非常非常差。

注意:設(shè)置的話不要通過(guò)下面這種方式來(lái)設(shè)置。

from pydub import AudioSegment

song = AudioSegment.from_mp3("高梨康治 - 百鬼夜行.mp3")
song.channels = 1

因?yàn)橐粋€(gè)屬性變了,可能會(huì)影響其它的屬性,比如:幀大小,它等于 通道數(shù) 乘上 采樣寬度(采樣位數(shù) / 8),如果通道變了,那么幀大小也會(huì)受到影響。所以我們應(yīng)該通過(guò) pydub 提供的 API 來(lái)設(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è)
# 比如我們?cè)O(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)格的限制,而限制的屬性也基本上就這些。無(wú)非是通道、采樣頻率、采樣位數(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é)果上來(lái)看,我們似乎沒(méi)有設(shè)置成功,因?yàn)檫@和音頻本身也是有相應(yīng)關(guān)系的??赡芤纛l本身的采樣寬度就只能是 2,不過(guò)絕大部分音頻的采樣寬度都是 2,即采樣位數(shù)為 16。

export 的其它參數(shù)

我們導(dǎo)出音頻的時(shí)候使用的是 export 方法,這里面還可以接收其它參數(shù),先來(lái)看看我們導(dǎo)出的音頻的原始的音頻之間的差異。

我們看到原始的音頻有很多其它信息,比如作曲人、專輯等等,但是我們導(dǎo)出的沒(méi)有,那么可不可以設(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": "媽耶, 真好聽"})

再來(lái)看看效果。

其它的屬性可以單擊右鍵,然后點(diǎn)擊屬性查看。對(duì)了還有圖片,如果在導(dǎo)出的時(shí)候想要自定義封面的話,可以通過(guò) cover 參數(shù),傳遞一個(gè)圖片文件地址即可。

另外,我們這里導(dǎo)出的文件要比原始文件小很多,原因在于比特率不一樣。原始的音頻的比特率是 320kbps,而我們導(dǎo)出的音頻的比特率要小很多。因?yàn)楸忍芈时硎疽纛l一秒所需的比特?cái)?shù),比特率越小,顯然文件就越小。而我們?cè)趯?dǎo)出的時(shí)候也是可以修改比特率的:

song.export("高梨康治 - 百鬼夜行_1.mp3",
            "mp3",
            bitrate="320k")

以上就是 pydub 對(duì)音頻的一些常見操作,總的來(lái)說(shuō)支持的功能還是比較多的。如果你對(duì)音視頻處理感興趣,可以在這一領(lǐng)域深耕下去,因?yàn)樯孀阍擃I(lǐng)域的人確實(shí)不多。

責(zé)任編輯:華軒 來(lái)源: 古明地覺的編程教室
相關(guān)推薦

2018-11-16 17:00:05

Python腳本數(shù)據(jù)分析

2019-08-02 15:39:06

PythonLinuxJSON

2014-07-08 09:27:24

SQLSERVER腳本

2012-04-10 13:37:28

JavaScript

2024-07-02 11:29:28

Typer庫(kù)Python命令

2022-07-21 09:50:20

Python日期庫(kù)pendulum

2024-04-01 05:00:00

GUIpythonDearPyGui

2022-05-26 05:44:52

PythonPyScript框架

2024-04-10 12:39:08

機(jī)器學(xué)習(xí)庫(kù)python

2021-07-29 10:46:56

Python內(nèi)置庫(kù)代碼

2021-08-27 09:48:18

Pythonitertools代碼

2021-05-19 22:23:56

PythonJavaScript數(shù)據(jù)

2024-09-24 10:16:13

PythonWord文檔

2013-03-18 10:31:22

JS異常

2021-03-10 18:26:49

Tensorflow語(yǔ)音識(shí)別音頻處理

2024-02-07 08:52:07

VueUI 庫(kù)Vue.js

2022-05-26 08:12:52

debugSpringFeign

2010-03-02 16:33:14

linux數(shù)據(jù)備份

2016-12-21 11:35:55

Python程序員庫(kù)

2023-12-22 14:50:02

開發(fā)PythonHypothesis
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)