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

news2024/11/25 20:06:33

前言

       最近在做一个功能,然后就发现了一个很有趣的东西,虽然在一定程度上属于偷懒,但是在一些短频快的应用中还是很适用的,下面我就针对于这个测试做一些简单的分享,希望帮助到大家,在实际的开发中获得一些灵感和帮助,具体的实现方式,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 json
    
    dataPath = 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 = 0
        for filename in file_lst:
            img = cv2.imread(ImagePath + 'TextureImage' + str(count) + '.png')
            count += 1
            video.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_data
        print(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.coloradmin.cn/o/1599960.html

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

相关文章

三大变换(杂乱)

任何一个函数都可以看成是若干个三角函数的加权和 一、傅里叶变换 1、推导过程 资料&#xff1a;https://www.bilibili.com/video/BV1pW411J7s8/?spm_id_from333.1007.top_right_bar_window_history.content.click &#xff08;1&#xff09; e i θ e^{i\theta} eiθ代表…

策略模式:灵活调整算法的设计精髓

在软件开发中&#xff0c;策略模式是一种行为型设计模式&#xff0c;它允许在运行时选择算法的行为。通过定义一系列算法&#xff0c;并将每个算法封装起来&#xff0c;策略模式使得算法可以互换使用&#xff0c;这使得算法可以独立于使用它们的客户。本文将详细介绍策略模式的…

前端大文件上传 -- 上传文件到S3或本地服务器

特别提醒 大文件上传的文件切片逻辑, 包括如何将分片文件上传到本地服务器, 请查看之前的文章: 前端大文件上传 - 总结&#xff08;Vue3 hook Web Worker实现&#xff0c;通过多个Worker线程大大提高Hash计算的速度&#xff09;, 本篇仅实现如何将大文件分块上传到S3. 后面写…

Yolo-world使用

1、安装 python pip install ultralytics 前往官网下载模型&#xff1a;https://docs.ultralytics.com/models/yolo-world/#key-features 我这里使用yolov8s-world.pt举例 最简单的使用示例 if __name__ __main__:model YOLO(model/yolov8s-world.pt)results model.pre…

力扣101. 对称二叉树(java)

思路&#xff1a; 一、验证 左右子树是否可翻转对称的&#xff1f; 二、分析左右子树情况&#xff1a; 1&#xff09;左右都也空 对称 2&#xff09;左右有一个为空 不对称 3&#xff09;左右都不为空&#xff0c;但数字不同 不对称 4&#xff09;左右都不为空&#xff0c;且数…

ENVI实战—一文学会使用GLT配准工具对风云数据进行几何校正

实验2&#xff1a;学会使用GLT配准工具 目的&#xff1a;完成气象卫星数据的校正&#xff0c;掌握利用GLT配准工具实验地理配准的方法 过程&#xff1a; ①读取影像&#xff1a;选择“文件”&#xff0c;选择“HS5”文件并打开&#xff0c;在弹出的科学数据集浏览器中&#x…

保姆级教程 | Adobe Illustrator 中插入数学符号

背景 鉴于Adobe Illustrator作为比较专业的绘图/组图软件&#xff0c;我的论文数据作图都会选择先在origin中把原始数据绘制好&#xff0c;后都放入AI中细修。由于在作图过程中需要插入数学符号&#xff0c;但仿佛没有PowerPoint用起来那么熟悉&#xff0c;遂记录下。 步骤 …

高分二号卫星(GF-2):中国遥感科技的新高度

​高分二号卫星&#xff08;GF-2&#xff09;是中国在高分辨率地球观测领域的重要成就&#xff0c;其引入了先进的成像技术和灵活的数据获取模式&#xff0c;为地球资源监测、环境保护、城市规划等领域提供了强大的数据支持。本文将深入介绍高分二号卫星的技术特点、成像能力以…

Methoxy PEG Tosylate可以用于制备特定化合物、改变分子的溶解性和生物活性

【试剂详情】 英文名称 mPEG-OTs,mPEG-Tosylate, Methoxy PEG Tosylate 中文名称 聚乙二醇单甲醚对甲苯磺酸酯&#xff0c; 甲氧基聚乙二醇甲苯磺酸酯 外观性状 取决于分子量&#xff0c;粘稠液体或固体 分子量 400&#xff0c;600&#xff0c;2k&#xff0c;3.4k&#…

JavaWeb前端/后端开发规范——接口文档概述及YApi平台的使用

前言&#xff1a; 整理下笔记&#xff0c;打好基础&#xff0c;daydayup!!! 接口文档 什么是接口文档&#xff1f; 目前主流的开发模式为前后端分离式开发&#xff0c;为了方便前后端的对接&#xff0c;就需要使用接口文件进行统一规范。 接口文档记载什么信息&#xff1f; 1&…

【C/C++笔试练习】read函数、虚拟存储、用户态、线程特点、缺页处理、调度算法、进程优先级、锁的使用、创建进程、不用加减乘除做加法、三角形

文章目录 C/C笔试练习选择部分&#xff08;1&#xff09;read函数&#xff08;2&#xff09;虚拟存储&#xff08;3&#xff09;用户态&#xff08;4&#xff09;线程特点&#xff08;5&#xff09;缺页处理&#xff08;6&#xff09;调度算法&#xff08;7&#xff09;进程优先…

动态IP代理API的应用与优点

“动态”意味着每次连接或每隔一段时间&#xff0c;用户的IP地址都会发生改变。由于IP地址的不断变化&#xff0c;用户可以避免因频繁访问同一网站而导致的IP被封锁的问题。API叫做应用程序接口&#xff0c;是一种让软件之间相互通信的接口。API允许用户通过编程方式来调用动态…

vs2019 - detected memory leak

文章目录 vs2019 - detected memory leak概述笔记vs2019 consolevs2019 MFC Dlg但是&#xff0c;工程大了之后&#xff0c;VS2019提示的就变了样整好的内存泄漏侦测头文件和实现my_debug_new_define.hmy_debug_new_define.cpp在所有.cpp文件入口处包含my_debug_new_define.h包含…

深度学习 Lecture 8 决策树

一、决策树模型&#xff08;Decision Tree Model) 椭圆形代表决策节点&#xff08;decison nodes)&#xff0c;矩形节点代表叶节点&#xff08;leaf nodes)&#xff0c;方向上的值代表属性的值&#xff0c; 构建决策树的学习过程&#xff1a; 第一步&#xff1a;决定在根节点…

【切换网络连接后】VMware虚拟机网络配置【局域网通信】

初次安装Linux虚拟机以及切换网络都需要配置虚拟机网络&#xff0c; 从而使得win主机内通过远程连接工具能够连接该虚拟机&#xff0c; 而不是在虚拟机内操作。 本片文章你将了解到网络切换后如何配置虚拟机网络的一些基础操作&#xff0c;以及局域网通信的一些基础知识。 …

一文看懂CRMEB开源商城系统与标准版之间的区别

一直以来&#xff0c;CRMEB开源商城系统和标准版商城系统都在被比较&#xff0c;很多人都会疑问&#xff0c;为什么有免费的开源商城系统&#xff0c;还有那么多人去购买商业版的CRMEB标准版商城系统呢&#xff1f;其实&#xff0c;在纠结到底选哪款系统时&#xff0c;我们不妨…

重磅消息:CnosDB 文档网站升级全新框架啦!

我们很高兴地宣布&#xff0c;CnosDB 文档网站迎来了一次重大升级&#xff01;现在&#xff0c;我们采用了全新的强大的开源文档框架&#xff0c;为用户提供更流畅、更直观的浏览体验。 全新框架带来的优势&#xff1a; 更快速的加载速度&#xff1a;现在您可以更快地访问并查…

运输问题的中转或者转运问题

1、这类问题&#xff0c;不好理解&#xff0c;做个笔记&#xff0c;记录一下。 2、可以参考一下&#xff1a; https://blog.csdn.net/YUNCHOUSHUO/article/details/121660675?spm1001.2014.3001.5506 这个csdn写的还是不错的&#xff0c;推荐。 或者&#xff0c;可以参考 …

飞腾UEFI电源控制选择代码解析

飞腾UEFI电源控制选择代码解析 CPLD 处理方式EC 处理方式注:本文以飞腾UEFI edk-code-4.2.0版本进行说明,如果有朋友需要借鉴,请使用该版本代码。 以D2000打工工具为例,下图打包工具中有选择主板电源管理方式,这里可以选择CPLD、EC、和SE,其中SE代表为X100控制上下电时序…

2024年面试工具篇Postman面试题及答案

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…