UnityEngine.Video.VideoPlayer

作者:追风剑情 发布于:2019-5-7 21:59 分类:Unity3d

官方文档
https://docs.unity3d.com/ScriptReference/Video.VideoPlayer.html
https://docs.unity3d.com/Manual/class-VideoClip.html

示例:在Plane上播放电影

导入一个电影文件,新建一个材质,新建一个RenderTexture。如图

99999.png

设置MovieRenderTexture的大小与视频分辨率相同,否则显示不清晰。

1111.png(查看视频分辨率多少)

1111.png

Deinterlace: 去隔行扫描。off: 逐行扫描。Even:只扫描偶数行。Odd:只扫描奇数行.

2222.png(Size与视频分辨率对应)

场景元素,如图

8888.png

7777.png

运行效果

111.png

问题:VideoPlayer组件在某些Windows版本下播放会崩溃
解决方案:设置视频编码方式为VP8

1111.png

注意:Android 10系统在手机上设置videoPlayer.url时,不要加file://前缀。否则会报AndroidVideoMedia: Error opening extractor: -10002错误。其他Android系统版本需要加file://

111111.png

UI上播放视频类

工程截图

11111.png


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Video;
using UnityEngine.UI;
/// <summary>
/// UI视频播放器
/// </summary>

public class UIVideoPlayer : MonoBehaviour
{
    [SerializeField]
    private VideoPlayer m_VideoPlayer;
    [SerializeField]
    private RawImage m_RawImage;
    [SerializeField]
    private bool m_FitInParent = true;
    [SerializeField]
    private VideoAspectRatio m_VideoAspectRatio = VideoAspectRatio.FitInside;
    //播放进度条
    [SerializeField]
    private Slider m_Slider;
    private bool _pressSlider;
    private float _delayFrame;
    //End

    //播放图标
    [SerializeField]
    private GameObject m_PlayIcon;

    private AspectRatioFitter m_AspectRatioFitter;
    private bool IsRegPrepareCompleted = false;
    private RenderTexture m_TargetTexture = null;

    private void Awake()
    {
        //true:允许从视频的某个时间点开始播放
        m_VideoPlayer.skipOnDrop = true;
        if (m_FitInParent)
        {
            m_AspectRatioFitter = this.GetComponent<AspectRatioFitter>();
            if (m_AspectRatioFitter == null)
                m_AspectRatioFitter = gameObject.AddComponent<AspectRatioFitter>();
            m_AspectRatioFitter.aspectMode = AspectRatioFitter.AspectMode.FitInParent;
        }
    }

    public void Play(string url)
    {
        if (!IsRegPrepareCompleted)
        {
            IsRegPrepareCompleted = true;
            m_VideoPlayer.prepareCompleted += OnPrepareCompleted;
            m_VideoPlayer.errorReceived += OnErrorReceived;
            m_VideoPlayer.loopPointReached += OnLoopPointReached;
            m_VideoPlayer.seekCompleted += OnSeekCompleted;
            m_VideoPlayer.frameReady += OnFrameReady;
            m_VideoPlayer.clockResyncOccurred += OnClockResyncOccurred;
            m_VideoPlayer.frameDropped += OnFrameDropped;
        }

        if (m_VideoPlayer.isPlaying)
            m_VideoPlayer.Stop();

        //注意:Android 10系统不要加"file://"协议前缀否则无法播放。
        m_VideoPlayer.url = FormatProtocolURL(url);
        //当组件未激活时,需要将playOnAwake设置为true,随后调用Prepare()方法才不会报错 Cannot Prepare a disabled VideoPlayer
        m_VideoPlayer.playOnAwake = !gameObject.activeInHierarchy;
        //当组件对象未激活时,调用Prepare()会报错 Cannot Prepare a disabled VideoPlayer
        m_VideoPlayer.Prepare();
        Debug.LogFormat("Play url: {0}", m_VideoPlayer.url);
        m_VideoPlayer.time = 0;
        if (m_VideoPlayer.isPrepared)
            m_VideoPlayer.Play();
        else
            m_VideoPlayer.Prepare();

        GameEventManager.FireEvent(GameEventType.UI_WAIT_LOADING_SHOW, Config.LAN_VIDEO_LOADING);
    }

    public string FormatProtocolURL(string url)
    {
        //网络地址
        if (url.StartsWith("http://"))
            return url;

        //本地地址
        if (!url.StartsWith("file://") && !url.StartsWith("jar:file:///"))
            url = "file://" + url;
        /*
        if (Application.platform != RuntimePlatform.Android)
            return url;
        //Android OS 10 / API-29 (QKQ1.190825.002/V11.0.9.0.QFACNXM)
        string os = SystemInfo.operatingSystem;
        os = os.Substring(11, 2);
        int version = 0;
        if (int.TryParse(os, out version))
        {
            //Android 10系统不加file://
            if (10 == version)
            {
                url = url.Replace("file://", "");
            }
        }
        */
        return url;
    }

    public void Stop()
    {
        m_VideoPlayer.Stop();
        //清空RenderTexture上的画面
        m_VideoPlayer.targetTexture.Release();
    }

    public void Resume()
    {
        m_VideoPlayer.Play();
    }

    public void Pause()
    {
        m_VideoPlayer.Pause();
    }

    private void OnPrepareCompleted(VideoPlayer source)
    {
        Debug.Log("OnPrepareCompleted");
        GameEventManager.FireEvent(GameEventType.UI_WAIT_LOADING_HIDE);

        Vector2 size = UGUITool.GetSize(m_RawImage.rectTransform);
        int width = (int)size.x;
        int height = (int)size.y;
        Debug.LogFormat("Rect: {0}x{1}", width, height);
        if (m_TargetTexture == null)
        {
            m_TargetTexture = RenderTexture.GetTemporary(width, height, 0, RenderTextureFormat.ARGB32);
            m_RawImage.texture = m_TargetTexture;
            m_VideoPlayer.targetTexture = m_TargetTexture;
        }

        source.aspectRatio = m_VideoAspectRatio;
        if (!m_VideoPlayer.isPlaying)
            m_VideoPlayer.Play();

        if (m_FitInParent)
            m_AspectRatioFitter.aspectRatio = (float)source.width / (float)source.height;
    }

    private void OnErrorReceived(VideoPlayer source, string message)
    {
        GameEventManager.FireEvent(GameEventType.UI_WAIT_LOADING_HIDE);
        DialogBox.Instance.Show(message + "/n" + source.url);
    }

    private void OnLoopPointReached(VideoPlayer source)
    {
        Debug.Log("OnLoopPointReached");
    }

    private void OnSeekCompleted(VideoPlayer source)
    {
        Debug.Log("OnSeekCompleted");
        _pressSlider = false;
    }

    private void OnFrameReady(VideoPlayer source, long frameIdx)
    {
        Debug.Log("OnFrameReady");
    }

    private void OnClockResyncOccurred(VideoPlayer source, double seconds)
    {
        Debug.Log("OnClockResyncOccurred");
    }

    private void OnFrameDropped(VideoPlayer source)
    {
        Debug.Log("OnFrameDropped");
    }

    public void Show()
    {
        gameObject.SetActive(true);
    }

    public void Hide()
    {
        if (m_VideoPlayer.isPlaying)
            m_VideoPlayer.Stop();
        gameObject.SetActive(false);
    }

    private void OnDestroy()
    {
        m_VideoPlayer.prepareCompleted -= OnPrepareCompleted;
        m_VideoPlayer.errorReceived -= OnErrorReceived;
        m_VideoPlayer.loopPointReached -= OnLoopPointReached;
        m_VideoPlayer.seekCompleted -= OnSeekCompleted;
        m_VideoPlayer.frameReady -= OnFrameReady;
        m_VideoPlayer.clockResyncOccurred -= OnClockResyncOccurred;
        m_VideoPlayer.frameDropped -= OnFrameDropped;
    }

    private void LateUpdate()
    {
        UpdateSliderProgress();
        if (m_PlayIcon != null)
            m_PlayIcon.SetActive(m_VideoPlayer.isPaused);
    }

    #region 播放进度条
    public void OnSliderPointerDownHandler()
    {
        _pressSlider = true;
    }

    //当在进度条上释放鼠标时,重新设置播放的开始时间点
    public void OnSliderPointerUpHandler()
    {
        if (m_VideoPlayer.isPrepared)
        {
            double time = (double)m_Slider.value * m_VideoPlayer.length;
            m_VideoPlayer.time = time;
            _delayFrame = 0;
        }
    }

    // 更新播放进度条(Slider)
    private void UpdateSliderProgress()
    {
        if (m_Slider == null)
            return;
        if (!m_VideoPlayer.isPrepared || !m_VideoPlayer.isPlaying)
            return;
        if (_pressSlider)
            return;
        if (_delayFrame < 10)
        {
            _delayFrame++;
            return;
        }
        double progress = m_VideoPlayer.time / m_VideoPlayer.length;
        m_Slider.value = (float)progress;
    }
    #endregion

    public void OnClickVideo()
    {
        if (m_VideoPlayer.isPlaying)
            m_VideoPlayer.Pause();
        else if (m_VideoPlayer.isPaused)
            m_VideoPlayer.Play();
    }
}


效果
播放中
22222.png

暂停
333333.png

标签: Unity3d

Powered by emlog  蜀ICP备18021003号-1   sitemap

川公网安备 51019002001593号