python 錄制系統(tǒng)聲音的示例
環(huán)境準(zhǔn)備
python
- wave
- pyaudio
wave 可以通過(guò)pip直接install,在安裝pyaudio時(shí),通過(guò)正常的pip install 直接安裝一直處于報(bào)錯(cuò)階段,后來(lái)想到可以通過(guò)輪子直接安裝。
在pypi提供的安裝包中有對(duì)應(yīng)的安裝包,注意,不僅僅是python2和python3的區(qū)別,python3的小版本也有點(diǎn)差別??杀叩氖?,小主電腦里裝的是python3.8,后來(lái)想到還有一個(gè)網(wǎng)站可以安裝pythonlibs,找到對(duì)應(yīng)的版本后,下載下來(lái)。直接在文件所在目錄,或者在安裝中指定文件目錄中執(zhí)行安裝
pip install /c/Users/root/Downloads/PyAudio-0.2.11-cp38-cp38-win_amd64.whl
代碼和運(yùn)行
def audio_record(out_file, rec_time):
CHUNK = 1024
FORMAT = pyaudio.paInt16 # 16bit編碼格式
CHANNELS = 1 # 單聲道
RATE = 16000 # 16000采樣頻率
p = pyaudio.PyAudio()
# 創(chuàng)建音頻流
dev_idx = findInternalRecordingDevice(p)
stream = p.open(format=FORMAT, # 音頻流wav格式
channels=CHANNELS, # 單聲道
rate=RATE, # 采樣率16000
input=True,
input_device_index=dev_idx, # 指定內(nèi)錄設(shè)備的id,可以不寫,使用win的默認(rèn)錄音設(shè)備
frames_per_buffer=CHUNK)
print("Start Recording...")
frames = [] # 錄制的音頻流
# 錄制音頻數(shù)據(jù)
for i in range(0, int(RATE / CHUNK * rec_time)): # 控制錄音時(shí)間
data = stream.read(CHUNK)
frames.append(data)
# 錄制完成
stream.stop_stream()
stream.close()
p.terminate()
print("Recording Done...")
# 保存音頻文件
wf = wave.open(out_file, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()
在使用默認(rèn)錄音設(shè)備時(shí),發(fā)現(xiàn)是話筒錄音,效果并不是太理想,所以就去查查能不能直接錄系統(tǒng)的聲音。
def findInternalRecordingDevice(p):
# 要找查的設(shè)備名稱中的關(guān)鍵字
target = '立體聲混音'
# 逐一查找聲音設(shè)備
for i in range(p.get_device_count()):
devInfo = p.get_device_info_by_index(i)
print(devInfo)
if devInfo['name'].find(target) >= 0 and devInfo['hostApi'] == 0:
# print('已找到內(nèi)錄設(shè)備,序號(hào)是 ',i)
return i
print('無(wú)法找到內(nèi)錄設(shè)備!')
return -1
可以使用p.get_device_info_by_index()去查看系統(tǒng)有關(guān)聲音的設(shè)備,通過(guò)設(shè)置為立體聲混音就可以錄制系統(tǒng)聲音。
保存聲音
def save(fileName): # 創(chuàng)建pyAudio對(duì)象 p = pyaudio.PyAudio() # 打開用于保存數(shù)據(jù)的文件 wf = wave.open(fileName, 'wb') # 設(shè)置音頻參數(shù) wf.setnchannels(CHANNELS) wf.setsampwidth(p.get_sample_size(FORMAT)) wf.setframerate(RATE) # 寫入數(shù)據(jù) wf.writeframes(b''.join(_frames)) # 關(guān)閉文件 wf.close() # 結(jié)束pyaudio p.terminate()
保存聲音是通過(guò)上述代碼進(jìn)行保存,此處的_frames是個(gè)list,是通過(guò)每錄一個(gè)chunk(數(shù)據(jù)流塊),就把這一塊的數(shù)據(jù)添加進(jìn)去
然后只需要重新創(chuàng)建PyAudio對(duì)象,把這個(gè)list轉(zhuǎn)為字節(jié)串保存到文件中就可以了
問(wèn)題
上述一般可以錄到系統(tǒng)聲音,但在執(zhí)行的時(shí)候發(fā)現(xiàn),并不能。
原因是:win的輸入設(shè)備中沒(méi)有配置立體聲混音
設(shè)置步驟:
- 在win的聲音調(diào)節(jié)出,右擊打開聲音設(shè)置
- 找到管理聲音設(shè)備
- 在輸入設(shè)備處啟用立體聲混音
就此,就完成了錄制系統(tǒng)聲音的需求
注意
上述操作,可以外放,可以插入3.5mm耳機(jī),但系統(tǒng)靜音和tpye-c耳機(jī)插入的時(shí)候不能錄到聲音
完整代碼
import os
import pyaudio
import threading
import wave
import time
from datetime import datetime
# 需要系統(tǒng)打開立體聲混音
# 錄音類
class Recorder():
def __init__(self, chunk=1024, channels=2, rate=44100):
self.CHUNK = chunk
self.FORMAT = pyaudio.paInt16
self.CHANNELS = channels
self.RATE = rate
self._running = True
self._frames = []
# 獲取內(nèi)錄設(shè)備序號(hào),在windows操作系統(tǒng)上測(cè)試通過(guò),hostAPI = 0 表明是MME設(shè)備
def findInternalRecordingDevice(self, p):
# 要找查的設(shè)備名稱中的關(guān)鍵字
target = '立體聲混音'
# 逐一查找聲音設(shè)備
for i in range(p.get_device_count()):
devInfo = p.get_device_info_by_index(i)
# print(devInfo)
if devInfo['name'].find(target) >= 0 and devInfo['hostApi'] == 0:
# print('已找到內(nèi)錄設(shè)備,序號(hào)是 ',i)
return i
print('無(wú)法找到內(nèi)錄設(shè)備!')
return -1
# 開始錄音,開啟一個(gè)新線程進(jìn)行錄音操作
def start(self):
threading._start_new_thread(self.__record, ())
# 執(zhí)行錄音的線程函數(shù)
def __record(self):
self._running = True
self._frames = []
p = pyaudio.PyAudio()
# 查找內(nèi)錄設(shè)備
dev_idx = self.findInternalRecordingDevice(p)
if dev_idx < 0:
return
# 在打開輸入流時(shí)指定輸入設(shè)備
stream = p.open(input_device_index=dev_idx,
format=self.FORMAT,
channels=self.CHANNELS,
rate=self.RATE,
input=True,
frames_per_buffer=self.CHUNK)
# 循環(huán)讀取輸入流
while (self._running):
data = stream.read(self.CHUNK)
self._frames.append(data)
# 停止讀取輸入流
stream.stop_stream()
# 關(guān)閉輸入流
stream.close()
# 結(jié)束pyaudio
p.terminate()
return
# 停止錄音
def stop(self):
self._running = False
# 保存到文件
def save(self, fileName):
# 創(chuàng)建pyAudio對(duì)象
p = pyaudio.PyAudio()
# 打開用于保存數(shù)據(jù)的文件
wf = wave.open(fileName, 'wb')
# 設(shè)置音頻參數(shù)
wf.setnchannels(self.CHANNELS)
wf.setsampwidth(p.get_sample_size(self.FORMAT))
wf.setframerate(self.RATE)
# 寫入數(shù)據(jù)
wf.writeframes(b''.join(self._frames))
# 關(guān)閉文件
wf.close()
# 結(jié)束pyaudio
p.terminate()
if __name__ == "__main__":
# 檢測(cè)當(dāng)前目錄下是否有record子目錄
if not os.path.exists('record'):
os.makedirs('record')
print("\npython 錄音機(jī) ....\n")
print("提示:按 r 鍵并回車 開始錄音\n")
i = input('請(qǐng)輸入操作碼:')
if i == 'r':
rec = Recorder()
begin = time.time()
print("\n開始錄音,按 s 鍵并回車 停止錄音,自動(dòng)保存到 record 子目錄\n")
rec.start()
running = True
while running:
i = input("請(qǐng)輸入操作碼:")
if i == 's':
running = False
print("錄音已停止")
rec.stop()
t = time.time() - begin
print('錄音時(shí)間為%ds' % t)
# 以當(dāng)前時(shí)間為關(guān)鍵字保存wav文件
rec.save("record/rec_" + datetime.now().strftime("%Y-%m-%d_%H-%M-%S") + ".wav")
以上就是python 錄制系統(tǒng)聲音的示例的詳細(xì)內(nèi)容,更多關(guān)于python 錄制系統(tǒng)聲音的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python連接Hadoop數(shù)據(jù)中遇到的各種坑(匯總)
這篇文章主要介紹了Python連接Hadoop數(shù)據(jù)中遇到的各種坑,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04
Django?ORM數(shù)據(jù)庫(kù)操作Python化藝術(shù)探索
這篇文章主要介紹了Django?ORM數(shù)據(jù)庫(kù)操作Python化藝術(shù)探索,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11
python隨機(jī)生成指定長(zhǎng)度密碼的方法
這篇文章主要介紹了python隨機(jī)生成指定長(zhǎng)度密碼的方法,涉及Python操作字符串的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04
Python 用__new__方法實(shí)現(xiàn)單例的操作
這篇文章主要介紹了Python 用__new__方法實(shí)現(xiàn)單例的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12
pytorch 實(shí)現(xiàn)查看網(wǎng)絡(luò)中的參數(shù)
今天小編就為大家分享一篇pytorch 實(shí)現(xiàn)查看網(wǎng)絡(luò)中的參數(shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-01-01

