基于TightVNC源码实现远程桌面本地录像功能(OpenCV)
原博客地址:https://www.cnblogs.com/feixiang-energy/p/15528903.html
一.出发点:
tightVNC是一个用在windows上的很好的远程桌面工具,实现了远程桌面、文件传输等功能。 但是没有实现远程桌面录像保存的功能。
tightVNC使用远程桌面协议 (RDP) 实现终端服务器和终端服务器客户端之间的通信。客户端将服务器端的屏幕拼接成帧图片进行展示。为了实现屏幕录制的功能,考虑基于tightVNC的源码进行修改,在客户端展示屏幕帧的同时,增加一个线程将已经拼接好的连续的屏幕帧图片保存为视频文件。
使用了OpenCV的cv::VideoWriter对象,将连续的图片保存为视频文件。经过初步测试,能达到客户端本地远程桌面录像的功能。
现在把实现方式贴出来,希望对有需要的人提供些参考。
二.源码下载:
tightVNC官网有C++版本的开源代码可供下载:https://www.tightvnc.com/download.php
![](https://img2020.cnblogs.com/blog/2607547/202111/2607547-20211109144547786-1902903807.png)
三.实现方式:
使用VS2019打开并编译源码。我使用的是tightvnc-2.8.27-gpl版本。
修改viewer-core/RemoteViewerCore类,在里面增加一个record_fun的处理函数实现对远程桌面屏幕的录制。
主要代码如下:
//远程桌面客户端屏幕录制线程 DWORD _stdcall RemoteViewerCore::record_fun(LPVOID lparam) { Sleep(1000); //远程桌面客户端连接对象 RemoteViewerCore* lp = (RemoteViewerCore*)lparam; //视频文件名称 char file_name[256] = { 0 }; time_t t = time(0); char time_str[64]; strftime(time_str, sizeof(time_str), "%Y%m%d%H%M%S", localtime(&t)); sprintf(file_name, "video/video_%s_%s.mp4", lp->m_host_name, time_str); //获取远程桌面屏幕帧的分辨率 Dimension dimension = lp->m_frameBuffer.getDimension(); int weight = dimension.width; int hight = dimension.height; //opencv的视频保存对象,初始化大小为0.5倍,是为了对分辨率进行裁剪 cv::VideoWriter writer; writer.open(file_name, CV_FOURCC('m', 'p', '4', 'v'), 9, cv::Size(weight * 0.5, hight * 0.5), true); //tightvnc远程桌面屏幕帧编码格式为RGBA //初始化一个4倍分辨率的数组用于保存帧二进制数据 int buf_len = weight * hight * 4; char* buf = new char[buf_len]; while (lp->m_record_flag) { int start = clock(); //初始化一个RGB格式的Mat对象 cv::Mat dst = cv::Mat::zeros(hight, weight, 16); memset(buf, 0, buf_len); memcpy(buf, lp->m_frameBuffer.getBuffer(), lp->m_frameBuffer.getBufferSize()); //将视频帧的数据RGB数据保存到对应的Mat对象中 for (int i = 0; i < hight; i++) { for (int j = 0; j < weight; j++) { dst.at<cv::Vec3b>(i, j)[0] = buf[(i* weight + j) * 4]; dst.at<cv::Vec3b>(i, j)[1] = buf[(i * weight + j) * 4 + 1]; dst.at<cv::Vec3b>(i, j)[2] = buf[(i * weight + j) * 4 + 2]; } } int used = clock() - start; //对Mat对象进行图片裁剪 cv::Mat dst1; cv::resize(dst, dst1, cv::Size(weight * 0.5, hight * 0.5)); //将图片写入到视频保存对象 writer.write(dst1); //休眠100毫秒。这个时间间隔可以用来控制每秒中保存的视频图像帧数,即控制码率。 Sleep(100); } //释放掉二进制数组。 delete[]buf; return 0; }
四.实现效果:
每次使用重新编译过的TightVNCViewer进程远程桌面连接时,都在本地会保存一个本次操作的远程桌面录像文件。