咪哥雜談
1 前言 今天開始進(jìn)入近期系列文章的第一篇,如何用 Python 來(lái)實(shí)現(xiàn)錄音功能。 在開始'造輪子'之前,個(gè)人一直強(qiáng)調(diào)一個(gè)觀點(diǎn),如果有些東西已經(jīng)有了,不妨直接去 github 上搜,用現(xiàn)成的就好。關(guān)于這個(gè)想法,其實(shí) github 上已經(jīng)有人實(shí)現(xiàn)了。 但是有些細(xì)節(jié)點(diǎn),和我想的不太一樣。所以呢,我還是決定自己體驗(yàn)一波流程,順便踩踩坑,畢竟是從興趣出發(fā)。 而在上篇文章留言區(qū)中,有個(gè)小伙伴也提出,其實(shí)在去年,就已經(jīng)用樹莓派實(shí)現(xiàn)了這系列的功能,我覺(jué)得還是蠻有意思的一件事。 下面進(jìn)入正題。 2 環(huán)境準(zhǔn)備 開始之前,先要介紹的是今天的主角,PyAudio。 這款第三方庫(kù),是一個(gè)跨平臺(tái)音頻庫(kù)。 跨平臺(tái)的性質(zhì),不用多說(shuō)了吧!就是多面兼容你的系統(tǒng),不論你是用的 windows 、mac、linux,它都是支持的。 安裝命令如下: pip install PyAudio mac的同志們,需要注意下,安裝的時(shí)候可能會(huì)報(bào)錯(cuò),安裝如下即可。 brew install portaudio 完備的第三方庫(kù)都會(huì)有對(duì)應(yīng)的文檔,地址如下: https://people.csail./hubert/pyaudio/docs/#pyaudio 3 錄音功能實(shí)現(xiàn) 先來(lái)介紹一下,如何使用它來(lái)進(jìn)行錄制音頻功能! PS: 音頻方面的東西,我之前也沒(méi)過(guò)多了解,近期寫了 PyAudio 庫(kù)的代碼實(shí)現(xiàn)后才發(fā)現(xiàn),要想明白代碼的含義,還要有一些音頻方面的知識(shí)作為前置儲(chǔ)蓄,所以下面我會(huì)結(jié)合代碼去通俗講解,若有哪里不對(duì)的地方,歡迎評(píng)論區(qū)留言指出! 先來(lái)看代碼。 設(shè)定參數(shù): CHUNK = 1024 # 每個(gè)緩沖區(qū)的幀數(shù)FORMAT = pyaudio.paInt16 # 采樣位數(shù)CHANNELS = 1 # 單聲道RATE = 44100 # 采樣頻率 設(shè)定具體實(shí)現(xiàn)的參數(shù),分別有 緩沖區(qū)幀數(shù)、采樣位數(shù)、聲道模式、采樣頻率。 具體實(shí)現(xiàn)錄音代碼: def record_audio(wave_out_path, record_second): ''' 錄音功能 ''' p = pyaudio.PyAudio() # 實(shí)例化對(duì)象 stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True, frames_per_buffer=CHUNK) # 打開流,傳入響應(yīng)參數(shù) wf = wave.open(wave_out_path, 'wb') # 打開 wav 文件。 wf.setnchannels(CHANNELS) # 聲道設(shè)置 wf.setsampwidth(p.get_sample_size(FORMAT)) # 采樣位數(shù)設(shè)置 wf.setframerate(RATE) # 采樣頻率設(shè)置 for _ in range(0, int(RATE * record_second / CHUNK)): data = stream.read(CHUNK) wf.writeframes(data) # 寫入數(shù)據(jù) stream.stop_stream() # 關(guān)閉流 stream.close() p.terminate() wf.close() 先用正常代碼邏輯思維解釋下,其中涉及到的專業(yè)名詞,繼續(xù)往下看,后面會(huì)有相應(yīng)的解釋。 首先對(duì) pyaudio 庫(kù)進(jìn)行實(shí)例化。用其生成的實(shí)例化對(duì)象對(duì)數(shù)據(jù)流進(jìn)行相應(yīng)的打開,也就是 open 函數(shù)。在這塊,分別傳入了參數(shù),采樣位數(shù)、聲道、采樣頻率,以及最后的緩沖區(qū)幀數(shù)。 調(diào)用 Python 自帶的 wave 庫(kù),再次進(jìn)行寫入 wav 的相關(guān)設(shè)置。此處的操作類似 Python 寫 txt ,只不過(guò)多了點(diǎn)音頻設(shè)置而已。 用 采樣頻率 * 音頻秒數(shù)/ 每個(gè)緩沖區(qū)幀數(shù) ,得到的就是你要寫入多少個(gè)塊緩沖區(qū)的數(shù)量。最終,只需要每次循環(huán)寫入固定的 1024,一共循環(huán)得出的多少個(gè)塊緩沖區(qū)。即可得到最終的數(shù)據(jù)。 這里的公式計(jì)算,如果在不了解下述基礎(chǔ)概念之前,是很難理解的。 4 音頻基礎(chǔ)知識(shí)普及 看了上面的代碼解釋,是不是一臉懵逼。來(lái)普及下所涉及到的專業(yè)名詞。 首先, wav 和 mp3 的后綴結(jié)尾,有什么不同? 其次,關(guān)鍵的名詞解釋。 采樣位數(shù):可以理解數(shù)字音頻設(shè)備處理聲音的解析度,即對(duì)聲音的辨析度。就像表示顏色的位數(shù)一樣(8位表示256種顏色,16位表示65536種顏色),有8位,16位等。這個(gè)數(shù)越大,解析度就越高,錄制和回放的聲音也就越真實(shí)。 采樣頻率:就是對(duì)聲音信息1秒鐘采樣多少次,以記錄成數(shù)字信息。如CD音頻是44.1KHz采樣率,它對(duì)聲音以每秒44100次的頻率來(lái)記錄信息。原則上采樣率越高,聲音的質(zhì)量越好。 截取了一段百度百科的例子,關(guān)于采樣頻率的設(shè)定,代碼中選擇的即 44100 Hz 。 每個(gè)緩沖區(qū)幀數(shù):通俗的舉個(gè)例子,你手里有 102400 塊錢,現(xiàn)在要上交給女朋友。但是,你心想一口氣全給她,怕?lián)伪怂腻X包。于是你定了一個(gè)值,每次只給她 1024 元。 這里的 1024 元即每個(gè)緩存區(qū)的幀數(shù)。你想全部上交,需要幾次才能完成呢?是不是得重復(fù)上交這個(gè)動(dòng)作 100 次!此時(shí),這里的 100 次,便對(duì)應(yīng)了上述代碼的循環(huán)次數(shù),即公式算出來(lái)的有多少個(gè)塊緩存區(qū)。 弄懂音頻基礎(chǔ)知識(shí)后,再去回看代碼,你會(huì)發(fā)現(xiàn)那些參數(shù)的意義就一目了然了。 5 播放功能實(shí)現(xiàn) 有了以上知識(shí)點(diǎn),對(duì)于讀文件來(lái)說(shuō),就相當(dāng) easy 了!直接放上核心代碼: def play_audio(wave_input_path): p = pyaudio.PyAudio() # 實(shí)例化 wf = wave.open(wave_input_path, 'rb') # 讀 wav 文件 stream = p.open(format=p.get_format_from_width(wf.getsampwidth()), channels=wf.getnchannels(), rate=wf.getframerate(), output=True) data = wf.readframes(CHUNK) # 讀數(shù)據(jù) while len(data) > 0: stream.write(data) data = wf.readframes(CHUNK) stream.stop_stream() # 關(guān)閉資源 stream.close() p.terminate() 讀文件的話,沒(méi)有什么可講的,我是直接從官方文檔的例子中 copy 的,修改了一下相應(yīng)的參數(shù),即可實(shí)現(xiàn)。 6 總結(jié) 總的來(lái)說(shuō),音頻的操作,Python中的 PyAudio 庫(kù)是非常友好的,當(dāng)然,經(jīng)過(guò)各種查閱資料,發(fā)現(xiàn)在寫入音頻文件時(shí),不同人有不同的寫法,而文中的這套公式算法,應(yīng)該是較為簡(jiǎn)潔的一種。 放上一段,我用 Python 錄制的 wav 音頻文件。短暫的 3 s。 老規(guī)矩,有想要本章全部源碼的同學(xué),后臺(tái)回復(fù) 音頻 ,即可獲得地址。 文中關(guān)于音頻的解釋,哪里有錯(cuò)誤,歡迎評(píng)論區(qū)留言指出! ▼ 往期精彩回顧 ▼ |
|
來(lái)自: xvdo > 《python編程學(xué)習(xí)》