UE 录屏自动化上传阿里云OSS

前言

       最近在做一个功能,然后就发现了一个很有趣的东西,虽然在一定程度上属于偷懒,但是在一些短频快的应用中还是很适用的,下面我就针对于这个测试做一些简单的分享,希望帮助到大家,在实际的开发中获得一些灵感和帮助,具体的实现方式,UE通过Texture2D将每一帧的图片存储到本地,存完以后调用一个本地PythonEXE执行文件进行视频封装和OSS上传,我这里使用的版本UE5.3,大家根据代码自己调试下。

UE开发调试过程

  1. 新建一个带有C++内容的项目,因为有一些代码功能需要用到C++,我这里的名称因为创建过了所以有个提示。
  2. 然后在Edit -> Plugins -> Add点击新建一个BlueprintLibeary的插件,因为我个人写一些封装性功能的时候喜欢用插件,这样其他的项目用到的时候直接导入调用就可以了,如果你想在类里面使用的话创建一个BlueprintFunctionLibrary的类就可以了。
  3. 创建完插件后,会在VistualStudio中提示,直接点全部加载,然后点击全部保存关闭项目,因为有时候有些编译会有问题,在UE和VS都关闭的状态下,在你的工程根目录打开sln的VS主文件,我们直接进行操作
  4. 接下来在插件中TextureVideoBPLibrary.h和TextureVideoBPLibrary.cpp中,我们添加两个功能,打开.h文件将原有的函数进行删除然后添加我们新的函数
    // Copyright Epic Games, Inc. All Rights Reserved.#pragma once#include "Kismet/BlueprintFunctionLibrary.h"
    #include "TextureVideoBPLibrary.generated.h"/* 
    *	Function library class.
    *	Each function in it is expected to be static and represents blueprint node that can be called in any blueprint.
    *
    *	When declaring function you can define metadata for the node. Key function specifiers will be BlueprintPure and BlueprintCallable.
    *	BlueprintPure - means the function does not affect the owning object in any way and thus creates a node without Exec pins.
    *	BlueprintCallable - makes a function which can be executed in Blueprints - Thus it has Exec pins.
    *	DisplayName - full name of the node, shown when you mouse over the node and in the blueprint drop down menu.
    *				Its lets you name the node using characters not allowed in C++ function names.
    *	CompactNodeTitle - the word(s) that appear on the node.
    *	Keywords -	the list of keywords that helps you to find node when you search for it using Blueprint drop-down menu. 
    *				Good example is "Print String" node which you can find also by using keyword "log".
    *	Category -	the category your node will be under in the Blueprint drop-down menu.
    *
    *	For more info on custom blueprint nodes visit documentation:
    *	https://wiki.unrealengine.com/Custom_Blueprint_Node_Creation
    */
    UCLASS()
    class UTextureVideoBPLibrary : public UBlueprintFunctionLibrary
    {GENERATED_UCLASS_BODY()UFUNCTION(BlueprintCallable, meta = (DisplayName = "SavePixtureToFile", KeyWords = "Save Pic To File"), Category = "TextureVideoTesting")static bool SavePicToFile(UTextureRenderTarget2D* rt, const FString& fileDestination);UFUNCTION(BlueprintCallable, meta = (DisplayName = "OpenExeVideo", Keywords = "Open Exe Video"), Category = "TextureVideoTesting")static bool OpenExe(FString URL);
    };
    
  5. 在cpp文件中我们添加以下逻辑,大家看到这里的时候基本已经知道了这两个函数的作用一个是存储图片一个是打开exe
    // Copyright Epic Games, Inc. All Rights Reserved.#include "TextureVideoBPLibrary.h"
    #include "TextureVideo.h"
    #include "Engine/TextureRenderTarget2D.h"
    #include "Misc/FileHelper.h"
    #include <ImageUtils.h>UTextureVideoBPLibrary::UTextureVideoBPLibrary(const FObjectInitializer& ObjectInitializer)
    : Super(ObjectInitializer)
    {}bool UTextureVideoBPLibrary::SavePicToFile(UTextureRenderTarget2D* rt, const FString& fileDestination)
    {FTextureRenderTargetResource* rtResource = rt->GameThread_GetRenderTargetResource();FReadSurfaceDataFlags readPixelFlags(RCM_UNorm);TArray<FColor> outBMP;for (FColor& color : outBMP){color.A = 255;}outBMP.AddUninitialized(rt->GetSurfaceWidth() * rt->GetSurfaceHeight());rtResource->ReadPixels(outBMP, readPixelFlags);FIntPoint destSize(rt->GetSurfaceWidth(), rt->GetSurfaceHeight());TArray<uint8> CompressedBitmap;FImageUtils::CompressImageArray(destSize.X, destSize.Y, outBMP, CompressedBitmap);bool imageSavedState = FFileHelper::SaveArrayToFile(CompressedBitmap, *fileDestination);return imageSavedState;
    }bool UTextureVideoBPLibrary::OpenExe(FString URL)
    {FProcHandle ExeHandle = FPlatformProcess::CreateProc(*URL, nullptr, true, false, false, nullptr, 0, nullptr, nullptr);bool ret = FPlatformProcess::IsProcRunning(ExeHandle);return ret;
    }
    
  6. 然后对项目进行清理和重新生成,如果重新编译的过程中出现了报错,别管他,全部保存,然后关闭VS再重新打开再次编译生成即可。编译后打开我们的UE,在UE插件的Content文件中我们可以创建一个BP文件夹放置我们的一些文件,鼠标右键在Texture中创建一个RenderTarget文件用来进行渲染UE画面
  7. 双击打开我们的RenderTarget,将SizeX和SizeY进行调试,这是我们最终生成图片的比例,但是这块,大家要实际和电脑性能进行以下调试,因为图片分辨率越大输出渲染占用的资源就越高,所以这块自己在用的时候要注意下。
  8. 新建一个Actor,我这里用的画面是一个角色,所以我就创建了一个Character类型的Actor,这块根据自己需求不需要的话,就创建一个基础的Actor就可以,打开新建的Actor,在Add中添加一个SceneCaptureComponent2D组件,我这里都在一起所以我直接就调整了它们之间的位置关系,如果你这块是不需要的话,那你直接把Actor拖拽到场景中调整位置关系即可,然后点击SceneCaptureComponent2D组件,细节中的TextureTarget设置为刚才创建的RenderTarget
  9. 现在插件功能开发和基础的设置就已经做完了,接下来我们开始进行调试我们的功能,考虑到后续UE可能进行打包操作,这块的路径我就直接设置为插件路径,在插件目录下创建了一个VideoInDEP的文件下面有三个文件Image;Video;Data,Image和Video就是存放我们的缓存图片和缓存视频,Data是可调整的一个参数文件,EXE为调用执行的文件
  10. 在事件开始运行时,我们对图片还有EXE进行了变量存储,这的SetActorHiddenInGame作用是为了隐藏项目运行可能会出现一个控制器小球,然后ImagePath和VideoPath创建两个字符串的变量进行连接即可
  11. 现在开始图片存储功能通过一个事件委托,我们调用SavePixtureToFile的函数节点,将其进行设置Rt是我们创建的RnderTarget,Timer提示为变量这个变量作用是在关闭的时候断开捕捉存储图片用的,新建一个int变量初始值为0,然后作为图片下标进行使用,接下来你就可以测试第一个功能图片存储,直接调用SaveImage自定义事件,在我们的插件对应的路径下你就会看到你生成的图片,这里time为0.04秒,就是40毫秒,也就是一秒25帧。
  12. 第二个功能打开EXE,这块你可以先随便找个exe进行测试只要路径填写对就可以测试

 Python开发流程

  1. 我这用的最新的Pycharm写的,不会Python的也没关系我后面会把插件还有EXE链接放到下面的直接下载也能用,新建一个工程和一个py文件命名为VideoToOSS,这里oss的包的装以下,直接终端pip install oss2就行,有其他包的环境如果提示没有的话记得也装一下,代码
    #ImageToVideo
    import cv2
    import os
    import sys
    import glob#数据上传
    import oss2
    import jsondataPath = os.path.dirname(os.path.realpath(sys.executable)) + '\\Data\\data.json'def ImageToVideo(ImagePath,VideoPath,Fps,PngImage):print('This is PNG Path:',ImagePath)print('This is Video Path:',VideoPath)fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')  # 设置输出视频为mp4格式# size要和图片的size一样,但是通过img.shape得到图像的参数是(height,width,channel),# 可以实现在图片文件夹下查看图片属性,获得图片的分辨率size = (1024, 768)video = cv2.VideoWriter(VideoPath, fourcc, Fps, size)  # 设置保存视频的名称和路径,默认在根目录下file_lst = os.listdir(ImagePath)count = 0for filename in file_lst:img = cv2.imread(ImagePath + 'TextureImage' + str(count) + '.png')count += 1video.write(img)video.release()delete_all_pngs(PngImage,VideoPath)
    def delete_all_pngs(folder_path,Video_Path):# 使用glob查找文件夹下所有的.png文件png_files = glob.glob(os.path.join(folder_path, '*.png'))# 遍历并删除找到的文件for png_file in png_files:try:os.remove(png_file)#print(f"已删除: {png_file}")except OSError as e:print(f"删除失败: {png_file} - {e.strerror}")print("This set of data has now been deleted!")VideoToOSS(Video_Path)def JsonToStr(JsPath):with open(JsPath, 'r', encoding='utf-8') as file:json_data = json.load(file)return json_dataprint(json_data)def VideoToOSS(VideoPath):access_key_id = JsonToStr(dataPath)['access_key_id']access_key_secret = JsonToStr(dataPath)['access_key_secret']endpoint = JsonToStr(dataPath)['endpoint']bucket_name = JsonToStr(dataPath)['bucket_name']object_name = JsonToStr(dataPath)['object_name']  # OSS上的对象路径和名称local_file = VideoPath# 创建Bucket的句柄auth = oss2.Auth(access_key_id, access_key_secret)bucket = oss2.Bucket(auth, endpoint, bucket_name)# 上传文件bucket.put_object_from_file(object_name, local_file)print(f"文件 {local_file} 已成功上传到 OSS,路径为 {object_name}")if os.path.exists(local_file):os.remove(local_file)print(f"本地缓存文件 {local_file} 已被删除")else:print(f"文件 {local_file} 不存在")# 按装订区域中的绿色按钮以运行脚本。
    if __name__ == '__main__':#本地的图片视频地址信息PathVideo = os.path.dirname(os.path.realpath(sys.executable)) + '\\Video\\result.mp4'PathImage = os.path.dirname(os.path.realpath(sys.executable)) + '\\Image\\'PathDelayImage = os.path.dirname(os.path.realpath(sys.executable)) + '\\Image'FpsPath = JsonToStr(dataPath)['Video_fps']ImageToVideo(PathImage,PathVideo,FpsPath,PathDelayImage)
  2. 这是完整逻辑,函数ImageToVideo用来将图片转为视频的,delete_all_pngs函数作用是将本地图片进行删除的,JsonToStr是用来读取本地设置信息的,VideoToOSS将本地视频提交OSS然后进行删除,main就是调用了,这块东西很简单自己看下就会了,然后把代码进行打包在终端直接打包,运行完成后会在本地生成一个EXE执行文件
    
    Pyinstaller -F VideoToOSS.py
  3. data.json中是我们的oss的配置信息,这块我就不写了,自己找一下配置一下就行,Videofps是视频生成时的帧数
    {"Video_fps": 25,"access_key_id": "<自己的KeyID>","access_key_secret": "<自己的secre>","endpoint": "<自己的服务地址>","bucket_name": "<自己的bucket文件名称>","object_name": "video/object.mp4"
    }

 结语

        确保最终的UE打开EXE名称为VideoToOSS,基本的使用过程就是这样,因为UE直接做视频和OSS需要对于的FFMPEG或者OSS其他库,处理起来很麻烦,很多应用也不一定能找到,通过这种方式可以巧妙的解决掉这个麻烦,如果你觉得exe没有回调的话出现问题时怎么办,可以做一个简单的通信,让UE和这个EXE去协同处理来解决或者通过句柄的方式,但是这块呢大家各自发挥。

链接:https://pan.baidu.com/s/1DI-iWjwAO9Hy4pQGE6FInA 
提取码:8i55 

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

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

相关文章

计算机视觉——OpenCV Python基于颜色识别的目标检测

1. 计算机视觉中的颜色空间 颜色空间在计算机视觉领域的应用非常广泛&#xff0c;它们在图像和视频处理、物体检测等任务中扮演着重要角色。颜色空间的主要作用是将颜色以数值形式表示出来&#xff0c;这样计算机算法就能够对其进行处理和分析。不同的颜色空间有着不同的特点和…

Pytorch搭建GoogleNet神经网络

一、创建卷积模板文件 因为每次使用卷积层都需要调用Con2d和relu激活函数&#xff0c;每次都调用非常麻烦&#xff0c;就将他们打包在一起写成一个类。 in_channels&#xff1a;输入矩阵深度作为参数输入 out_channels: 输出矩阵深度作为参数输入 经过卷积层和relu激活函数…

0基础如何入门编程?

0基础如何进入IT行业 &#xff1f; 前言 简介&#xff1a;对于没有任何相关背景知识的人来说&#xff0c;如何才能成功进入IT行业&#xff1f;是否有一些特定的方法或技巧可以帮助他们实现这一目标&#xff1f; 主要方法有如下几点建议提供给宝子们 目录 免费视频网课学习…

36、二叉树-二叉树的中序遍历

思路&#xff1a; 二叉树的遍历可以有 前序&#xff0c;中序&#xff0c;后序&#xff0c;层序遍历。 前序&#xff1a;头左右中序&#xff1a;左头右后序&#xff1a;左右头层序:从左往右依次遍历 实现方式&#xff1a; 递归通过栈结构便于回溯 代码如下&#xff1a; c…

3D模型处理的并行化

今天我们将讨论如何使用 Python 多进程来处理大量3D数据。 我将讲述一些可能在手册中找到的一般信息&#xff0c;并分享我发现的一些小技巧&#xff0c;例如将 tqdm 与多处理 imap 结合使用以及并行处理存档。 那么我们为什么要诉诸并行计算呢&#xff1f; 使用数据有时会出现…

Backend - DRF 序列化(django-rest-framework)

目录 一、restful 、django-rest-framework 、swagger 三者的关系 &#xff08;一&#xff09;restful API&#xff08;REST API&#xff09; 1. rest 2. restful 3. api 4. restfulAPI &#xff08;二&#xff09;django-rest-framework&#xff08;简称DRF&#xff09…

Web3D智慧医院平台(HTML5+Threejs)

智慧医院的建设将借助物联网、云计算、大数据、数字孪生等技术&#xff0c;以轻量化渲染、极简架构、三维可视化“一张屏”的形式&#xff0c;让医院各大子系统管理既独立又链接&#xff0c;数据相互融合及联动。 建设医院物联网应用的目标对象&#xff08;人、物&#xff09;都…

7 pytorch DataLoader, TensorDataset批数据训练方法

前言 本文主要介绍pytorch里面批数据的处理方法&#xff0c;以及这个算法的效果是什么样的。具体就是要弄明白这个批数据选取的算法是在干什么&#xff0c;不会涉及到网络的训练。 from torch.utils.data import DataLoader, TensorDataset主要实现就是上面的数据集和数据载入…

pdf做批注编辑工具 最新pdf reader pro3.3.1.0激活版

PDF Reader Pro是一款功能强大的PDF阅读和编辑工具。它提供了多种工具和功能&#xff0c;帮助用户对PDF文档进行浏览、注释、编辑、转换和签名等操作。以下是PDF Reader Pro的一些主要特色&#xff1a; 最新pdf reader pro3.3.1.0激活版下载 多种查看模式&#xff1a;PDF Reade…

STM32 PB3 PB4 无法作为 GPIO 使用解决办法

如下所示&#xff0c;PA13 PA14 PB3 PB4 PB5, 默认是JTAG SWD的 PIN, 需要引脚ReMap 才能作为GPIO 使用。 HAL库解决办法 // __HAL_AFIO_REMAP_SWJ_ENABLE(); //Full SWJ (JTAG-DP SW-DP):// __HAL_AFIO_REMAP_SWJ_NONJTRST(); //Full SWJ (JTAG-DP SW-DP) but without NJTR…

【代理模式】静态代理-简单例子

在Java中&#xff0c;静态代理是一种设计模式&#xff0c;它涉及到为一个对象提供一个代理以控制对这个对象的访问。静态代理在编译时就已经确定&#xff0c;代理类和被代理类会实现相同的接口或者是代理类继承被代理类。客户端通过代理类来访问&#xff08;调用&#xff09;被…

认识异常(1)

❤️❤️前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; hellohello~&#xff0c;大家好&#x1f495;&#x1f495;&#xff0c;这里是E绵绵呀✋✋ &#xff0c;如果觉得这篇文章还不错的话还请点赞❤️❤️收藏&#x1f49e; &#x1f49e; 关注&#x1f4a5;&a…

计算机网络:MAC地址 IP地址 ARP协议

计算机网络&#xff1a;MAC地址 & IP地址 & ARP协议 MAC地址IP地址ARP协议 MAC地址 如果两台主机通过一条链路通信&#xff0c;它们不需要使用地址就可以通信&#xff0c;因为连接在信道上的主机只有他们两个。换句话说&#xff0c;使用点对点信道的数据链路层不需要使…

开源 Ruo-Yi 项目引入 Mybatis-Plus:3.5.3 报错ClassNotFoundException:

开源 Ruo-Yi 项目引入 Mybatis-Plus:3.5.3 报错ClassNotFoundException&#xff1a; Caused by: java.lang.ClassNotFoundException: com.baomidou.mybatisplus.extension.plugins.MybatisPlusInter1 分析问题 控制台报错说明我们引入的 mybatis-plus 的依赖里找不到com.baom…

数字化转型-工具变量数据集

01、数据介绍 数字化转型是指企业或个人利用数字技术&#xff0c;如大数据、云计算、人工智能等&#xff0c;对其业务流程、运营模式、决策方式等进行全面、深入的变革&#xff0c;以提高效率、降低成本、提升质量、增强竞争力。在这个过程中&#xff0c;工具变量扮演着至关重…

JVM虚拟机(九)如何开启 GC 日志

目录 一、引言二、开启 GC 日志三、解析 GC 日志四、优化建议 一、引言 在 Java 应用程序的运行过程中&#xff0c;垃圾收集&#xff08;Garbage Collection&#xff0c;简称 GC&#xff09;是一个非常重要的环节。GC 负责自动管理内存&#xff0c;回收不再使用的对象所占用的…

zabbix 自动发现与自动注册 部署 zabbix 代理服务器

zabbix 自动发现&#xff08;对于 agent2 是被动模式&#xff09; zabbix server 主动的去发现所有的客户端&#xff0c;然后将客户端的信息登记在服务端上。 缺点是如果定义的网段中的主机数量多&#xff0c;zabbix server 登记耗时较久&#xff0c;且压力会较大。1.确保客户端…

一次配置Docker环境的完整记录

一次配置Docker环境的完整记录 Docker环境搭建报错与解决报错一报错二报错三 Docker环境搭建 本节介绍了一次配置docker环境的完整记录&#xff1a; 编写Dockerfile文件&#xff1a; FROM pytorch/pytorch:1.10.0-cuda11.3-cudnn8-develRUN rm /etc/apt/sources.list.d/cuda.l…

mfc 带有复选框的ListBox

mfc 带有复选框的 ListBox 效果&#xff1a; 添加 ListBox 控件 从工具箱拖拽 ListBox 控件到窗口上&#xff0c;并设置属性&#xff1a; 包含字符串&#xff1a;true所有者描述&#xff1a;Fixed 给ListBox添加控制变量 添加完后&#xff0c;将m_list_box的类型使用CC…

Qt+vstudio2022的报错信息积累

从今天开始记录一下平常开发工作中的报错记录&#xff0c;后续有错误动态补充&#xff01; 报错信息&#xff1a;【MSB8041】此项目需要 MFC 库。从 Visual Studio 安装程序(单个组件选项卡)为正在使用的任何工具集和体系结构安装它们。 解决&#xff1a; 背景&#xff1a;换…