Unity之获取Avpro视频画面并在本地创建缩略图

一、效果 

获取StreamingAssets文件夹下的所有视频(包含其子文件夹),获取指定时间的视频画面,然后将图片保存到本地磁盘中。

二、关于Avpro的事件监听

当指定视频时间进度时会触发FinishedSeeking,代表加载完成这时我们在进行缩略图创建功能,否则视频帧未更新创建缩略图会出现问题。

//使用方法   
mediaPlayer.Events.AddListener(OnVideoEvent);//监听private void OnVideoEvent(MediaPlayer mp, MediaPlayerEvent.EventType et, ErrorCode errorCode){switch (et){case MediaPlayerEvent.EventType.MetaDataReady:Debug.Log("当元数据(宽度,持续时间等)可用时触发");break;case MediaPlayerEvent.EventType.ReadyToPlay:Debug.Log("可以播放");break;case MediaPlayerEvent.EventType.Started:Debug.Log("播放开始时触发");break;case MediaPlayerEvent.EventType.FirstFrameReady:Debug.Log("第一帧渲染完成");break;case MediaPlayerEvent.EventType.FinishedPlaying:Debug.Log("视频结束");break;case MediaPlayerEvent.EventType.Closing:Debug.Log("媒体关闭时触发");break;case MediaPlayerEvent.EventType.Error:Debug.Log("发生错误时触发");break;case MediaPlayerEvent.EventType.SubtitleChange:Debug.Log("字幕改变时触发");break;case MediaPlayerEvent.EventType.Stalled:Debug.Log("当介质停止时触发(例如。当失去与媒体流的连接时)");break;case MediaPlayerEvent.EventType.Unstalled:Debug.Log("当媒体从停止状态恢复时触发(例如。当失去的连接重新建立时)");break;case MediaPlayerEvent.EventType.ResolutionChanged:Debug.Log("当视频的分辨率发生变化(包括加载)时触发,用于自适应流");break;case MediaPlayerEvent.EventType.StartedSeeking:Debug.Log("搜索开始时触发");break;case MediaPlayerEvent.EventType.FinishedSeeking:Debug.Log("搜索完成时触发 Seek视频指定时间跳转结束后调用");break;case MediaPlayerEvent.EventType.StartedBuffering:Debug.Log("缓冲开始时触发");break;case MediaPlayerEvent.EventType.FinishedBuffering:Debug.Log("缓冲完成时触发");break;case MediaPlayerEvent.EventType.PropertiesChanged:Debug.Log("当任何属性被触发(例如立体声包装被改变)-这必须手动触发");break;case MediaPlayerEvent.EventType.PlaylistItemChanged:Debug.Log("当新项目在播放列表中播放时触发");break;case MediaPlayerEvent.EventType.PlaylistFinished:Debug.Log("当播放列表结束时触发");break;case MediaPlayerEvent.EventType.TextTracksChanged:Debug.Log("当添加或删除文本轨道时触发");break;}}

三、脚本

using System.IO;
using UnityEngine;
using RenderHeads.Media.AVProVideo;
using System.Collections.Generic;
using System.Collections;
using System;
using System.Linq;public struct ThumbnailData
{public Action OnComplete;      //回调函数public float thumbnailTime;    //时间戳,用于生成缩略图的位置public MediaPlayer mediaPlayer;
}public class ThumbnailGenerator : MonoBehaviour
{public MediaPlayer mediaPlayer;ThumbnailData thumbnailData;//缩略图数据List<string> videoPaths = new List<string>();//所有视频路径void Start(){//获取指定文件夹下的所有视频GetAllVideoFile($"{Application.streamingAssetsPath}");//创建缩略图数据thumbnailData = new ThumbnailData(){OnComplete = () => { Debug.Log("********创建结束*******"); },thumbnailTime = 5,//缩略图时间mediaPlayer = mediaPlayer,};//创建缩略图GenThumbnail(thumbnailData);}#region 获取指定文件夹所有视频文件void GetAllVideoFile(string path){//获取文件夹下指定类型视频videoPaths = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories).Where(s => IsAssignTypeFile(s)).ToList();}/// <summary>/// 判断是否是指定类型文件/// </summary>/// <param name="suffix">文件后缀</param>/// <returns></returns>bool IsAssignTypeFile(string suffix){string[] types = ".vid|.mp4|.wav".Split('|');//设置指定后缀//是指定类型for (int i = 0; i < types.Length; i++)if (suffix.EndsWith(types[i])) return true;return false;}#endregion#region 创建缩略图public void GenThumbnail(ThumbnailData _thumbnailData){thumbnailData = _thumbnailData;//视频状态监听 创建thumbnailData.mediaPlayer.Events.AddListener(OnVideoEvent);thumbnailData.mediaPlayer.OpenMedia(MediaPathType.AbsolutePathOrURL, videoPaths[0], false);thumbnailData.mediaPlayer.Control.Seek(thumbnailData.thumbnailTime);// 执行Seek操作}#endregion#region 视频状态监听int index;//当前视频地址private void OnVideoEvent(MediaPlayer mp, MediaPlayerEvent.EventType et, ErrorCode errorCode){switch (et){case MediaPlayerEvent.EventType.FinishedSeeking:Debug.Log("搜索完成时触发");//本地创建缩略图CreateThumbnailsLocally(mp);break;}}#endregion#region 在本地创建缩略图void CreateThumbnailsLocally(MediaPlayer mp){string path = mp.MediaPath.Path;//获取视频 RenderTextureRenderTexture renderTexture = GetVideoRenderTexture(mp);//将RenderTexture转换成texture2DTexture2D texture2D = RenderTexture2Texture2D(renderTexture);//将Texture2D写入本地string previewPath = Path.Combine(Path.GetDirectoryName(path), Path.GetFileNameWithoutExtension(path)) + ".png";Texture2dWriteLocal(texture2D, previewPath);//创建下一个缩略图index++;if (index < videoPaths.Count){Debug.Log("加载下一个缩略图:" + videoPaths[index]);//播放视频mp.OpenMedia(MediaPathType.AbsolutePathOrURL, videoPaths[index], false);mp.Control.Seek(thumbnailData.thumbnailTime);// 执行Seek操作}elsethumbnailData.OnComplete?.Invoke();//执行回调}#endregion#region 获取视频 RenderTextureMaterial mt;RenderTexture GetVideoRenderTexture(MediaPlayer mp){if (mt == null){mt = new Material(Shader.Find("AVProVideo/Internal/Resolve"));mt.color = Color.white;//颜色设置mt.DisableKeyword("USE_HSBC");//禁用USE_HSBC关键字}VideoRender.SetupMaterialForMedia(mt, mp, -1); //设置材质贴图等VideoRender.ResolveFlags resolveFlags = (VideoRender.ResolveFlags.ColorspaceSRGB | VideoRender.ResolveFlags.Mipmaps | VideoRender.ResolveFlags.PackedAlpha | VideoRender.ResolveFlags.StereoLeft);//播放器标志return VideoRender.ResolveVideoToRenderTexture(mt, null, mp.TextureProducer, resolveFlags);//将视频解析为RenderTexture}#endregion#region 将RenderTexture转换为Texture2Dprivate static Texture2D RenderTexture2Texture2D(RenderTexture renderTexture){int width = renderTexture.width;int height = renderTexture.height;Texture2D texture2D = new Texture2D(width, height, TextureFormat.ARGB32, false);RenderTexture.active = renderTexture;texture2D.ReadPixels(new Rect(0, 0, width, height), 0, 0);texture2D.wrapMode = TextureWrapMode.Clamp;texture2D.Apply();return texture2D;}#endregion#region 将Texture2d写入本地void Texture2dWriteLocal(Texture2D texture2D, string localPath){File.WriteAllBytes(localPath, texture2D.EncodeToPNG());}#endregion}

在使用avpro制作缩略图时,我尝试使用mediaPlayer.TextureProducer.GetTexture();方法获取画面Texture,然后将其写入RenderTexture,在转换Texture2D写入本地会发现缩略图颜色泛白,经过排查MediaPlayer原脚本,发现在转换RenderTexture时需要使用avpro的指定shader处理才会显示正确的材质,感兴趣的朋友可以打开MediaPlayer脚本进行查看

改版

MediaPlayer脚本

原脚本查看方法:

注意:添加的MediaPlayer需要将AutoOpen和AutoPlay关掉

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

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

相关文章

fpga系列 HDL:Relu激活函数实现与仿真

代码实现对OUTPUT_NODES个32位浮点数进行RELU操作。32位浮点数的二进制表示遵循 IEEE 754 标准&#xff0c;通常称为单精度浮点数。这个标准定义了浮点数的表示方法&#xff0c;具体分为三个部分&#xff1a; 符号位 (1 bit): 用于表示浮点数的正负。&#xff08; 0 表示正数&a…

全国糖酒会,就这5个字。“会天下美味”

“全国糖酒会&#xff0c;会天下美味”&#xff0c;是全国糖酒会的品牌口号。这个品牌口号来的非常偶然。 两年前&#xff0c;全国糖酒会准备更新标志之时&#xff0c;也设计了一个品牌口号。新标志发布前几天&#xff0c;临时作了调整&#xff0c;最终变成了“全国糖酒会&…

linux下oracle启动及关于pfile和spfile启动参数文件的配置

在现代企业环境中&#xff0c;Oracle数据库作为关键的业务支撑平台&#xff0c;承载着大量的数据处理和事务管理任务。 无论是对于DBA&#xff08;数据库管理员&#xff09;还是开发人员来说&#xff0c;掌握Oracle数据库的基本操作和配置技巧都是至关重要的。本文提供了一份全…

Flutter基本组件Text使用

Text是一个文本显示控件&#xff0c;用于在应用程序界面中显示单行或多行文本内容。 Text简单Demo import package:flutter/material.dart;class MyTextDemo extends StatelessWidget {const MyTextDemo({super.key});overrideWidget build(BuildContext context) {return Sca…

Protobuf库的使用

文章目录 Protobuf是什么Protobuf使⽤流程介绍ProtoBuf的使用创建.proto⽂件指定proto3语法package声明符定义消息&#xff08;message&#xff09;编译contacts.proto⽂件命令如下&#xff1a;序列化与反序列化的使⽤ Protobuf是什么 ProtoBuf&#xff08;全称ProtocolBuffer…

【Python基础】Python函数

本文收录于 《Python编程入门》专栏&#xff0c;从零基础开始&#xff0c;分享一些Python编程基础知识&#xff0c;欢迎关注&#xff0c;谢谢&#xff01; 文章目录 一、前言二、函数的定义与调用三、函数参数3.1 位置参数3.2 默认参数3.3 可变数量参数&#xff08;或不定长参数…

若依框架登录鉴权详解(动态路由)

若依框架登录鉴权&#xff1a;1.获取token&#xff08;过期在响应拦截器中实现&#xff09;,2.基于RBAC模型获取用户、角色和权限信息&#xff08;在路由前置守卫&#xff09;&#xff0c;3.根据用户权限动态生成&#xff08;从字符串->组件&#xff0c;根据permission添加动…

【C++进阶】hash表的封装

文章目录 hash表哈希表的关键组成部分哈希表的优缺点优点&#xff1a;缺点&#xff1a; 常见应用场景 开放定址法实现hash表负载因子 (Load Factor)负载因子的意义负载因子的影响再散列 (Rehashing)示例 整体框架insertFinderasehash桶封装框架insertfinderase~HashTable() 总结…

银行结算业务

1.1 银行本票 银行本票是由银行签发的,承诺自己在见票时无条件支付票款给收款人或持票人的业务。银行本票按票面划分为定额本票和不定额本票,按币种划分为人民币银行本票和外币银行本票。人民币银行本票仅在同一交换区域内使用,资金清算利用当地人民银行组织的资金清算形式…

多个vue项目部署到nginx服务器

文章目录 需求一、项目打包1.vue.config.js2.request.js文件3.打包 二、nginx配置 需求 同一个域名安装多个vue项目。 比如&#xff1a;域名为 https://domain.com 后缀。那么通过不同的后缀就能去访问不同的项目地址。 https://domain.com&#xff0c;不加任何后缀&#x…

【第0006页 · 数组】寻找重复数

【前言】本文以及之后的一些题解都会陆续整理到目录中&#xff0c;若想了解全部题解整理&#xff0c;请看这里&#xff1a; 第0006页 寻找重复数 今天想讨论的一道题在 LeetCode 上评论也是颇为“不错”。有一说一&#xff0c;是道好题&#xff0c;不过我们还是得先理解了它才…

微信小程序中如何监听元素进入目标元素

Page({onLoad: function(){// 如果目标节点&#xff08;用选择器 .target-class 指定&#xff09;进入显示区域以下 100px 时&#xff0c;就会触发回调函数。wx.createIntersectionObserver().relativeToViewport({bottom: 100}).observe(.target-class, (res) > {res.inter…

合宙4G模组Air780EX——产品规格书

Air780EX 是合宙通信推出的LTE Cat.1 bis通信模块&#xff1b; Air780EX采用移芯EC618平台&#xff0c;支持LTE 3GPP Rel.13 技术&#xff1b; Air780EX 是4G全网通模块&#xff0c;可适应不同的运营商和产品&#xff0c;确保产品设计的最大灵活性。 其主要特点和优势可以总…

maven配置文件常用模板

注释很详细&#xff0c;直接上代码 项目结构 内容 父项目 pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi…

高德地图SDK Android版开发 10 InfoWindow

高德地图SDK Android版开发 10 InfoWindow 前言相关类和方法默认样式Marker类AMap类AMap.OnInfoWindowClickListener 接口 自定义样式(视图)AMap 类AMap.ImageInfoWindowAdapter 接口 自定义样式(Image)AMap.ImageInfoWindowAdapter 接口 示例界面布局MapInfoWindow类常量成员变…

【数学建模国赛思路预约】2024全国大学生数学建模竞赛助攻思路、代码、论文

2024年全国大学生数学建模大赛马上就要开始了&#xff0c;大家有没有准备好呢&#xff0c;今年将会和之前一样&#xff0c;将会在比赛赛中时期为大家提供比赛各题的相关解题思路、可运行代码参考以及成品论文。 一、分享计划表如下所示 1、 赛中分享内容包括&#xff08;2023国…

高并发内存池(二):​整体框架的介绍与ThreadCache的实现

目录 整体框架介绍 ThreadCache的主体框架 自由链表-FreeList 内存对齐-RoundUp 计算桶位置-Index 基础版 进阶版 线程局部存储 __declspec(thread) 关键字 实现线程无锁 申请内存-Allocate 释放内存-Deallocate 从中心缓存中申请内存 整体框架介绍 高并发内存池…

机器学习引领未来:赋能精准高效的图像识别技术革新

图像识别技术近年来取得了显著进展,深刻地改变了各行各业。机器学习,特别是深度学习的突破,推动了这一领域的技术革新。本文将深入探讨机器学习如何赋能图像识别技术,从基础理论到前沿进展,再到实际应用与挑战展望,为您全面呈现这一领域的最新动态和未来趋势。 1. 引言 …

kubernetes集群部署Confluence 7.2.0+mysql 5.7(自测有效)

背景介绍&#xff1a; Confluence是一个专业的企业知识管理与协同软件。使用简单&#xff0c;但它强大的编辑和站点管理特征能够帮助团队成员之间共享信息、文档协作、集体讨论&#xff0c;信息推送。 这里介绍的使用的是Confluence 7.2.0版本的。 一、在kubernetes集群部署 1…

本地零阶提示优化

本文探讨了如何优化大型语言模型&#xff08;LLM&#xff09;中的提示&#xff08;prompt&#xff09;&#xff0c;以更有效地利用这些黑盒模型的能力。传统的优化方法倾向于寻找全局最优解&#xff0c;但在某些情况下这种做法可能表现不佳。通过对提示优化进行深入的研究&…