当前位置: 首页 > 工具软件 > OpenDX > 使用案例 >

解决opendx在windows下无法使用scrcpy录屏

詹斌蔚
2023-12-01


前言

opendx是一款基于 appium 的自动化测试平台。支持web端控制手机,整个架构设计非常优秀,可以根据公司业务,进行二次开发使用。

一、解决的问题

由于华为手机高版本无法使用appium自带的录制功能。所以opendx添加了scrcpy录制功能,缺点是需要在agent端安装scrcpy,且windows无法支持录制。由于公司大多数同学使用windows,导致启动的agent在高版本华为手机上无法录制视频,在用例结束后难以排查问题。

二、使用步骤

1.opendx源码下载

下载地址

2.修改agent内容

ScrcpyVideoRecorder类代码如下(示例):

package com.daxiang.core.mobile.android.scrcpy;

import com.daxiang.core.Device;
import com.daxiang.core.mobile.android.AndroidDevice;
import com.daxiang.utils.Terminal;
import com.daxiang.utils.UUIDUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * Created by jiangyitao.
 */
@Slf4j
public class ScrcpyVideoRecorder {

    private String mobileId;
    private String videoName;
    private boolean isRecording = false;
    private CountDownLatch countDownLatch;
    private Device device;
    private FileChannel fc;
    private Scrcpy scrcpy;
    private static final String H264 = ".h264";
    private static final String MP4 = ".mp4";
    public ScrcpyVideoRecorder(String mobileId,Device device) {
        this.mobileId = mobileId;
        this.device = device;
    }

    public synchronized void start() {
        if (isRecording) {
            return;
        }
        countDownLatch = new CountDownLatch(1);
        scrcpy = ((AndroidDevice) device).getScrcpy();

        try {
            videoName = UUIDUtil.getUUID();
            fc = new FileOutputStream(videoName+H264).getChannel();
            scrcpy.start(imgData -> {
                try {
                    fc.write(imgData);
                } catch (IOException e) {
                }
            });
            isRecording = true;
        } catch (Exception e) {
            isRecording = false;
            throw new RuntimeException(e);
        }finally {
            countDownLatch.countDown();
        }

    }

    /**
     * 1. kill scrcpy server来停止录制视频是最优方案。但大多数安卓Mobile只能通过ps(非ps -ef)获取到scrcpy server进程,
     * 此时的进程名为app_process, appium在Mobile里运行的进程也是app_process,所以可能会误杀appium在Mobile里运行的进程,不采用该方法
     * 2. ExecuteWatchdog.destroyProcess()会导致最后一部分视频无法写入,
     * 因为运行在pc的scrcpy进程被直接干掉,无法写入最终的视频,导致获取到破损的视频
     * 3. 在非windows操作系统下,scrcpy收到kill信号后,会写入最后一部分视频,目前采用该方法
     * 4. 无法在windows上使用,windows taskkill和ExecuteWatchdog.destroyProcess()一样
     */
    public synchronized File stop() throws IOException {
        if (!isRecording) {
            throw new IllegalStateException("video is not in recording");
        }

        log.info("[{}]stop record video: {}", mobileId, videoName);

        scrcpy.stop();
        if (fc != null){
            fc.close();
        }
        String killScrcpyCmd = String.format("ffmpeg -f h264 -i %s.h264 -y -vcodec copy %s.mp4", videoName,videoName);
        Terminal.execute(killScrcpyCmd);
        try {
            // 等待视频写入完成,最多等3min
            countDownLatch.await(3, TimeUnit.MINUTES);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        FileUtils.deleteQuietly(new File(videoName+H264));
        log.info("[{}]video: {} recording complete", mobileId, videoName);
        isRecording = false;
        return new File(videoName+MP4);
    }
}

AndroidDevice类代码如下(示例):

    @Override
    public void startRecordingScreen() {
        if (canUseAppiumRecordVideo) {
            try {
                AndroidStartScreenRecordingOptions androidOptions = new AndroidStartScreenRecordingOptions();
                // Since Appium 1.8.2 the time limit can be up to 1800 seconds (30 minutes).
                androidOptions.withTimeLimit(Duration.ofMinutes(30));
                androidOptions.withBitRate(Integer.parseInt(App.getProperty("androidRecordVideoBitRate")) * 1000000); // default 4000000
                ((AndroidDriver) driver).startRecordingScreen(androidOptions);
                return;
            } catch (Exception e) {
                log.warn("[{}]无法使用appium录制视频", getId(), e);
                canUseAppiumRecordVideo = false;
            }
        }

        if (scrcpyVideoRecorder == null) {
            scrcpyVideoRecorder = new ScrcpyVideoRecorder(getId(),this);
        }
        try {
            scrcpyVideoRecorder.start();
        }catch (Exception e){
            log.warn("[{}]无法使用scrcpy录制视频", getId(), e);
        }

    }

修改以上两个类后,agent端不需要安装scrcpy,windows也支持录制视频

 类似资料: