Unity笔记之获取视频某一帧的图片

需求:获取到视频某一帧的图片(需要保存直接写file存下来即可)
原因:用户不可能上传视频的同时还会给你单独上传视频对应的一张图片,所以只能是我们自己从视频里面去随机抽取一张作为这个视频的缩略图来展示。

#region 获取视频某一帧图片
    VideoPlayer video;
    Texture2D videoTextrue;
    RenderTexture renderTexture;
    Sprite sprite;
    void InitVideoToImage()//Start
    {
        videoTextrue = new Texture2D(2, 2);
        video = GetComponent<VideoPlayer>();
        video.url = path;
        video.playOnAwake = false;
        video.waitForFirstFrame = true;

        video.sendFrameReadyEvents = true;
        video.frameReady += GetNumTextrue;
        video.Play();


    }
    int framesValue = 0;//获得视频第几帧的图片
    /// <summary>
    /// 获取到framesValue帧的Textrue
    /// </summary>
    void GetNumTextrue(VideoPlayer source, long frameIdx)
    {
        framesValue++;
        if (framesValue == 1)
        {
            renderTexture = source.texture as RenderTexture;
            if (videoTextrue.width != renderTexture.width || videoTextrue.height != renderTexture.height)
            {
                videoTextrue.Resize(renderTexture.width, renderTexture.height);
            }
            RenderTexture.active = renderTexture;
            videoTextrue.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
            videoTextrue.Apply();
            RenderTexture.active = null;
            video.frameReady -= GetNumTextrue;
            video.sendFrameReadyEvents = false;
        }
        StartCoroutine(ScaleTexture(videoTextrue, 1920, 1080));
    }
    /// <summary>
    /// 生成缩略图
    /// </summary>
    IEnumerator ScaleTexture(Texture2D source, int targetWidth, int targetHeight)
    {
        yield return new WaitForSeconds(2);

        Texture2D result = new Texture2D(targetWidth, targetHeight, TextureFormat.ARGB32, false);

        for (int i = 0; i < result.height; ++i)
        {
            for (int j = 0; j < result.width; ++j)
            {
                Color newColor = source.GetPixelBilinear((float)j / (float)result.width, (float)i / (float)result.height);
                result.SetPixel(j, i, newColor);
            }
        }
        result.Apply();

        sprite = Sprite.Create(result, new Rect(0, 0, targetWidth, targetHeight), new Vector2(0.5f, 0.5f));
        image.sprite = sprite;
    }
    #endregion

以上就是代码内容,弄进去直接用或者魔改

我是借鉴了这个大哥的魔改的

对了,这个有个缺点,就是视频必须播放着,不然没办法搞到。
(今天导出webgl测试了一下,发现问题很大,这个应该不支持webgl,webgl打开会获取不到视频的纹理)

如果只是播放mp4的话,绝大部分都是支持的,所以用自带的videoplayer就足够了,这样就没必要再去使用插件了。
下面是代码的内容:

using System.Collections;
using System.Collections.Generic;
using UMP;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Video;

public class NewBehaviourScript : MonoBehaviour
{
    public Image image;
    string path;
    public VideoPlayer video;
    // Start is called before the first frame update
    void Start()
    {
        path = Application.streamingAssetsPath + "/中国机长.mp4";
        video.url = path;
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Q))
        {
            video.Play();
            StartCoroutine(Video());
        }
        if (Input.GetKeyDown(KeyCode.W))
        {
            video.Pause();
        }
        if (Input.GetKeyDown(KeyCode.E))
        {
            video.Stop();
        }
    }
    IEnumerator Video()
    {
        yield return new WaitForSeconds(1);
        Texture2D t = TextureToTexture2D(video.GetComponent<RawImage>().texture);
        image.sprite = GetSpriteByTexture(t);
    }
    /// <summary>
    /// 运行模式下Texture转换成Texture2D
    /// </summary>
    /// <param name="texture"></param>
    /// <returns></returns>
    private Texture2D TextureToTexture2D(Texture texture)
    {
        Texture2D texture2D = new Texture2D(texture.width, texture.height, TextureFormat.RGBA32, false);
        RenderTexture currentRT = RenderTexture.active;
        RenderTexture renderTexture = RenderTexture.GetTemporary(texture.width, texture.height, 32);
        Graphics.Blit(texture, renderTexture);

        RenderTexture.active = renderTexture;
        texture2D.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
        texture2D.Apply();

        RenderTexture.active = currentRT;
        RenderTexture.ReleaseTemporary(renderTexture);
        return texture2D;
    }
    /// <summary>
    /// 把Texture2D转为Sprite
    /// </summary>
    /// <param name="tex"></param>
    /// <returns></returns>
    Sprite GetSpriteByTexture(Texture2D tex)
    {
        Sprite _sprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f));
        return _sprite;
    }
}

有不对或者更好的方法欢迎指教!

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值