2017-03-12 13 views
1

から現在のフレームのテクスチャを取得これは、この記事でのVideoPlayer

、にTexture2Dとして現在のフレームを取得するための適切な方法は何してくださいですか?1「は、必要に応じてフレームごとにテクスチャを取得する」ことができUsing new Unity VideoPlayer and VideoClip API to play videoを記載されていますか

EDIT:

が答えた後、私はこれをしなかったが、働いていない:

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

public class AverageColorFromTexture : MonoBehaviour { 

    public VideoClip videoToPlay; 
    public Light lSource; 

    private Color targetColor; 
    private VideoPlayer videoPlayer; 
    private VideoSource videoSource; 
    private Renderer rend; 
    private Texture tex; 
    private AudioSource audioSource; 

    void Start() 
    { 
     Application.runInBackground = true; 
     StartCoroutine(playVideo()); 
    } 

    IEnumerator playVideo() 
    { 

     rend = GetComponent<Renderer>(); 

     videoPlayer = gameObject.AddComponent<VideoPlayer>(); 
     audioSource = gameObject.AddComponent<AudioSource>(); 

     //Disable Play on Awake for both Video and Audio 
     videoPlayer.playOnAwake = false; 
     audioSource.playOnAwake = false; 

     videoPlayer.source = VideoSource.VideoClip; 
     videoPlayer.audioOutputMode = VideoAudioOutputMode.AudioSource; 
     videoPlayer.EnableAudioTrack(0, true); 
     videoPlayer.SetTargetAudioSource(0, audioSource); 

     //Set video To Play then prepare Audio to prevent Buffering 
     videoPlayer.clip = videoToPlay; 
     videoPlayer.Prepare(); 

     //Wait until video is prepared 
     while (!videoPlayer.isPrepared) 
     { 
      Debug.Log("Preparing Video"); 
      yield return null; 
     } 
     Debug.Log("Done Preparing Video"); 

     //Assign the Texture from Video to Material texture 
     tex = videoPlayer.texture; 
     rend.material.mainTexture = tex; 

     //Enable new frame Event 
     videoPlayer.sendFrameReadyEvents = true; 

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

     //Play Video 
     videoPlayer.Play(); 

     //Play Sound 
     audioSource.Play(); 

     Debug.Log("Playing Video"); 
     while (videoPlayer.isPlaying) 
     { 
      Debug.LogWarning("Video Time: " + Mathf.FloorToInt((float)videoPlayer.time)); 
      yield return null; 
     } 
     Debug.Log("Done Playing Video"); 
    } 

    void OnNewFrame(VideoPlayer source, long frameIdx) 
    { 
     Texture2D videoFrame = (Texture2D)source.texture; 

     targetColor = CalculateAverageColorFromTexture(videoFrame); 
     lSource.color = targetColor ; 
    } 


    Color32 CalculateAverageColorFromTexture(Texture2D tex) 
    { 
     Color32[] texColors = tex.GetPixels32(); 
     int total = texColors.Length; 
     float r = 0; 
     float g = 0; 
     float b = 0; 

     for(int i = 0; i < total; i++) 
     { 
      r += texColors[i].r; 
      g += texColors[i].g; 
      b += texColors[i].b; 
     } 
     return new Color32((byte)(r/total) , (byte)(g/total) , (byte)(b/total) , 0); 
    } 
} 

答えて

1

あなたは三の段階で適切にそれを行うことができます。

.ENABLE新しいフレームVideoPlayer.sendFrameReadyEventstrueに設定してください。新しいフレームが利用可能になったとき

.Subscribe VideoPlayerframeReadyイベント

にあなたがVideoPlayerframeReadyイベントに割り当てられ【選択関数が呼び出されます。 VideoPlayerからビデオフレームにアクセスするには、VideoPlayer.textureTexture2Dにキャストしてパラメータに渡します。

これだけです。コードで


video.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. 
} 

このイベントを有効にするにはコストがかかることに注意してください。これを行う前に、各フレームが必要であることを確認してください。

EDIT:両方Texture2D videoFrame = (Texture2D)source.texture;

ととTexture2D videoFrame = source.texture as Texture2D;に失敗しました。

は私がOnNewFrame関数内Debug.Log(source.texture);を入れて得た:

TempBuffer 294 320×240(UnityEngine.RenderTexture)

だから、それは次のようにRenderTextureタイプではないTextureタイプを返してVideo.textureプロパティのように見えますそうすべき。

RenderTextureTexture2Dに変換する必要があります。あなたの質問から

void Start() 
{ 
    videoFrame = new Texture2D(2, 2);] 
    ... 
} 

//Initialize in the Start function 
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; 

    targetColor = CalculateAverageColorFromTexture(videoFrame); 
    lSource.color = targetColor; 
} 

完全なコード:

public class AverageColorFromTexture : MonoBehaviour 
{ 
    public VideoClip videoToPlay; 
    public Light lSource; 

    private Color targetColor; 
    private VideoPlayer videoPlayer; 
    private VideoSource videoSource; 
    private Renderer rend; 
    private Texture tex; 
    private AudioSource audioSource; 

    void Start() 
    { 
     videoFrame = new Texture2D(2, 2); 
     Application.runInBackground = true; 
     StartCoroutine(playVideo()); 
    } 

    IEnumerator playVideo() 
    { 
     rend = GetComponent<Renderer>(); 

     videoPlayer = gameObject.AddComponent<VideoPlayer>(); 
     audioSource = gameObject.AddComponent<AudioSource>(); 

     //Disable Play on Awake for both Video and Audio 
     videoPlayer.playOnAwake = false; 
     audioSource.playOnAwake = false; 

     videoPlayer.source = VideoSource.VideoClip; 
     videoPlayer.audioOutputMode = VideoAudioOutputMode.AudioSource; 
     videoPlayer.EnableAudioTrack(0, true); 
     videoPlayer.SetTargetAudioSource(0, audioSource); 

     //Set video To Play then prepare Audio to prevent Buffering 
     videoPlayer.clip = videoToPlay; 
     videoPlayer.Prepare(); 

     //Wait until video is prepared 
     while (!videoPlayer.isPrepared) 
     { 
      Debug.Log("Preparing Video"); 
      yield return null; 
     } 
     Debug.Log("Done Preparing Video"); 

     //Assign the Texture from Video to Material texture 
     tex = videoPlayer.texture; 
     rend.material.mainTexture = tex; 

     //Enable new frame Event 
     videoPlayer.sendFrameReadyEvents = true; 

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

     //Play Video 
     videoPlayer.Play(); 

     //Play Sound 
     audioSource.Play(); 

     Debug.Log("Playing Video"); 
     while (videoPlayer.isPlaying) 
     { 
      Debug.LogWarning("Video Time: " + Mathf.FloorToInt((float)videoPlayer.time)); 
      yield return null; 
     } 
     Debug.Log("Done Playing Video"); 
    } 

    //Initialize in the Start function 
    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; 

     targetColor = CalculateAverageColorFromTexture(videoFrame); 
     lSource.color = targetColor; 
    } 

    Color32 CalculateAverageColorFromTexture(Texture2D tex) 
    { 
     Color32[] texColors = tex.GetPixels32(); 
     int total = texColors.Length; 
     float r = 0; 
     float g = 0; 
     float b = 0; 

     for (int i = 0; i < total; i++) 
     { 
      r += texColors[i].r; 
      g += texColors[i].g; 
      b += texColors[i].b; 
     } 
     return new Color32((byte)(r/total), (byte)(g/total), (byte)(b/total), 0); 
    } 
} 
+0

おかげでお返事のためとあなたの答えをコーディングする時間を取るために非常に多くの! ... VideoPlayerテクスチャをキャストするときに 'UnityEngine.Video.VideoSourceをUnityEngine.Texture2Dに変換できません'というエラーが表示されます。 – Jayme

+0

私の答えは、あなたが 'VideoPlayer.texture' **を' VideoPlayer'ではなく 'Texture2D'に変換することを二度言いました。私の答えから関数を直接コピーしてください。 – Programmer

+0

返事をありがとう! 私はあなたが言ったとおりに正確に行ってきましたが、OnNewFrame関数内の 'Texture2D videoFrame =(Texture2D)source.texture; 'でキャストエラーが発生しました! 私が間違っていることを指摘してもらえますか? ありがとうございました – Jayme

関連する問題