Unity实现视频播放功能,制作视频播放器

目前先发布相关脚本代码,后续会对内容进行补充

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

namespace FrameWork
{
    public interface IVideo
    {
        VideoPlayer GetVideoPlayer();

        RawImage GetVideoImage();

        void OnPlayVideo();

        void OnPlayVideo(int index);

        void OnPlayVideo(string url);

        void OnPauseVideo();

        void OnStopVideo();

        void AddVideoUrl(string url);

        void AddVideoUrls(string[] url);

        void RemoveAllUrls();

        void RemoveUrl(int index);
    }

}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace FrameWork
{
    public class VideoManager : FrameworkComponent
    {
        public override void Init()
        {
            sceneVideos = new Dictionary<string, IVideo>();
        }
        private Dictionary<string, IVideo> sceneVideos;
        public void RegistMySelf_Video(string name, IVideo video)
        {
            if (sceneVideos == null)
                return;
            if (!sceneVideos.ContainsKey(name))
            {
                sceneVideos.Add(name, video);
            }
            else
            {
                Debug.Log("已添加video:" + name + " ,请检查是否重名");
            }
        }
        public void UnRegistMySelf_Video(string name)
        {
            if (sceneVideos == null)
                return;
            if (sceneVideos.ContainsKey(name))
            {
                sceneVideos.Remove(name);
            }
            else
            {
                Debug.Log("未找到video:" + name);
            }
        }
        public IVideo GetVideoComponent(string name)
        {
            if (sceneVideos.ContainsKey(name))
            {
                return sceneVideos[name];
            }
            Debug.Log("未找到IVideo:" + name);
            return null;
        }
    }
}

接下来是核心代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Video;
using UnityEngine.UI;
namespace FrameWork
{
    [RequireComponent(typeof(RawImage))]
    public class VideoComponent : MonoBehaviour, IVideo
    {
        #region 内部变量
        private VideoPlayer vPlayer//
            ;
        private AudioSource source;//

        private RawImage videoImage;//

        private bool playOnPrepareCompleted = false;

        private string videoUrlDefault;

        private bool isInDrag = false;
        #endregion

        #region SerializeField
        [SerializeField]
        private List<string> videoUrlPool;

        public bool playOnAwake = false;

        public bool prepareOnAwake = true;


        public bool isLooping = false;

        public bool waitForFirstFrame = false;

        public bool isStreamingAssetsPath = false;

        public Graphic loadingUI;

        public Graphic coverUI;

        public Button playBtn;

        public Button stopBtn;

        public Button pauseBtn;

        public Slider sliderVideo;

        public Text text_Time;

        public Slider sliderSource;

        public Text textSource;

        public Toggle voiceButton;
        #endregion

        public bool registeMyselfOnAwake = true;

        void Awake()
        {
            //if (registeMyselfOnAwake)
            //{
            //    FrameEntrance.Instance.Video.RegistMySelf_Video(gameObject.name, this);
            //}
            Init();
        }
        void OnDestroy()
        {
            FrameEntrance.Instance.Video.UnRegistMySelf_Video(gameObject.name);
        }
        void Init()
        {
            pauseBtn.onClick.AddListener(() => { OnPauseVideo(); });
            playBtn.onClick.AddListener(() => { OnPlayVideo(); });
            stopBtn.onClick.AddListener(() => { OnStopVideo(); });

            videoImage = GetComponent<RawImage>();//
            //一定要动态添加这两个组件,要不然会没声音
            vPlayer = gameObject.AddComponent<VideoPlayer>();//
            source = gameObject.AddComponent<AudioSource>();//

            vPlayer.isLooping = isLooping;
            vPlayer.waitForFirstFrame = waitForFirstFrame;

            //这3个参数不设置也会没声音 唤醒时就播放关闭
            vPlayer.playOnAwake = false;
            source.playOnAwake = false;
            source.Pause();


            //设置为URL模式
            vPlayer.source = VideoSource.Url;
            //设置渲染模式为APIOnly模式
            vPlayer.renderMode = VideoRenderMode.APIOnly;

            //在视频中嵌入的音频类型
            vPlayer.audioOutputMode = VideoAudioOutputMode.AudioSource;

            //把声音组件赋值给VideoPlayer
            vPlayer.SetTargetAudioSource(0, source);

            if (playOnAwake)
            {
                if (playBtn)
                {
                    playBtn.gameObject.SetActive(false);
                }
            }

            AddPlayFinishedEvent((videoplayer) =>
            {
                if (!vPlayer.isLooping)
                {
                    OnStop();
                }
            });

            AddPrepareCompletedEvent((videoplayer) => { OnPrepareCompleted(playOnPrepareCompleted); });

            #region 添加按钮事件
            if (sliderSource != null)
            {
                sliderSource.value = source.volume;
                sliderSource.onValueChanged.AddListener(delegate { ChangeSource(sliderSource.value); });
            }
            if (sliderVideo != null)
            {
                sliderVideo.value = 0;
                //EventTriggerListener.Get(sliderVideo.gameObject).onDown += (thisObj) => { isInDrag = true; };
                //EventTriggerListener.Get(sliderVideo.gameObject).onUp += (thisObj) => { isInDrag = false; ChangeVideo(sliderVideo.value); };
            }
            #endregion
        }
        void Start()
        {
            //如果playOnAwake,则Prepare完毕后自动播放
            playOnPrepareCompleted = playOnAwake;

            if (playOnAwake || prepareOnAwake)
            {
                //开始预加载视频
                PrepareVideo(VideoUrlDefault);
            }
        }

        void LateUpdate()
        {
            if (vPlayer.isPlaying && text_Time != null && sliderVideo)
            {

                float time = (float)vPlayer.time;

                if (!isInDrag)
                {
                    sliderVideo.value = time;
                }

                int hour = (int)time / 60;

                int mint = (int)time % 60;

                int hout_Count = (int)sliderVideo.maxValue / 60;

                int mint_Count = (int)sliderVideo.maxValue % 60;

                text_Time.text = string.Format("{0}:{1}/{2}:{3}", hour.ToString("0"), mint.ToString("00"), hout_Count.ToString("0"), mint_Count.ToString("00"));

            }

        }

        #region 内置方法
        /// <summary>
        ///     改变音量大小
        /// </summary>
        /// <param name="value"></param>
        private void ChangeSource(float value)
        {
            source.volume = value;
            if (textSource != null)
            {
                textSource.text = string.Format("{0:0}%", value * 100);
            }
        }

        /// <summary>
        ///     改变视频进度
        /// </summary>
        /// <param name="value"></param>
        private void ChangeVideo(float value)
        {
            vPlayer.time = value;
        }
        private string GetStreamingAssetsPath(string path)
        {
            if (path.Contains("StreamingAssets/"))
            {
                return path;
            }
            return Application.streamingAssetsPath + "/" + path;
        }
        private void PrepareVideo(string url)
        {
            //设置URL并进行预加载
            this.vPlayer.url = url;

            if (this.vPlayer.url == null)
            {
                Debug.Log("未添加URL");
                return;
            }

            vPlayer.Prepare();

            OnPrepare();
        }
        private void OnPrepare()
        {
            Debug.Log("OnPrepare");
            //先将视频RawImage的透明度设为0,开始播放后再调回1
            videoImage.color = new Color(1, 1, 1, 0);
            //打开loading的UI
            if (!vPlayer.isPrepared && loadingUI)
            {
                loadingUI.gameObject.SetActive(true);
            }
            //如果Prepare完毕直接播放的话,就关闭封面UI和播放按钮
            if (playOnPrepareCompleted)
            {
                if (coverUI)
                {
                    coverUI.gameObject.SetActive(false);
                }
                if (playBtn)
                {
                    playBtn.gameObject.SetActive(false);
                }
            }
        }
        IEnumerator DelayTodo(float time)
        {
            yield return new WaitForSeconds(time);
            videoImage.color = new Color(1, 1, 1, 1);
        }
        private void OnPlay()
        {
            Debug.Log("OnPlay");
            //把图像赋给RawImage
            videoImage.texture = vPlayer.texture;
            if (sliderVideo != null)
            {
                //帧数/帧速率=总时长    如果是本地直接赋值的视频,我们可以通过VideoClip.length获取总时长
                sliderVideo.maxValue = vPlayer.frameCount / vPlayer.frameRate;
            }
            StartCoroutine(DelayTodo(0.15f));


            if (coverUI)
            {
                coverUI.gameObject.SetActive(false);
            }

            if (playBtn)
            {
                playBtn.gameObject.SetActive(false);
            }

            if (stopBtn)
            {
                stopBtn.gameObject.SetActive(true);
            }

            if (pauseBtn)
            {
                pauseBtn.gameObject.SetActive(true);
            }

            if (sliderVideo)
            {
                sliderVideo.gameObject.SetActive(true);
            }
            if (voiceButton)
            {
                voiceButton.gameObject.SetActive(true);
            }
        }
        private void OnPrepareCompleted(bool isPlayOnPrepareCompleted)
        {
            Debug.Log("OnPrepareCompleted");
            //关闭LoadingUI
            if (loadingUI)
            {
                loadingUI.gameObject.SetActive(false);
            }
            //如果isPlayOnPrepareCompleted为true的话 播放视频
            if (isPlayOnPrepareCompleted)
            {
                OnPlayVideo();
            }
        }
        private void OnPause()
        {
            Debug.Log("OnPause");

            if (playBtn)
            {
                playBtn.gameObject.SetActive(true);
            }

            if (pauseBtn)
            {
                pauseBtn.gameObject.SetActive(false);
            }

        }
        private void OnStop()
        {
            Debug.Log("OnStop");
            if (stopBtn)
            {
                stopBtn.gameObject.SetActive(false);
            }
            if (playBtn)
            {
                playBtn.gameObject.SetActive(true);
            }
            if (pauseBtn)
            {
                pauseBtn.gameObject.SetActive(false);
            }
            if (sliderVideo)
            {
                sliderVideo.gameObject.SetActive(false);
            }
            if (voiceButton)
            {
                voiceButton.gameObject.SetActive(false);
            }
            if (coverUI)
            {
                coverUI.gameObject.SetActive(true);
            }
        }
        #endregion

        #region 对外接口
        public string VideoUrlDefault//默认Clip,调用OnPlayAudio,不传入参数时,Play这个clip,非只读
        {
            get
            {
                if (videoUrlDefault != null && videoUrlDefault != "")
                {
                    if (!isStreamingAssetsPath)
                    {

                        return videoUrlDefault;

                    }
                    else
                    {

                        return GetStreamingAssetsPath(videoUrlDefault);

                    }
                }
                if (videoUrlPool != null && videoUrlPool.Count > 0)
                {
                    if (!isStreamingAssetsPath)
                    {

                        return videoUrlPool[0];

                    }
                    else
                    {

                        return GetStreamingAssetsPath(videoUrlPool[0]);

                    }
                }
                return null;
            }
            set
            {
                videoUrlDefault = value;

                if (videoUrlPool == null)
                {
                    videoUrlPool = new List<string>();
                }

                if (!videoUrlPool.Contains(value))
                {
                    videoUrlPool.Add(value);
                }
            }
        }
        //索引器必须以this关键字定义,其实这个this就是类实例化之后的对象
        public string this[int index]
        {
            //实现索引器的get方法
            get
            {
                if (videoUrlPool != null && videoUrlPool.Count > 0)
                {
                    return videoUrlPool[index];
                }
                return null;
            }
        }
        public VideoPlayer GetVideoPlayer()
        {
            return vPlayer;
        }
        public RawImage GetVideoImage()
        {
            return videoImage;
        }
        #region Play按钮事件,对外接口
        public void OnPlayVideo()
        {
            if (vPlayer.url == VideoUrlDefault && vPlayer.isPrepared)
            {
                //如果加载完毕则直接播放
                vPlayer.Play();
                OnPlay();
            }
            else //如果没有预加载完毕则开始预加载
            {
                //因为是点击按钮事件,所以这里直接把playOnPrepareCompleted设为true,Prepare完毕后直接播放
                playOnPrepareCompleted = true;
                PrepareVideo(VideoUrlDefault);
            }
        }
        public void OnPlayVideo(int index)
        {
            if (videoUrlPool != null && videoUrlPool.Count >= index + 1)
            {
                VideoUrlDefault = videoUrlPool[index];
            }
            else
            {
                Debug.Log("该索引不存在");
                return;
            }
            OnPlayVideo();
        }
        public void OnPlayVideo(string url)
        {
            VideoUrlDefault = url;
            OnPlayVideo();
        }

        #endregion
        #region 暂停、停止按钮事件,对外接口
        public void OnPauseVideo()
        {
            vPlayer.Pause();
            OnPause();
        }
        public void OnStopVideo()
        {
            vPlayer.Stop();
            OnStop();
        }
        #endregion
        #region 添加URL到池中

        public void AddVideoUrl(string url)
        {
            if (videoUrlPool == null)
            {
                videoUrlPool = new List<string>();
            }
            if (!videoUrlPool.Contains(url))
            {
                videoUrlPool.Add(url);
            }
        }

        public void AddVideoUrls(string[] url)
        {
            for (int i = 0; i < url.Length; i++)
            {
                AddVideoUrl(url[i]);
            }
        }

        #endregion
        #region  从池中移除URL
        public void RemoveUrl(int index)
        {
            if (videoUrlPool != null && videoUrlPool.Count > index)
            {
                videoUrlPool.RemoveAt(index);
            }
        }
        public void RemoveAllUrls()
        {
            if (videoUrlPool != null)
            {
                videoUrlPool.Clear();
            }
        }
        #endregion
        #region 添加相关事件
        public void AddPrepareCompletedEvent(VideoPlayer.EventHandler prepareCompleteEvent)
        {
            vPlayer.prepareCompleted += prepareCompleteEvent;
        }
        public void AddPlayFinishedEvent(VideoPlayer.EventHandler finishEvent)
        {
            vPlayer.loopPointReached += finishEvent;
        }
        #endregion
        #endregion
    }
}

这个是FrameWork框架中的,如果后面有时间我会尝试着将核心的与视频播放有关的代码拆分出来。

上面三个脚本中前两个只需要放在Assets里就可以了,第二个需要作为组件挂载到游戏物体上。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值