当我们用录音机录网上的音乐时,有一个场景让人困扰:
比如听以下页面中的一首歌,要在页面上点击一下播放按钮
如果想把这一首歌录下来,当点击了播放按钮再去点录音机的录音按钮时,中间有一个时间差。可能一不小心,就错过了要
录制的内容。有的人的做法是先点录音机的录音按钮,再点页面上的播放按钮,这样一来,就可能会录上一段容白的内容,
当然会音频剪辑的人可以把这个空白剪掉,但终归不是最方便。
我的想法是让鼠标点击与开始录制同步,也就是想办法让程序自动点一下鼠标,然后再开始录音,这样两步操作就没有时间差了。
为此在前面一篇文章介绍的python录音机的基础之上做了改进,加上了录制鼠标宏的功能,也就是先将要进行的点击操作作为一个宏录制下来,在开始录音前,程序会自动回放这个宏,相当于让鼠标自动在想点击的位置上点一下之后再自动开始录音。
改进后的python录音机的启动界面
我们按下 ’ [ '键,开始记录鼠标操作,按下 ’ ] ’ 键停止记录鼠标操作,在这两个按键操作之间的鼠标点击会被记录下来,称为一
个鼠标宏。 当按下 ’ a ’ 键开始录音时,会自动回放这个鼠标宏,相当于鼠标点击之后以迅雷不及掩耳盗铃之势立即开始录音。
如果想检查一下录制的鼠标宏是否正确,按下’ m’ 键就可以直接回放鼠标宏,而不进行录音操作。
我们按下 ’ a '键开始录音,按下 ’ s '键停止录音,结果文件自动以时间为关键字命名,保存在程序所在目录的 record子目录中。
按下 ’ x '键将退出整个录音机程序。
改进后的python录音机的运行界面
下面是记录鼠标宏,并在开始录音时自动回放的操作结果
这时打开record子目录,里面出现了录制得到的wav文件
工作原理
使用pyAudio进行内录的原理,在前一篇文章《python开发的录音机(一)录制声卡播放的声音(内录)》已经做了介绍,这里着重说明一下鼠标操作的记录与回放技术
在这个例子当中,我们用到了 pynput 模块。这个模块的好处是将鼠标与键盘的各种控制与监视集成在一个模块中。以前的一些模块,比如pyHook只做监控,pyUserInput只做鼠标键盘的模拟。现在有了pynput ,一个模块全部搞定。
pynput的安装没有什么特殊之处,pip install pynput 就 OK了。
为了监控键盘,我们用到了keyboard.listener
为了监控鼠标,我们用到了mouse.Listener
在这两个listener的构造函数指定用于处理监控事件的回调函数就。
比如下面的代码
keyboard_listener=keyboard.Listener(on_press=on_keyPress)
mouse_listener=mouse.Listener(on_click=on_click)
绑定了两个处理监控事件的回调函数on_keyPress与on_click。
on_keyPress 是整个用户输入控制的核心函数
#监控按键
def on_keyPress(key):
try:
#print('key {0} pressed'.format( key.char))
#开始录音
if key.char == 'a':
#录音前回放鼠标宏
mouseMacro.playMouseMacro()
recorder.start()
#停止录音
if key.char == 's':
recorder.stop()
#开始录制鼠标事件
if key.char == '[':
mouseMacro.beginMouseMacro()
#停止录制鼠标事件
if key.char == ']':
mouseMacro.endMouseMacro()
#测试回放鼠标宏
if key.char == 'm':
mouseMacro.playMouseMacro()
#退出程序
if key.char == 'x':
#mouse_listener.stop()将停止对鼠标的监听
mouse_listener.stop()
#返回 False 将使键盘对应的lisenter停止监听
return False
except Exception as e:
print(e)
读一下源码就可以明白按下相应的键后会调用什么样的对象的什么方法。
比如
#开始录制鼠标事件
if key.char == '[':
mouseMacro.beginMouseMacro()
说明,当按下’[’ 就会调用 mouseMacro对象的beginMouseMacro方法。
再看一下对鼠标的监控处理
#监控鼠标
def on_click(x, y, button, pressed):
#print('{0} at {1}'.format('Pressed' if pressed else 'Released',(x, y)))
#如果正在录制鼠标宏,记录鼠标的点击位置
if pressed and mouseMacro.enabled:
mouseMacro.recordMouse((x,y))
return True
这个函数很简单,就是当允许记录鼠标宏时,将鼠标的点击位置保存起来,供以后回放时使用。
在这两个事件处理函数中都用到了一个类:MouseMacro 的各种方法。
下面是 MouseMacro 类的定义
#鼠标宏 ,目前只记录与回放click操作
class MouseMacro():
def __init__(self):
#指示是否记录鼠标事件
self.enabled = False
#模拟鼠标的控制器对象
self.mouseCtrl = mouse.Controller()
#记录鼠标点击位置的列表
self.mouseMacroList=[]
#开始记录鼠标宏操作
def beginMouseMacro(self):
print('开始记录鼠标宏')
self.mouseMacroList=[]
self.enabled=True
#记录鼠标宏操作
def recordMouse(self,event):
print('记录鼠标事件',event)
self.mouseMacroList.append(event)
#停止记录鼠标宏操作
def endMouseMacro(self):
self.enabled=False
print('停止记录鼠标宏!')
#回放录制的鼠标宏操作
def playMouseMacro(self):
if len(self.mouseMacroList) > 0:
print('回放鼠标宏:',self.mouseMacroList)
for pos in self.mouseMacroList:
self.mouseCtrl.position = pos
self.mouseCtrl.click(mouse.Button.left,1)
这个类中的两个核心方法是:
recordMouse,用于记录鼠标点击的位置,
playMouseMacro 用于回放鼠标的点击操作。
整个源码的内容都不长,而且加上了注释,感兴趣的朋友可以读一下完整的代码
完整的python代码
pyRecorderEx.py
# _*_ coding: utf-8 _*_
# 录音机,用于录制声卡播放的声音(内录)
# 可以录制鼠标操作,用于在开始录音时回放原先的鼠标操作
import os
#导入音频处理模块
import pyaudio
import threading
import wave
import time
from datetime import datetime
#导入控制与监控键盘和鼠标的模块
from pynput import keyboard,mouse
#录音类
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 = []
#录音开始时间
self.recBegin =0
#录音时长
self.recTime =0
#获取内录设备序号,在windows操作系统上测试通过,hostAPI = 0 表明是MME设备
def findInternalRecordingDevice(self,p):
#要找查的设备名称中的关键字
target = '立体声混音'
#逐一查找声音设备
for i in range(p.get_device_count()):
devInfo = p.get_device_info_by_index(i)
if devInfo['name'].find(target)>=0 and devInfo['hostApi'] == 0 :
#print('已找到内录设备,序号是 ',i)
return i
print('无法找到内录设备!')
return -1
#开始录音,开启一个新线程进行录音操作
def start(self):
print("正在录音...")
threading._start_new_thread(self.__record, ())
#执行录音的线程函数
def __record(self):
self.recBegin = time.time()
self._running = True
self._frames = []
p = pyaudio.PyAudio()
#查找内录设备
dev_idx = self.findInternalRecordingDevice(p)
if dev_idx < 0 :
return
#在打开输入流时指定输入设备
stream = p.open(input_device_index=dev_idx,
format=self.FORMAT,
channels=self.CHANNELS,
rate=self.RATE,
input=True,
frames_per_buffer=self.CHUNK)
#循环读取输入流
while(self._running):
data = stream.read(self.CHUNK)
self._frames.append(data)
#停止读取输入流
stream.stop_stream()
#关闭输入流
stream.close()
#结束pyaudio
p.terminate()
return
#停止录音
def stop(self):
self._running = False
self.recTime = time.time() - self.recBegin
print("录音已停止")
print('录音时间为%ds'%self.recTime)
#以当前时间为关键字保存wav文件
self.save("record/rec_"+datetime.now().strftime("%Y-%m-%d_%H-%M-%S")+".wav")
#保存到文件
def save(self, fileName):
#创建pyAudio对象
p = pyaudio.PyAudio()
#打开用于保存数据的文件
wf = wave.open(fileName, 'wb')
#设置音频参数
wf.setnchannels(self.CHANNELS)
wf.setsampwidth(p.get_sample_size(self.FORMAT))
wf.setframerate(self.RATE)
#写入数据
wf.writeframes(b''.join(self._frames))
#关闭文件
wf.close()
#结束pyaudio
p.terminate()
#鼠标宏 ,目前只记录与回放click操作
class MouseMacro():
def __init__(self):
#指示是否记录鼠标事件
self.enabled = False
#模拟鼠标的控制器对象
self.mouseCtrl = mouse.Controller()
#记录鼠标点击位置的列表
self.mouseMacroList=[]
#开始记录鼠标宏操作
def beginMouseMacro(self):
print('开始记录鼠标宏')
self.mouseMacroList=[]
self.enabled=True
#记录鼠标宏操作
def recordMouse(self,event):
print('记录鼠标事件',event)
self.mouseMacroList.append(event)
#停止记录鼠标宏操作
def endMouseMacro(self):
self.enabled=False
print('停止记录鼠标宏!')
#回放录制的鼠标宏操作
def playMouseMacro(self):
if len(self.mouseMacroList) > 0:
print('回放鼠标宏:',self.mouseMacroList)
for pos in self.mouseMacroList:
self.mouseCtrl.position = pos
self.mouseCtrl.click(mouse.Button.left,1)
#监控按键
def on_keyPress(key):
try:
#print('key {0} pressed'.format( key.char))
#开始录音
if key.char == 'a':
#录音前回放鼠标宏
mouseMacro.playMouseMacro()
recorder.start()
#停止录音
if key.char == 's':
recorder.stop()
#开始录制鼠标事件
if key.char == '[':
mouseMacro.beginMouseMacro()
#停止录制鼠标事件
if key.char == ']':
mouseMacro.endMouseMacro()
#测试回放鼠标宏
if key.char == 'm':
mouseMacro.playMouseMacro()
#退出程序
if key.char == 'x':
#mouse_listener.stop()将停止对鼠标的监听
mouse_listener.stop()
#返回 False 将使键盘对应的lisenter停止监听
return False
except Exception as e:
print(e)
#监控鼠标
def on_click(x, y, button, pressed):
#print('{0} at {1}'.format('Pressed' if pressed else 'Released',(x, y)))
#如果正在录制鼠标宏,记录鼠标的点击位置
if pressed and mouseMacro.enabled:
mouseMacro.recordMouse((x,y))
return True
if __name__ == "__main__":
#检测当前目录下是否有record子目录
if not os.path.exists('record'):
os.makedirs('record')
print("\npython 录音机 ....\n")
print("----------------- 提示 ------------------------------------------\n")
print("按 a 键 开始录音, 按 s 键 停止录音 , 按 x 键 退出程序 ")
print("按 [ 键 开始记录鼠标, 按 ] 键 停止记录鼠标 , 按 m 键 回放鼠标宏 \n")
print("-----------------------------------------------------------------\n")
#创建录音机对象
recorder = Recorder()
#创建“鼠标宏”对象
mouseMacro = MouseMacro()
#开始监听鼠标与键盘
keyboard_listener=keyboard.Listener(on_press=on_keyPress)
mouse_listener=mouse.Listener(on_click=on_click)
lst=[keyboard_listener,mouse_listener]
for t in lst:
t.start()
for t in lst:
t.join()
将以上内容保存到本地文件夹,在python3 与pyaudio,pynput已经安装好的前提下,
运行 python pyRecorderEx.py
就可以方便地进行各种声音资源的录制了。
补充说明:
现在录制的声音文件只能保存为wav格式的文件,以后会将保存为mp3格式的功能加上。