Airtest Windows 录屏

直南瓜 · August 26, 2019 · Last by 笑哼 replied at September 02, 2019 · 815 hits

引言

airtest中用Yosemite实现安卓端的录屏功能,但windows端并没有脚本运行过程的步骤视频,为了方便做PC端自动化测试时查bug简单一点,我就自己用OpenCV撸了个录屏。
原理比较简单,就是开一条子线程,不停截图,最后导出一个MP4即可

录屏线程

def Record(self, bbox):
import time
import airtest.core.win.screen as screen
threading.current_thread.name = 'recording'
while True:
if not self.m_bRecording:
break
self.m_Lock.acquire()
print('Recording...', (bbox[2] - bbox[0], bbox[3] - bbox[1]))
try:
im = aircv.crop_image(screen.screenshot(None), bbox)
self.video.write(numpy.array(im)) # img convert ndarray
except:
pass
self.m_Lock.release()
time.sleep(INTERVAL)

api

模仿airtest里安卓部分来写

def start_recording(self, output):
rect = self.get_rect() # 获得分辨率
bbox = (ToEvenNum(rect.left), ToEvenNum(rect.top), ToEvenNum(rect.right), ToEvenNum(rect.bottom)) # 虚拟机中需要是偶数
# bbox = (rect.left, rect.top, rect.right, rect.bottom)
size = (bbox[2] - bbox[0], bbox[3] - bbox[1])
width, heigh = size
self.video = cv2.VideoWriter(output, cv2.VideoWriter_fourcc(*'X264'), FPS, (width, heigh))
self.m_Lock = threading.Lock()
self.m_bRecording = True
self.LoopTimer = threading.Timer(INTERVAL, self.Record, [bbox])
self.LoopTimer.start()

def stop_recording(self, output):
self.m_Lock.acquire()
print('Record end')
self.m_bRecording = False
if self.LoopTimer:
self.LoopTimer.cancel()
self.LoopTimer = None
self.video.release()
self.m_Lock.release()

这里几个坑解释一下
1.start_recording里bbox 是截图时四个顶点的坐标,一开始在PC端搞的时候只要bbox = (rect.left, rect.top, rect.right, rect.bottom)就可以,后来PC数量有限换成了win10虚拟机怎么搞都不能截图,经过了一番调试发现把四个数都强转成偶数就可以了,至今没明白为什么。一个大迷。
2.cv2.VideoWriter_fourcc('X264')这个解码器选的是'X264',其他也试过,要么输出的颜色不对,要么导出的mp4无法在html中显示

初始化

def InitVideoRecorder(oDevices):
if oDevices.__class__.__name__ == "Windows":
oDevices.m_Lock = threading.Lock()
if not hasattr(oDevices, 'start_recording'):
oDevices.start_recording = types.MethodType(start_recording, oDevices)
if not hasattr(oDevices, 'stop_recording'):
oDevices.stop_recording = types.MethodType(stop_recording, oDevices)
if not hasattr(oDevices, 'Record'):
oDevices.Record = types.MethodType(Record, oDevices)

代码里调用

一般在AirtestCase的setUp里开始录制,在tearDown里结束录制
也可以自己在脚本里适当的位置初始化后开始和结束

def setUp(self):
auto_setup(logdir=self._logdir)
self.RecordScreen()

def tearDown(self):
try:
output = os.path.join(self.logdir, "recording_0.mp4")
print(output)
self.m_oDev.stop_recording(output)
except:
traceback.print_exc()

@RetryFunc()
def RecordScreen(self): # 开始录屏
try:
return self.StartRecording()
except Exception as e:
try:
self.m_oDev.stop_recording(is_interrupted=True)
except:
pass
raise e

def StartRecording(self):
if device_platform(self.m_oDev) == 'Windows':
output = os.path.join(self.logdir, 'recording_0.mp4')
video.InitVideoRecorder(self.m_oDev)
self.m_oDev.start_recording(output)
else:
self.m_oDev.start_recording()

完整代码

共收到 2 条回复 时间 点赞

楼主66666666

试了下这个方法,效果还不错

需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up