Unity从VideoPlayer获取当前帧纹理

Unity从VideoPlayer获取当前帧纹理

Video Player

Video Player在Unity5.6版本正式加入用以取代之前的MovieTexture。在视频导入编辑和播放等功能上比之前的MovieTexture已经好上很多。
相关介绍链接:https://blog.csdn.net/f_957995490/article/details/108112467

每一帧的纹理

具体操作,如下:

  1. 通过将VideoPlayer.sendFrameReadyEvents设置为true来启用新的帧事件。
  2. 订阅VideoPlayer.frameReady活动。
  3. 当新帧可用时,将调用您分配给VideoPlayer.frameReady事件的功能.只需从VideoPlayer访问视频帧,它将通过将VideoPlayer.texture转换为Texture2D传递给参数。

在代码中:
VideoPlayer.Play()之前添加以下内容:

//Enable new frame Event
videoPlayer.sendFrameReadyEvents = true;
//Subscribe to the new frame Event
videoPlayer.frameReady += OnNewFrame;

这是您的OnNewFrame函数签名:

void OnNewFrame(VideoPlayer source, long frameIdx)
{
    Texture2D videoFrame = (Texture2D)source.texture;
    //Do anything with the videoFrame Texture.
}

值得注意的是,启用该事件的成本很高.在执行此操作之前,请确保您需要每个框架。
编辑:
Texture2D videoFrame =(Texture2D)source.texture;Texture2D videoFrame = source.texture;作为Texture2D;失败.
我把Debug.Log(source.texture);OnNewFrame函数内部得到:

TempBuffer 294 320×240 (UnityEngine.RenderTexture)

因此,看起来Video.texture属性返回RenderTexture类型而不是像它应该的纹理类型。
我们必须将RenderTexture转换为Texture2D

void Start()
{
    videoFrame = new Texture2D(2, 2);
}
Texture2D videoFrame;
void OnNewFrame(VideoPlayer source, long frameIdx)
{
    RenderTexture renderTexture = source.texture as RenderTexture;
    if (videoFrame.width != renderTexture.width || videoFrame.height != renderTexture.height)
    {
        videoFrame.Resize(renderTexture.width, renderTexture.height);
    }
    RenderTexture.active = renderTexture;
    videoFrame.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
    videoFrame.Apply();
    RenderTexture.active = null;
}

项目完整代码

using System.IO;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Video;

public class VideoTest : MonoBehaviour
{
    private VideoPlayer m_videoPlayer = null;
    public RawImage m_rawImage;

    void Awake()
    {
        videoFrame = new Texture2D(2, 2);
    }
    private void OnEnable()
    {
        if (null == m_videoPlayer)
        {
            m_videoPlayer = m_rawImage.gameObject.GetComponent<VideoPlayer>();
        }
        m_videoPlayer.sendFrameReadyEvents = true;
        m_videoPlayer.frameReady += OnNewFrame;
        m_videoPlayer.Play();
    }
    Texture2D videoFrame;
    private void OnNewFrame(VideoPlayer source, long frameIdx)
    {
        RenderTexture renderTexture = source.texture as RenderTexture;
        if (null == renderTexture)
        {
            Debug.LogError("空的?" + source.name);
        }
        if (videoFrame.width != renderTexture.width || videoFrame.height != renderTexture.height)
        {
            videoFrame.Resize(renderTexture.width, renderTexture.height);
        }
        RenderTexture.active = renderTexture;
        videoFrame.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
        videoFrame.Apply();
        RenderTexture.active = null;
        SaveToFile("test.png", videoFrame.EncodeToPNG());
    }
    private void OnDisable()
    {
        m_videoPlayer.frameReady -= OnNewFrame;
        m_videoPlayer.sendFrameReadyEvents = false;
        if (null != m_videoPlayer)
            m_videoPlayer.Stop();
    }

    /// <summary>
    /// 保存文件
    /// </summary>
    /// <param name="file">文件名</param>
    /// <param name="data">字节数组</param>
    private void SaveToFile(string file, byte[] data)
    {
        string path = Application.persistentDataPath + file;
        string outFileDirectory = path.Remove(path.LastIndexOf('/'));
        if (!File.Exists(outFileDirectory))
        {//防止路径不存在,则创建拷贝目标所需路径
            Directory.CreateDirectory(outFileDirectory);
        }
        File.WriteAllBytes(path, data);
    }
}
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Unity中的VideoPlayer组件可以在游戏中播放视频文件。要实现为视频添加链接,可以使用Texture的动态更新功能以及MeshCollider组件。 首先,需要向VideoPlayer组件添加一个渲染目标来显示视频。可以创建一个RawImage对象,并将其作为VideoPlayer的TargetGraphic。然后,将VideoPlayer的targetTexture设置为该RawImage的主要纹理(mainTexture)。 接下来,创建一个2D纹理(Texture2D),用于作为视频中某个位置的链接。可以使用红色或绿色像素来代表链接的位置。 然后,需要使用Texture2D的动态更新功能。可以通过编写一个脚本,在Update函数中获取VideoPlayer当前,并在Texture2D上进行更新。使用GetVideoTexture方法获取当前视频的Texture,然后使用Texture2D的SetPixels函数将该的像素数据分配到Texture2D的相应位置上。最后,调用Texture2D的Apply函数,以确保更新被应用到主纹理上。 最后,为包含链接的位置添加一个MeshCollider组件。可以创建一个Plane对象,将其缩小至适当的大小,并将其作为链接位置的父对象。然后,将Texture2D作为纹理应用到Plane的材质上,并为Plane添加MeshCollider。这样,当玩家将鼠标悬停在链接位置上时,可以检测到该位置,并触发相应的事件。 以上是将链接添加到Unity VideoPlayer的基本方法。可以根据需要对脚本进行扩展和自定义,以实现更复杂的链接功能,如跳转到其他场景或打开外部链接等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天富儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值