使用新的Unity VideoPlayer和VideoClip API播放视频

Pro*_*mer 35 c# unity-game-engine unity5

在Unity 5.6.0b1发布之后, MovieTexture最终被弃用,现在发布了在桌面和移动设备上播放视频的新API.

如果需要, VideoPlayer VideoClip可用于播放视频并检索每个帧的纹理.

我已经设法让视频正常工作但是却没有从Windows 10的编辑器那里得到音频.任何人都知道为什么音频没有播放?

//Raw Image to Show Video Images [Assign from the Editor]
public RawImage image;
//Video To Play [Assign from the Editor]
public VideoClip videoToPlay;

private VideoPlayer videoPlayer;
private VideoSource videoSource;

//Audio
private AudioSource audioSource;

// Use this for initialization
void Start()
{
    Application.runInBackground = true;
    StartCoroutine(playVideo());
}

IEnumerator playVideo()
{
    //Add VideoPlayer to the GameObject
    videoPlayer = gameObject.AddComponent<VideoPlayer>();

    //Add AudioSource
    audioSource = gameObject.AddComponent<AudioSource>();

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

    //We want to play from video clip not from url
    videoPlayer.source = VideoSource.VideoClip;

    //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");

    //Set Audio Output to AudioSource
    videoPlayer.audioOutputMode = VideoAudioOutputMode.AudioSource;

    //Assign the Audio from Video to AudioSource to be played
    videoPlayer.EnableAudioTrack(0, true);
    videoPlayer.SetTargetAudioSource(0, audioSource);

    //Assign the Texture from Video to RawImage to be displayed
    image.texture = videoPlayer.texture;

    //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");
}
Run Code Online (Sandbox Code Playgroud)

Pro*_*mer 57

发现了问题.以下是播放视频和音频的FIXED代码:

//Raw Image to Show Video Images [Assign from the Editor]
public RawImage image;
//Video To Play [Assign from the Editor]
public VideoClip videoToPlay;

private VideoPlayer videoPlayer;
private VideoSource videoSource;

//Audio
private AudioSource audioSource;

// Use this for initialization
void Start()
{
    Application.runInBackground = true;
    StartCoroutine(playVideo());
}

IEnumerator playVideo()
{
    //Add VideoPlayer to the GameObject
    videoPlayer = gameObject.AddComponent<VideoPlayer>();

    //Add AudioSource
    audioSource = gameObject.AddComponent<AudioSource>();

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

    //We want to play from video clip not from url
    videoPlayer.source = VideoSource.VideoClip;

    //Set Audio Output to AudioSource
    videoPlayer.audioOutputMode = VideoAudioOutputMode.AudioSource;

    //Assign the Audio from Video to AudioSource to be played
    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 RawImage to be displayed
    image.texture = videoPlayer.texture;

    //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");
}
Run Code Online (Sandbox Code Playgroud)

为什么音频没有播放:

//Set Audio Output to AudioSource
videoPlayer.audioOutputMode = VideoAudioOutputMode.AudioSource;

//Assign the Audio from Video to AudioSource to be played
videoPlayer.EnableAudioTrack(0, true);
videoPlayer.SetTargetAudioSource(0, audioSource);
Run Code Online (Sandbox Code Playgroud)

必须先打电话,然后videoPlayer.Prepare();再打电话.这需要数小时的实验才能发现这是我遇到的问题.


坚持"准备视频"?

videoPlayer.Prepare();调用后等待5秒钟然后退出while循环.

更换:

while (!videoPlayer.isPrepared)
{
    Debug.Log("Preparing Video");
    yield return null;
}
Run Code Online (Sandbox Code Playgroud)

有:

//Wait until video is prepared
WaitForSeconds waitTime = new WaitForSeconds(5);
while (!videoPlayer.isPrepared)
{
    Debug.Log("Preparing Video");
    //Prepare/Wait for 5 sceonds only
    yield return waitTime;
    //Break out of the while loop after 5 seconds wait
    break;
}
Run Code Online (Sandbox Code Playgroud)

这应该可以,但是当视频开始播放时您可能会遇到缓冲.在使用这个临时修复时,我的建议是提交标题为"videoPlayer.isPrepared always true"的bug,因为这是一个bug.

有些还修改了它:

videoPlayer.playOnAwake = false; 
audioSource.playOnAwake = false;
Run Code Online (Sandbox Code Playgroud)

videoPlayer.playOnAwake = true; 
audioSource.playOnAwake = true;
Run Code Online (Sandbox Code Playgroud)

从URL播放视频:

更换:

//We want to play from video clip not from url
videoPlayer.source = VideoSource.VideoClip;
Run Code Online (Sandbox Code Playgroud)

有:

//We want to play from url
videoPlayer.source = VideoSource.Url;
videoPlayer.url = "http://www.quirksmode.org/html5/videos/big_buck_bunny.mp4";
Run Code Online (Sandbox Code Playgroud)

然后删除:

public VideoClip videoToPlay;videoPlayer.clip = videoToPlay;这些都不再需要.

从StreamingAssets文件夹播放视频:

string url = "file://" + Application.streamingAssetsPath + "/" + "VideoName.mp4";

if !UNITY_EDITOR && UNITY_ANDROID
    url = Application.streamingAssetsPath + "/" + "VideoName.mp4";
#endif

//We want to play from url
videoPlayer.source = VideoSource.Url;
videoPlayer.url = url;
Run Code Online (Sandbox Code Playgroud)

所有支持的视频格式:

  • OGV
  • VP8
  • WEBM
  • MOV
  • DV
  • MP4
  • M4V
  • MPG
  • MPEG

Windows上额外支持的视频格式:

  • AVI
  • ASF
  • WMF

其中一些格式在某些平台上不起作用.有关支持的视频格式的更多信息,请参阅帖子.


Gro*_*shh 8

与其他答案一样.您可以在准备和结束视频状态时使用回调.而不是使用协同程序和收益率.

videoPlayer.loopPointReached += EndReached;
videoPlayer.prepareCompleted += PrepareCompleted;

void PrepareCompleted(VideoPlayer vp) {
    vp.Play();
}

void EndReached(VideoPlayer vp) {
    // do something
}
Run Code Online (Sandbox Code Playgroud)

  • 这听起来比协同程序更合理 (2认同)