应用市场上录屏工具的原理很好理解,一是屏幕,二是声音。从这个角度出发,我们就可以对屏幕和声音同步来录制,最后在将音频和视频合并在一起,最后我们就得到了我们录屏的视频。
为了使音频和视频同步,这里采用双线程同步进行,同时启动,同时结束。
为了更好的理解,做了详细的注释。
导包
import wave
import pyaudio
import cv2
import moviepy
import threading
import _thread
import numpy as np
from time import sleep
from PIL import ImageGrab
from datetime import datetime
from moviepy.editor import AudioFileClip,VideoFileClip
import warnings
warnings.filterwarnings("ignore")
音频的录制
音频的录制采用的是 pyaudio 库来启用麦克风记录声音并保存到本地。
def record_audio(self):
#创建一个pyaudio对象
recordAudio = pyaudio.PyAudio()
#创建一个输入流stream
stream = recordAudio.open(format = pyaudio.paInt16,#使用量化位数,16位
channels = 2,#双声道数
rate = 44100,#采样频率
input = True,#确定是输入流
frames_per_buffer = 128#指定每个数据帧数
)
waveFile = wave.open(self.audio_filename,'wb')
#音频通道数
waveFile.setnchannels(2)
#量化位数
waveFile.setsampwidth(recordAudio.get_sample_size(pyaudio.paInt16))
#采样频率
waveFile.setframerate(44100)
#录制,不断写入
while self.recording:
waveFile.writeframes(stream.read(128))
waveFile.close()
#停止输入
stream.stop_stream()
#关闭输入流
stream.close()
recordAudio.terminate()
pass
视频的录制
视屏的录制采用的是不断获取当前屏幕的截图,然后利用 opencv 写入到视频文件中。
def video_record(self):
#获取屏幕
screen = ImageGrab.grab()
#转换RGB
video = cv2.VideoWriter(self.video_record_filename,cv2.VideoWriter_fourcc(*'XVID'),20,screen.size)
#录制
while self.recording:
#截取屏幕
screen = ImageGrab.grab()
screen = cv2.cvtColor(np.array(screen),cv2.COLOR_RGB2BGR)
#写入到本地文件
video.write(screen)
print(datetime.now())
#释放
video.release()
pass
主程序
def run(self):
print("3秒后开始录制,输入quit结束")
sleep(3)
#文件命名为当前时间
self.now = str(datetime.now())[:19].replace(':','_').replace('-','_').replace(' ','_')
#音频
self.audio_filename = "{}.wav".format(self.now)
#视频
self.video_record_filename = "{}_video.avi".format(self.now)
#最终的视频
self.video_filename = "{}.mp4".format(self.now)
#开启两个线程
t1 = threading.Thread(target = self.record_audio)
t2 = threading.Thread(target = self.video_record)
for t in [t1,t2]:
t.start()
while True:
if(input() == 'quit'):
break
#两个线程同时结束
self.recording = False
for t in [t1,t2]:
t.join()
audio = AudioFileClip(self.audio_filename) #moviepy读取视频
video = VideoFileClip(self.video_record_filename)#moviepy读取音频
totalVideo = video.set_audio(audio)#音频附加到视频上
#编码.mp4 帧率25
totalVideo.write_videofile(self.video_filename,codec = "libx264",fps = 25)
pass
当然了,也可以用PyQt实现图形化界面,真正的实现录屏软件。
收获 —— 多线程
多线程类似于同时执行多个不同程序,多线程运行有如下优点:
- 使用线程可以把占据长时间的程序中的任务放到后台去处理。
- 用户界面可以更加吸引人,比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度。
- 程序的运行速度可能加快。
- 在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较有用了。在这种情况下我们可以释放一些珍贵的资源如内存占用等等。
例如
import time
import threading
def tstart():
time.sleep(0.5)
print(" running....")
if __name__ == '__main__':
#创建线程
t1 = threading.Thread(target = tstart)
t2 = threading.Thread(target = tstart)
#开启线程
for t in [t1,t2]:
t.start()
#join的原理就是依次检验线程池中的线程是否结束
#没有结束就阻塞直到线程结束
#如果结束则跳转执行下一个线程的join函数。
for t in [t1,t2]:
t.join()
print("This is main function")