unity 使用自带的videoplayer获取视频缩略图

unity 使用自带的videoplayer获取视频缩略图

主要用到的API:
yield return new WaitUntil(() => thumbVideoPlayer.isPrepared);

yield return new WaitUntil(() => thumbVideoPlayer.frame >= frameSet);

tempRenderTex = thumbVideoPlayer.texture as RenderTexture;

RenderTexture.active = tempRenderTex;

var frameTex = new Texture2D((int)thumbVideoPlayer.width, (int)thumbVideoPlayer.height, TextureFormat.RGB24, false);//创建新的texture2D

frameTex.ReadPixels(new Rect(0, 0, tempRenderTex.width, tempRenderTex.height), 0, 0);

frameTex.Apply();

return Sprite.Create(frameTex, new Rect(0, 0, frameTex.width, frameTex.height), new Vector2(0.5f, 0.5f));//创建sprite
关键代码如下(一下使用vp代替videoplayer)

IEnumerator LoadAssets()
    {
        yield return null;
        for (int t = 0; t < testVideoPath.Count; t++)
        {
            FileItem fileItem = new FileItem();

            thumbVideoPlayer.url = testVideoPath[t];
            yield return new WaitForEndOfFrame();
            thumbVideoPlayer.Prepare();
            yield return new WaitUntil(() => thumbVideoPlayer.isPrepared);//等待准备完毕
            thumbVideoPlayer.Play();
            yield return new WaitUntil(() => thumbVideoPlayer.frame >= frameSet);//等待播放帧数大于设置帧数

            fileItem.sprite = GetThumbSprite();
            fileItem.name = Path.GetFileName(testVideoPath[t]);
            thumbVideoPlayer.Stop();
            yield return new WaitForEndOfFrame();
            fileItems.Add(fileItem);
        }

        yield return new WaitForEndOfFrame();
        Debug.Log("加载完毕");
        OnAllAssetsLoaded?.Invoke();
    }

private Sprite GetThumbSprite()
    {
        tempRenderTex = thumbVideoPlayer.texture as RenderTexture;

        RenderTexture.active = tempRenderTex;
        var frameTex = new Texture2D((int)thumbVideoPlayer.width, (int)thumbVideoPlayer.height, TextureFormat.RGB24, false);
        frameTex.ReadPixels(new Rect(0, 0, tempRenderTex.width, tempRenderTex.height), 0, 0);
        frameTex.Apply();
        return Sprite.Create(frameTex, new Rect(0, 0, frameTex.width, frameTex.height), new Vector2(0.5f, 0.5f));
    }

主要就是使用vp准备(Prepare),等待准备完毕开始播放,等待vp的帧数大于预设的帧数,就可以进行下一步来获取当前帧的sprite(根据自己的需求可以只获取texture2D)。

下面是用于测试的完整代码``
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Video;
using System;
using System.IO;
using UnityEngine.UI;

public class TestLoadVideoFrameTex : MonoBehaviour
{
    public string dicPath = @"F:\第二季 SIKIC#中级教程 (2015版)\视频";//视频文件夹地址,根据自己需求随意
    public List<string> testVideoPath = new List<string>();//测试路径地址(原先想直接输入地址的,后来想直接代码获取文件夹内的视频地址)

    private VideoPlayer thumbVideoPlayer;//临时的视频播放器,也可以直接在unity里设置好
    private GameObject thumbVideoObj;
    private int frameSet = 5;//预设的需要获取的第几帧;
    private RenderTexture tempRenderTex = default;//这个根据自己的需求设置
    public List<FileItem> fileItems = new List<FileItem>();//测试用的list

    private event Action OnAllAssetsLoaded;//测试 用于资源都加载完成时的加载下图片的

    public Transform Content;//测试用放置预览图片的父物体

    // Start is called before the first frame update
    void Start()
    {
        OnAllAssetsLoaded += AllAssetsLoaded;

        if (Directory.Exists(dicPath))
        {
            string[] filePath = Directory.GetFiles(dicPath, "*.mp4");
            for (int i = 0; i < filePath.Length; i++)
            {
                testVideoPath.Add(filePath[i]);
            }
        }

        InitThumbVideo();
        StartCoroutine(LoadAssets());
    }

    /// <summary>
    /// 资源全部加载完成时要处理的内容
    /// </summary>
    private void AllAssetsLoaded()
    {
        for (int i = 0; i < fileItems.Count; i++)
        {
            var img = new GameObject("img").AddComponent<Image>();
            img.transform.SetParent(Content);

            #region  //这部分都是不想动手拖,结果还是写了一大堆,最好还是根据自己的需求做成prefab吧
            var text = new GameObject("text").AddComponent<Text>();
            text.transform.SetParent(img.transform);

            text.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
            text.alignment = TextAnchor.MiddleCenter;
            text.color = Color.white;
            text.fontSize = 16;
            text.horizontalOverflow = HorizontalWrapMode.Overflow;
            text.verticalOverflow = VerticalWrapMode.Overflow;
            text.alignment = TextAnchor.LowerCenter;
            text.text = fileItems[i].name;
            text.rectTransform.pivot = new Vector2(0.5f, 0);
            text.rectTransform.anchorMin = new Vector2(0.5f, 0);
            text.rectTransform.anchorMax = new Vector2(0.5f, 0);
            text.rectTransform.anchoredPosition = new Vector2(0, -20);
            #endregion

            img.sprite = fileItems[i].sprite;

        }
        Debug.Log("赋值完成");
    }


    /// <summary>
    /// 初始化下videoplayer,自己也可以提前在unity里就设置好
    /// </summary>
    private void InitThumbVideo()
    {
        thumbVideoObj = new GameObject("thumbVideo");
        thumbVideoPlayer = thumbVideoObj.AddComponent<VideoPlayer>();
        thumbVideoPlayer.source = VideoSource.Url;
        thumbVideoPlayer.playOnAwake = false;
        thumbVideoPlayer.audioOutputMode = VideoAudioOutputMode.None;

    }

    /// <summary>
    /// 协程加载资源
    /// </summary>
    /// <returns></returns>
    IEnumerator LoadAssets()
    {
        yield return null;
        for (int t = 0; t < testVideoPath.Count; t++)
        {
            FileItem fileItem = new FileItem();

            thumbVideoPlayer.url = testVideoPath[t];
            yield return new WaitForEndOfFrame();
            thumbVideoPlayer.Prepare();
            yield return new WaitUntil(() => thumbVideoPlayer.isPrepared);//等待准备完毕
            thumbVideoPlayer.Play();
            yield return new WaitUntil(() => thumbVideoPlayer.frame >= frameSet);//等待播放帧数大于设置帧数

            fileItem.sprite = GetThumbSprite();
            fileItem.name = Path.GetFileName(testVideoPath[t]);
            thumbVideoPlayer.Stop();
            yield return new WaitForEndOfFrame();
            fileItems.Add(fileItem);
        }

        yield return new WaitForEndOfFrame();
        Debug.Log("加载完毕");
        OnAllAssetsLoaded?.Invoke();

        //用完不需要了,销毁吧
        if (thumbVideoObj!=null )
        {
            Destroy(thumbVideoObj);
        }
    }

    /// <summary>
    /// 获取缩略图
    /// </summary>
    /// <returns></returns>
    private Sprite GetThumbSprite()
    {
        tempRenderTex = thumbVideoPlayer.texture as RenderTexture;

        RenderTexture.active = tempRenderTex;
        var frameTex = new Texture2D((int)thumbVideoPlayer.width, (int)thumbVideoPlayer.height, TextureFormat.RGB24, false);//创建新的texture2D
        frameTex.ReadPixels(new Rect(0, 0, tempRenderTex.width, tempRenderTex.height), 0, 0);
        frameTex.Apply();
        return Sprite.Create(frameTex, new Rect(0, 0, frameTex.width, frameTex.height), new Vector2(0.5f, 0.5f));//创建sprite
    }

}

/// <summary>
/// 临时测试用的
/// </summary>
[Serializable]
public class FileItem
{
    public Sprite sprite;
    public string name;
}

网上找了很久,也没找到合适的,觉得这种方式还可以,就记录一下,
主要是感觉算是比较快的,也不需要给vp的targettexture赋值,也不需要创建RenderTexture,
也不用使用vp的那种使用事件的方式(thumbVideoPlayer.frameReady)。感觉还能优化,希望路过的大神能再给点优化意见。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ThousandsOfSongs

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

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

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

打赏作者

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

抵扣说明:

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

余额充值