Unity 使用AVProMovieCapture实现Game视图屏幕录制

内容将会持续更新,有错误的地方欢迎指正,谢谢!
 

Unity 使用AVProMovieCapture实现Game视图屏幕录制
     
TechX 坚持将创新的科技带给世界!

拥有更好的学习体验 —— 不断努力,不断进步,不断探索
TechX —— 心探索、心进取!

助力快速掌握 AVProMovieCapture 屏幕录制

为初学者节省宝贵的学习时间,避免困惑!


文章目录

  • 一、导入AVProMovieCapture包
  • 二、屏幕捕捉基本设置
  • 三、实现Game视图屏幕捕捉功能
    • 1、屏幕捕捉功能
    • 2、视频列表功能
    • 3、视频播放功能
  • 四、MovieCapture项目地址


一、导入AVProMovieCapture包


在Asset Store资源商店里面可以下载这个插件:

https://assetstore.unity.com/packages/tools/video/avpro-movie-capture-desktop-edition-221914

目前这个插件比较贵,以下提供了老一点的版本,也是可以用的。
https://download.csdn.net/download/caiprogram123/89517225

下载之后解压,并把这个包导入到Unity中,可以看到RenderHeads/AVProMovieCapture

在这里插入图片描述



二、屏幕捕捉基本设置


在开始录制Game视图时要对录制做一些基本的设置:

  • 输出文件夹类型:输出视频到哪个位置
    在这里插入图片描述

  • 输出子文件夹:输出视频位置的子文件夹

  • 分辨率:设置视频的分辨率
    在这里插入图片描述

  • 帧率:设置视频的帧率

  • 视频前缀:设置视频名称的前缀

//视频输出路径
public string videoOutFolder;
//视频输出路径类型
public OutputPath outputFolderType = defaultOutputFolderType;
//视频输出文件夹
public string outputFolderPath = defaultOutputFolderPath;//视频降分辨率
public CaptureBase.DownScale downScale = CaptureBase.DownScale.Original;
//视频帧率
public float frame = 60;
//视频前缀
public string prefix = "ScreenCapture";/// <summary>
/// 设置视频输出路径
/// </summary>
private void SetOutFolderPath()
{videoOutFolder = GetFolder(outputFolderType, outputFolderPath);if (!Directory.Exists(videoOutFolder))Directory.CreateDirectory(videoOutFolder);_movieCapture.OutputFolderPath = videoOutFolder;
}/// <summary>
/// 设置视频画质
/// </summary>
private void SetDownScale()
{_movieCapture.ResolutionDownScale = downScale;
}/// <summary>
/// 设置帧率
/// </summary>
private void SetFrameRate()
{_movieCapture.FrameRate = frame;}/// <summary>
/// 设置文件前缀
/// </summary>
private void SetPrefix()
{_movieCapture.FilenamePrefix = prefix;
}


三、实现Game视图屏幕捕捉功能


1、屏幕捕捉功能


在导入包后就可以进行屏幕录制功能开发,包含开始录频、结束录频、查看最近录制,同时在录制的过程中也能够看到当前当前录制视频的大小和时长。

 private long _lastFileSize;private uint _lastEncodedMinutes;private uint _lastEncodedSeconds;private uint _lastEncodedFrame;private StringBuilder _fileSize = new StringBuilder();private StringBuilder _videoLength = new StringBuilder();/// <summary>/// 开始录制/// </summary>private void StartCapture(){_lastFileSize = 0;_lastEncodedMinutes = _lastEncodedSeconds = _lastEncodedFrame = 0;if (_movieCapture != null){_movieCapture.StartCapture();startRecord.interactable = false;stopRecord.interactable = true;}}/// <summary>/// 停止录制/// </summary>private void StopCapture(){if (_movieCapture != null){if (_movieCapture.IsCapturing()){_movieCapture.StopCapture();startRecord.interactable = true;stopRecord.interactable = false;}}}/// <summary>/// 文件大小设置/// </summary>/// <param name="lastFileSize"></param>private void FileSize(){_lastFileSize = _movieCapture.GetCaptureFileSize();_fileSize.Clear();_fileSize.Append((_lastFileSize / (1024f * 1024f)).ToString("F1"));_fileSize.Append("MB");}/// <summary>/// 视频长度设置/// </summary>private void VideoLength(){if (!_movieCapture.IsRealTime){_lastEncodedSeconds = (uint)Mathf.FloorToInt(_movieCapture.CaptureStats.NumEncodedFrames / _movieCapture.FrameRate);}else{_lastEncodedSeconds = _movieCapture.CaptureStats.TotalEncodedSeconds;}_lastEncodedMinutes = _lastEncodedSeconds / 60;_lastEncodedSeconds = _lastEncodedSeconds % 60;_lastEncodedFrame = _movieCapture.CaptureStats.NumEncodedFrames % (uint)_movieCapture.FrameRate;_videoLength.Clear();_videoLength.Append(_lastEncodedMinutes.ToString("00"));_videoLength.Append(":");_videoLength.Append(_lastEncodedSeconds.ToString("00"));_videoLength.Append(".");_videoLength.Append(_lastEncodedFrame.ToString("000"));}
  • 开始录制: 开始进行Game视图录制
  • 结束录制: 结束录制,录制结束后,视频会进进行保存
  • 最新录制: 显示最近录制的视频记录
  • File Size: 当前录制视频的文件大小
  • Video Length: 当前录制视频的时长

在这里插入图片描述

2、视频列表功能


在视频录制完成后,会将视频信息进行保存,当点击最新录制会显示视频列表窗口,在这里你可以找到所有的最近录制的视频记录。

public class RecordList : MonoBehaviour
{public RecordItem recordItemPre;private List<RecordItem> records = new List<RecordItem>();/// <summary>/// 初始化记录表/// </summary>/// <param name="saveInfos"></param>public void InitRecordList(List<VideoInfo> videoList){gameObject.SetActive(true);for (int i = 0; i < records.Count; i++){Destroy(records[i].gameObject);}records.Clear();for (int i = 0; i < videoList.Count; i++){RecordItem recordItem = Instantiate(recordItemPre, recordItemPre.transform.parent);recordItem.InitRecordItem(videoList[i]);records.Add(recordItem);recordItem.gameObject.SetActive(true);}}
}
 public class RecordItem : MonoBehaviour{public Text videoName;public Text videoSize;public Text videoLength;public Text lastModifyTime;public Button view;public VideoControl videoControl;private VideoInfo videoInfo;// Start is called before the first frame updatevoid Start(){view.onClick.AddListener(() => {videoControl.VideoControlInit(videoInfo.videoPath);});}/// <summary>/// 初始化记录表/// </summary>/// <param name="saveInfo"></param>public void InitRecordItem(VideoInfo videoInfo){this.videoInfo = videoInfo;videoName.text = videoInfo.videoName;videoSize.text = (videoInfo.videoSize / (1024f * 1024f)).ToString("F1") + "MB";videoLength.text = (videoInfo.videoLength / 60).ToString("00") + ":" + (videoInfo.videoLength % 60).ToString("00");lastModifyTime.text = videoInfo.lastModifyTime;}}
  • 名称: 视频名称
  • 大小: 视频文件大小
  • 时长: 视频时长
  • 最后修改: 视频保存时间
  • 查看: 播放视频

在这里插入图片描述

3、视频播放功能


在视频列表中,点击查看按钮就可以播放该视频。

public class VideoControl : MonoBehaviour
{public Text title;public VideoPlayer player;public Slider videoSlider;public Button close;public Text videotime;public Text videoLength;string videoPath;private void Update(){if (player.isPlaying){SetCurPlayTime();SetPlaySchedule();}}private void Awake(){player.prepareCompleted += OnPrepareCompleted;}private void OnDestroy(){player.prepareCompleted -= OnPrepareCompleted;}public void VideoControlInit(string videoPath){this.videoPath = videoPath;gameObject.SetActive(true);SetVideoPlayPath(videoPath);PlayVideo();}/// <summary>/// 视频准备/// </summary>/// <param name="videoSource"></param>private void OnPrepareCompleted(VideoPlayer videoSource){SetVideoName();SetVideoLength();}/// <summary>/// 设置视频名称/// </summary>private void SetVideoName(){title.text = Path.GetFileNameWithoutExtension(videoPath);}/// <summary>/// 设置播放器路径/// </summary>/// <param name="path"></param>public void SetVideoPlayPath(string path){player.url = path;}/// <summary>/// 当前视频播放时间/// </summary>private void SetCurPlayTime(){videotime.text = TimeProcess(player.time);}/// <summary>/// 设置视频时长/// </summary>/// <param name="length"></param>private void SetVideoLength(){videoLength.text = TimeProcess(player.length);}/// <summary>/// 设置播放进度/// </summary>private void SetPlaySchedule(){videoSlider.value = (float)player.frame / player.frameCount;}/// <summary>/// 时间处理/// </summary>/// <param name="time"></param>/// <returns></returns>private string TimeProcess(double time){int minutes = (int)time / 60;int seconds = (int)time % 60;return minutes.ToString("00") + ":" + seconds.ToString("00");}/// <summary>/// 视频播放/// </summary>public void PlayVideo(){player.Play();}
}

视频播放时,会显示视频名称、时长、当前时间和播放进度

在这里插入图片描述


四、MovieCapture项目地址


项目完整地址:

https://gitcode.com/CTLittleNewbie/ScreenRecord_240520/





TechX —— 心探索、心进取!

每一次跌倒都是一次成长

每一次努力都是一次进步

END
感谢您阅读本篇博客!希望这篇内容对您有所帮助。如果您有任何问题或意见,或者想要了解更多关于本主题的信息,欢迎在评论区留言与我交流。我会非常乐意与大家讨论和分享更多有趣的内容。
如果您喜欢本博客,请点赞和分享给更多的朋友,让更多人受益。同时,您也可以关注我的博客,以便及时获取最新的更新和文章。
在未来的写作中,我将继续努力,分享更多有趣、实用的内容。再次感谢大家的支持和鼓励,期待与您在下一篇博客再见!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1473298.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【二】Ubuntu24虚拟机在Mac OS的VMware Fusion下无法联网问题

文章目录 1.环境背景2. 需求背景3. 解决方法3.1 在mac的终端查看虚拟机NAT网络3.2 查看unbuntu节点2的网络配置3.3 问题定位与解决3.3.1 检查是否有冲突3.3.2 冲突解决方法 4. 总结4.1 NAT 网关的原理4.2 VMware Fusion 的 NAT 模式4.3 为什么网关冲突会引起问题4.4 理解配置冲…

Linux 程序卡死的特殊处理

一、前言 Linux环境。 我们在日常编写的程序中&#xff0c;可能会出现一些细节问题&#xff0c;导致程序卡死&#xff0c;即程序没法正常运行&#xff0c;界面卡住&#xff0c;也不会闪退... 当这种问题出现在客户现场&#xff0c;那就是大问题了。。。 当我们暂时还无法排…

利用 STM32 实现多协议物联网网关:Modbus/Zigbee 到以太网/Wi-Fi 的数据桥接

摘要: 随着物联网技术的飞速发展&#xff0c;不同通信协议之间的互联互通成为了构建智能化系统的一大挑战。本文将以实战项目为例&#xff0c;详细介绍如何利用 STM32 微控制器实现 Modbus/Zigbee 与以太网/Wi-Fi 之间的协议转换&#xff0c;从而打通传感器数据上传至服务器的“…

代码随想录Day69(图论Part05)

并查集 // 1.初始化 int fa[MAXN]; void init(int n) {for (int i1;i<n;i)fa[i]i; }// 2.查询 找到的祖先直接返回&#xff0c;未进行路径压缩 int.find(int i){if(fa[i] i)return i;// 递归出口&#xff0c;当到达了祖先位置&#xff0c;就返回祖先elsereturn find(fa[i])…

实现沉浸式体验的秘诀:深入了解折幕投影技术!

在当今多媒体技术的浪潮中&#xff0c;投影技术已蜕变成为超越传统内容展示范畴的非凡工具&#xff0c;它深度融合了互动性与沉浸感&#xff0c;成为连接观众与虚拟世界的桥梁。折幕投影技术&#xff0c;作为这一领域的璀璨明珠&#xff0c;更是以其独特而神奇的手法&#xff0…

如何从相机的存储卡中恢复原始照片

“不好了。” 当您意识到自己不小心从存储卡中删除了照片&#xff0c;或者错误地格式化了相机的记忆棒时&#xff0c;您首先会喊出这两个词。这是一种常见的情况&#xff0c;每个人一生中都会遇到这种情况。幸运的是&#xff0c;有办法从相机的 RAW 记忆棒中恢复已删除的照片。…

笛卡尔集的情况 rows 1

running ~ 1 hour and TEMP Space using > 450 GB 1000*4.9k4.9M 1*4.9K4.9K

【LabVIEW学习篇 - 3】:程序结构——顺序结构、for循环、while循环

文章目录 顺序结构案例一案例二 for循环while循环 顺序结构 LabVIEW中的顺序结构是一种常用的控制结构&#xff0c;用于按顺序执行程序的不同部分。顺序结构在程序中按照从左到右的顺序依次执行各个子结构&#xff0c;类似于传统的文本编程语言中的顺序执行。 案例一 案例一…

查询数据库下所有表的数据量

个人思路: 首先把库里Schema下表名拿出来放记事本(EmEditor)里, 用一下正则匹配替换 (\w) → select \1 tableName,count(1) from \1 union all 然后把最后的union all删除掉,替换为order by tableName

C++部分复习笔记上

C语法复习 1. C入门基础 缺省参数 半缺省参数必须从右往左依次来给出&#xff0c;不能间隔着给缺省参数不能在函数声明和定义中同时出现缺省值必须是常量或者全局变量C语言不支持&#xff08;编译器不支持&#xff09; 函数重载 函数重载是函数的一种特殊情况&#xff0c;…

红薯小眼睛接口分析与Python脚本实现

文章目录 1. 写在前面2. 接口分析3. 算法脚本实现 【&#x1f3e0;作者主页】&#xff1a;吴秋霖 【&#x1f4bc;作者介绍】&#xff1a;擅长爬虫与JS加密逆向分析&#xff01;Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Py…

数据库系统原理练习 | 作业2-第2章关系数据库(附答案)

整理自博主本科《数据库系统原理》专业课完成的课后作业&#xff0c;以便各位学习数据库系统概论的小伙伴们参考、学习。 *文中若存在书写不合理的地方&#xff0c;欢迎各位斧正。 专业课本&#xff1a; 目录 一、选择题 二、填空题 三、简答题 四、关系代数 1.课本p70页&…

Vatee万腾平台:引领智能互联新时代

在科技浪潮的推动下&#xff0c;我们正步入一个前所未有的智能互联新时代。在这个时代里&#xff0c;万物皆可互联&#xff0c;数据成为新的生产要素&#xff0c;智能技术深刻改变着人类社会的每一个角落。而Vatee万腾平台&#xff0c;正是这一新时代的引领者&#xff0c;以其卓…

盘点各个国家的国宝

中国&#xff1a;熊猫 熊猫已有800万年的历史&#xff0c;和它们同时代的动物都已灭绝&#xff0c;大熊猫生存至今成为“活化石”。 俄罗斯&#xff1a;北极熊 北极熊是世界上最大的陆地食肉动物&#xff0c;体型巨大&#xff0c;性格凶猛。 美国&#xff1a;白头海雕 白头海雕…

事件分发机制:demo复现自定义ViewGroup点击事件不起作用

几年前遇到的一个bug&#xff0c;不弄清楚心里就是不舒服&#xff01; 平时应用开发中&#xff0c;经常遇到的UI需求&#xff0c;例如抖音的设置界面&#xff0c;如下图所示&#xff1a; 很容易想到&#xff0c;自定义一个Layout&#xff0c;左边一个图标&#xff0c;中间文…

二维树状数组区域查询

落谷4514 过关代码如下 #define _CRT_SECURE_NO_WARNINGS #include<bits/stdc.h> using namespace std; //#define int long longconst int N 2050; int t1[N][N], t2[N][N], t3[N][N], t4[N][N]; int lowbit(int x) { return x & (-x); } int n, m; void update(…

@Slf4j idea标红Cannot resolve symbol ‘log‘

一、背景 时间久了没有应用idea,打开工程后项目 log 提示报红&#xff0c;未能解析&#xff0c;Cannot resolve symbol log &#xff0c;Slf4j 注解正常&#xff0c;应用的lombok插件。 检查lombok插件安装情况&#xff0c;发现未安装&#xff0c;重新安装重启idea后正常。 二…

zxing-cpp+OpenCV根据字符串生成条形码

编译构建 需要使用到 CMake、Git、GCC 或 MSVC。 github 链接&#xff1a;https://github.com/zxing-cpp/zxing-cpp 编译之前请确保&#xff1a; 确保安装了 CMake 版本 3.15 或更高版本。 确保安装了与 C17 兼容的编译器(最低VS 2019 16.8 / gcc 7 / clang 5)。 编译构建…

什么是 VueQuill(前端的富文本编辑器)?

什么是 VueQuill&#xff1f; 1. 简介 VueQuill 是 Vue.js 的一个富文本编辑器插件&#xff0c;它基于 Quill 编辑器构建&#xff0c;提供了简洁且功能强大的富文本编辑功能。Quill 是一个现代化的富文本编辑器&#xff0c;提供丰富的文本编辑能力&#xff0c;支持多种格式和…

Beats:使用 Filebeat 从 Python 应用程序中提取日志

本指南演示了如何从 Python 应用程序中提取日志并将其安全地传送到 Elasticsearch Service 部署中。你将设置 Filebeat 来监控具有标准 Elastic Common Schema (ECS) 格式字段的 JSON 结构日志文件&#xff0c;然后你将在 Kibana 中查看日志事件发生的实时可视化。虽然此示例使…