Unity实现摄像头录像功能

news2024/11/24 19:44:16

Unity实现摄像头录像功能

前言

在之前的很多展馆展示的项目中,甲方有很多要求实现用摄像头录像的功能。使用Unity实现调用USB摄像头画面的功能非常容易实现,但是实现录屏的功能有一些困难,我使用了几种方法都没有实现出想要的效果,后来我在网上找到一款叫做AVProMovieCapture的插件,实现了录屏的良好效果,同时也实现了使用Unity实现摄像头录像的效果,具体实现方法如下所示:

实现步骤

1.在项目中导入AVProMovieCapture插件,如下图所示:
在这里插入图片描述
2.在场景中新建plane物体,设置如下图所示:
在这里插入图片描述3.在场景中拖入ScreenGameObject物体,如下图所示:
在这里插入图片描述
4.在场景中新建WebCapture物体,在该物体上挂载WebCapture.cs脚本,脚本代码如下图所示:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace RenderHeads.Media.AVProMovieCapture.Demos
{
    public class WebCapture : MonoBehaviour
    {
        private class Instance
        {
            public string name;
            public WebCamTexture texture;
            public CaptureFromTexture capture;
            public CaptureGUI gui;
        }

        [SerializeField]
        private GUISkin _skin;

        //[SerializeField]
        //private GameObject _prefab;

        [SerializeField]
        private int _webcamResolutionWidth = 1920;

        [SerializeField]
        private int _webcamResolutionHeight = 1080;

        [SerializeField]
        private int _webcamFrameRate = 30;

        //State
        private Instance[] _instances;
        private int _selectedWebcamIndex;
        //显示视频的面板
        public MeshRenderer plane;
        //调用录像的脚本物体
        public CaptureGUI captureObject;

        private void Start()
        {
            //Create instance data per webcam
            int numCams = WebCamTexture.devices.Length;
            _instances = new Instance[numCams];
            for (int i = 0;i < numCams;i++)
            {
                //GameObject go = (GameObject)GameObject.Instantiate(_prefab);

                Instance instance = new Instance();
                instance.name = WebCamTexture.devices[i].name;
                //instance.capture = go.GetComponent<CaptureFromTexture>();
                instance.capture = captureObject.gameObject.GetComponent<CaptureFromTexture>();
                instance.capture._autoFilenamePrefix = "Demo4Webcam-" + i;
                //instance.gui = go.GetComponent<CaptureGUI>();
                instance.gui = captureObject.gameObject.GetComponent<CaptureGUI>();
                instance.gui._showUI = true;

                _instances[i] = instance;
            }

            if (numCams > 0)
            {
                Change(0);
            }
            StartCoroutine(OpenCamera());
            //captureObject = GameObject.Find("ScreenGameObject(Clone)").GetComponent<CaptureGUI>();
        }
        /// <summary>
        /// 开启摄像头
        /// </summary>
        /// <returns></returns>
        IEnumerator OpenCamera()
        {
            yield return new WaitForSeconds(0.5f);
            beginCamera();
            yield return new WaitForSeconds(0.5f);
            captureObject.ToStartCapture();
        }

        private void StartWebcam(Instance instance)
        {
            instance.texture = new WebCamTexture(instance.name,_webcamResolutionWidth,_webcamResolutionHeight,_webcamFrameRate);
            instance.texture.Play();
            if (instance.texture.isPlaying)
            {
                instance.capture.SetSourceTexture(instance.texture);
                plane.material.mainTexture = instance.texture;
            }
            else
            {
                StopWebcam(instance);
            }
        }

        private void StopWebcam(Instance instance)
        {
            if (instance.texture != null)
            {
                if (instance.capture != null && instance.capture.IsCapturing())
                {
                    instance.capture.SetSourceTexture(null);
                    instance.capture.StopCapture();
                }
                instance.texture.Stop();
                Destroy(instance.texture);
                instance.texture = null;
            }
        }

        private void OnDestroy()
        {
            for (int i = 0;i < _instances.Length;i++)
            {
                StopWebcam(_instances[i]);
            }
        }

        private void Change(int index)
        {
            _selectedWebcamIndex = index;
            for (int j = 0;j < _instances.Length;j++)
            {
                _instances[j].gui._showUI = (j == _selectedWebcamIndex);
            }
        }
        /// <summary>
        /// 开启摄像头
        /// </summary>
        public void beginCamera()
        {
            for (int i = 0;i<_instances.Length;i++)
            {
                Instance webcam = _instances[i];
                StartWebcam(webcam);
            }
        }
    }
}

5.运行场景,发现已经调用了摄像头,如下图所示:
在这里插入图片描述
6.虽然调用了摄像头,但是不知道是否已经进行了录像,查找到工程下的movie文件夹,发现已经录入了视频,从而实现了使用usb摄像头录像的功能,如下图所示:
在这里插入图片描述
7.实现录像功能,有的需求还需要获取到这些视频并且展示出来,这个也在我之前的项目实现了,具体怎么实现不再赘述了,在这里将核心代码分享在这里:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;


public class Load : MonoBehaviour
{
    public List<string> filePaths;
    public static string[][] pic;
    private List<string> LAN;
    private string movieUrl;
    //遍历的视频数量
    public static int movieNumber = 0;

    private void Start()
    {
        movieUrl = ConfigTest.dic["录像路径"]["url"];
        LAN = new List<string>();
        LAN.Add(movieUrl);
        pic = new string[LAN.Count][];
        Debug.Log(pic.Length);
        LoadIma();
    }

    void LoadIma()
    {
        for (int i = 0;i < pic.Length;i++)
        {
            pic[i] = (load(LAN[i],i));
        }
    }

    string[] load(string LAN,int t)
    {
        filePaths = new List<string>();
        string imgtype = "*.mp4|*.mov|*.avi";
        string[] ImageType = imgtype.Split('|');
        for (int i = 0;i < ImageType.Length;i++)
        {
            //获取所有视频视频的路径
            string[] dirs = Directory.GetFiles(@"" + LAN,ImageType[i]);
            //Debug.Log(dirs.Length);
            //movieNumber = dirs.Length;
            for (int j = 0;j < dirs.Length;j++)
            {
                filePaths.Add(dirs[j]);
                movieNumber = j;
                //Debug.Log(movieNumber);
            }
        }
        return fuzhi(t);
    }

    public string[] fuzhi(int t)
    {
        pic[t] = new string[filePaths.Count];
        for (int i = 0; i < filePaths.Count;i++)
        {
            pic[t][i] = filePaths[i];
        }
        return pic[t];
    }
}

结尾语

网上开发的各种大神有很多,他们开发出许许多多的插件供我们使用,极大节省了我们的开发时间,在这里向他们表示感谢。我作为一名Unity小菜鸟,希望和大家有问题一起讨论,共同进步,大家有问题可以私聊我。

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

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

相关文章

广播实现强制下线功能

实现强制下线功能 强制下线应该是一个比较常用的功能,比如QQ在比的地方被登陆了,就会强制比被挤下线.强制下线的功能还是比较简单的,只需要在界面上弹出一个框,告知用户无法再进行任何操作即可.只能点击确定然后跳转至登录界面.强制下线功能需要关闭所有的Activity,然后返回到…

5 - 2 单选题

1.下列线索二叉树中&#xff08;用虚线表示线索&#xff09;&#xff0c;符合后序线索树定义的是&#xff1a;B 后序线索二叉树的构建流程就是&#xff1a; 1.后序遍历二叉树&#xff1a;d b c a 2.第一个结点的前驱是NULL&#xff0c;即d的前驱&#xff0c;d的左孩子为NULL …

在 Android 中创建静态应用程序快捷方式

您是否在日常应用程序中看到过快捷方式示例?可能像 Instagram、Discord、Medium 等。提供它们是为了帮助我们快速导航到应用程序内部的特定功能、屏幕或部分,而无需逐步浏览它们。 在本文中,我们将逐步实现静态快捷方式。但在我们开始编码之前,我们需要知道这个快捷方式到底…

大数据(9h)FlinkSQL之Lookup Join

文章目录概述pom.xmlMySQL建表对应Flink的建表SQLLookup JoinFlinkSQL完整Java代码概述 lookup join通常是 查询外部系统的数据 来 充实FlinkSQL的主表 例如&#xff1a;事实表 关联 维度表&#xff0c;维度表在外部系统&#xff08;如MySQL&#xff09;要求&#xff1a; 1个表…

中国多媒体与网络教学学报杂志社中国多媒体与网络教学学报编辑部2022年第9期目录

多媒体信息技术《中国多媒体与网络教学学报》投稿&#xff1a;cn7kantougao163.com 采油工程探索式虚拟仿真实验教学实践——以有杆抽油系统实验为例 窦祥骥 ;何岩峰 ;张少辉 ;王相 ;徐慧 ; 1-5 人体寄生虫课程网络虚拟实验环境的构建及其应用研究 周蕾;贺帅;李晓琳;席…

深入理解mysql执行的底层机制

MySql系列整体栏目 内容链接地址【一】深入理解mysql索引本质https://blog.csdn.net/zhenghuishengq/article/details/121027025【二】深入理解explain以及索引优化https://blog.csdn.net/zhenghuishengq/article/details/124552080【三】深入理解mysql事务本质https://blog.cs…

3dmax如何进行网络渲染?网渲云渲染渲染农场怎么用?

渲染本身是将3d模型转换为2d图像的一个过程&#xff0c;而网络渲染就是把3d模型放在云端进行完成&#xff0c;而本地我们只需要等待结果就好。而云渲染也就是网渲的标准称呼&#xff0c;两个是一个意思。 那怎么进行网络渲染呢&#xff1f; 首先我们需要下载网络渲染客户端&a…

03-Docker-Docker镜像的分层概念

目录 一、镜像是什么 二、UnionFS&#xff08;联合文件系统&#xff09; 三、Docker镜像加载原理 四、将容器生成为镜像Commit命令 一、镜像是什么 是一种轻量级、可执行的独立软件包&#xff0c;包含运行某个软件所需的所有内容&#xff0c;我们把应用程序和配置依赖打包好…

TextBox文本框与PasswordBox密码框水印

在开发一个软件和网页的时候&#xff0c;都会有一个功能&#xff0c;那就是登陆功能&#xff0c;有了登陆那就一定需要用户输入账号和密码&#xff0c;我们在写登陆页面都会想到使用TextBox和PasswordBox去完成这两个功能&#xff0c;但是有一个问题&#xff0c;那就是如果你使…

java EE初阶 — 线程的状态

文章目录1.状态的基本认识2.观察线程的所有状态3.线程状态和状态转移4.多线程的意义1.状态的基本认识 NEW 创建了 Thread 对象&#xff0c;但是还没调用 start&#xff08;内核里还没有创建对应的PCB&#xff09;TERMINATED 表示内核中的 PCB 已经执行完毕了&#xff0c;但是 …

zabbix监控触发器与报警动作

目录 一、环境准备 1、搭建zabbix基础环境 2、创建被监控主机 二、触发器概念 三、创建触发器 1、创建触发器步骤 2、触发器表达式 &#xff08;1&#xff09;表达式格式 &#xff08;2&#xff09;表达式函数 3、配置触发器 四、创建报警动作 1、设置邮箱服务器 …

学生选课系统

项目描述 通过项目背景的分析以及了解到现在学校面临的问题&#xff0c;特别需要一个选课管理系统保证学生信息以及各种课程成绩的准确性和实效性&#xff0c;通过利用计算机的高速计算和快速的统计分析&#xff0c;保证学生信息的最新记录。从教职工的角度老考虑&#xff0c;…

网络套接字编程(UDP协议)

文章目录预备知识socket&#xff08;网络套接字&#xff09;编程接口简单的UDP网络程序增加多用户可以互相通信预备知识 网络字节序 大端存储&#xff1a;数据的高字节内容保存在内存的低地址处&#xff0c;数据的低字节内容保存在内存的高地址处 小端存储&#xff1a;数据的高…

婚纱预订小程序开发,商家线上展示平台

婚纱代表着纯洁与忠贞&#xff0c;也是爱情永恒的见证者&#xff0c;穿上洁白的婚纱嫁给自己心爱的人是每个女生的梦想&#xff0c;婚纱对于每一个女生来说都有着重要的意义&#xff0c;所以选择一件美丽且适合的婚纱非常重要&#xff0c;因此人们在选择婚纱时会花费很多的时间…

MySQL数据库之索引

目录 一、MySQL索引简介 二、索引的作用 1、优点 2、缺点 三、创建索引的原则依据 四、索引的分类和创建 1、普通索引 2、唯一索引&#xff08;创建唯一键即创建唯一索引&#xff09; 3、主键索引&#xff08;和创建主键的方式一样&#xff09; 4、组合索引&#xff…

Python标准库之copy

1. copy标准库简介 Python 中赋值语句不复制对象&#xff0c;而是在目标和对象之间创建绑定 (bindings) 关系。对于自身可变或者包含可变项的集合对象&#xff0c;我们有时会需要生成其副本用于改变操作&#xff0c;进而避免改变原对象。 2. copy常用函数 2.1 copy.copy(x) …

R语言用ARIMA模型滑动时间窗口识别网络流量时间序列异常值

全文链接&#xff1a;http://tecdat.cn/?p30597最近我们被要求解决时间序列异常检验的问题。有客户在使用大量的时间序列。这些时间序列基本上是每10分钟进行一次的网络测量&#xff0c;其中一些是周期性的&#xff08;即带宽&#xff09;&#xff0c;而另一些则不是&#xff…

Android Jetpack Compose——一个简单的聊天界面

Jetpack Compose——聊天界面前言效果视频引入RowColumnTextImage聊天界面效果左边布局右边布局插入数据总结前言 目前声明式UI已经成为前端开发趋势&#xff0c;除了一开始的跨端开发React,Flutter等以及Web支持外&#xff0c;后续Android和IOS平台也相继推出声明式开发&…

零基础快速开发Vue图书管理系统—登录注册篇(一)

零基础快速开发Vue图书管理系统—登录注册篇&#xff08;一&#xff09; 一、图书管理系统项目功能 二、项目技术选型 前端主要采用&#xff1a;Vue3.x (vuex/vue-router)、Ant Design Vue、Axios等服务端主要采用&#xff1a;Node.js、Koa、Mongoose等数据库主要采用&#x…

Docker安装Redis集群失败经历汇总

在程序员的开发过程中&#xff0c;Redis可以说基本上是必不可少的缓存中间件。不管是二进制包还是docker安装Redis的文章在网上都是数不胜数。我之前自己玩Redis的时候基本不是二进制包安装就是docker安装&#xff0c;也没有尝试过集群方式。每次需要的时候&#xff0c;网上百度…