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

Posted

技术标签:

【中文标题】使用新的 Unity VideoPlayer 和 VideoClip API 播放视频【英文标题】:Using new Unity VideoPlayer and VideoClip API to play video 【发布时间】:2016-12-14 13:38:42 【问题描述】:

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

VideoPlayerVideoClip 可用于播放视频并在需要时检索每一帧的纹理。

我已设法让视频正常工作,但在 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");

【问题讨论】:

您自己转换为向社区发帖了吗? @Lestat 我没有,但如果可以的话,我会的。看起来Martijn Pieters 这样做了,因为这个问题被新用户滥用,他们只发布问题作为答案。他不得不删除其中的多个答案/问题。 我创建了一个使用 VideoPlayer 的视频教程。这是链接。 youtu.be/nGA3jMBDjHk. 另外,如果您正在加载多个视频并面临应用程序的滞后,这可能会有所帮助。 ***.com/questions/42801468/… 看来 VideoPlayer.prepare() 在主线程上运行!尤其是在安卓上。结果是应用程序在 prepare() 工作时挂起!使这个新界面几乎无法使用。而且你也不能在 bckd 线程上运行它。有人找到解决办法吗? 【参考方案1】:

发现问题。下面是播放视频和音频的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");

为什么没有播放音频:

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

必须在videoPlayer.Prepare(); 之前而不是之后调用。这需要数小时的实验才能发现这是我遇到的问题。


卡在“准备视频”?

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

替换:

while (!videoPlayer.isPrepared)

    Debug.Log("Preparing Video");
    yield return null;

与:

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

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

一些people 也通过更改修复了它:

videoPlayer.playOnAwake = false; 
audioSource.playOnAwake = false;

videoPlayer.playOnAwake = true; 
audioSource.playOnAwake = true;

从 URL 播放视频:

替换:

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

与:

//We want to play from url
videoPlayer.source = VideoSource.Url;
videoPlayer.url = "http://www.quirksmode.org/html5/videos/big_buck_bunny.mp4";

然后删除

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;

所有支持的视频格式

ogv vp8 网站 电影 dv mp4 m4v mpg mpeg

Windows 上额外支持的视频格式

avi asf wmf

其中一些格式不适用于某些平台。有关支持的视频格式的更多信息,请参阅 this 帖子。

【讨论】:

很抱歉时不时地戳你,但对我来说视频没有播放,那是因为videoPlayer.playOnAwake = false; audioSource.playOnAwake = false;我将值更改为true。我现在明白了,我想我现在必须开发脚本来控制视频的播放和暂停。 我不这么认为,但是如果您能够将视频存储在任何这些服务上,并且 URL 以 .mp4 或有效的视频文件名结尾,那么您就可以播放它。请记住,这些服务并非为此而生。您需要一个专用服务器,因为流式传输视频很昂贵。当我说昂贵时,我指的是带宽。 @Harschell 如果这对您不起作用,请提交错误报告。 @Bluetree 是的。新的VideoPlayer 应该可以在任何平台上运行。 @Programmer 如何获取 videoPlayer.url 的长度?我没有使用 VideoClip。【参考方案2】:

与其他答案所说的类似。您可以在准备和结束视频状态时使用回调。而不是使用协程和yield return。

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

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


void EndReached(VideoPlayer vp) 
    // do something

【讨论】:

当然,我还遇到了一些音频错误。我发现使用回调方法的地方为我省去了很多麻烦。特别是如果您最终尝试在一个视频之后播放另一个视频。 这听起来比协程合理得多【参考方案3】:

我使用 @Programmer 的答案从 URL 播放视频,但我无法播放任何声音。最终我在the comments of a YouTube tutorial.找到了答案

要让通过 URL 加载的电影播放音频,您需要在调用 EnableAudioTrack 之前添加以下行:

videoPlayer.controlledAudioTrackCount = 1;

【讨论】:

有趣。网址视频中的音频没有问题,但这对其他人有帮助。这可能是编辑器中的错误。【参考方案4】:

到现在为止,VideoPlayer 应该已经足够更新,您无需编写代码即可正常工作。以下是我发现效果最理想的设置:

这些设置是:

视频播放器

在清醒状态下播放:正确 等待第一帧:错误 音频输出模式:

音源

在清醒状态下播放:正确

不要忘记为 VideoPlayer 设置一个 VideoClip,为 AudioSource 设置一个 AudioClip。我发现效果最好的文件格式是用于视频的 .ogv 和用于音频的 .wav。

【讨论】:

“VideoPlayer 应该更新到足以让您无需编写代码即可正常工作” 并非如此。您仍然需要在某些平台和一些(长)视频上编写一些代码,否则视频将被冻结。修复方法是调用只能通过代码完成的 Prepare() 函数。 @Programmer 好点。我只有一个简短的视频,所以我不需要代码让它在启动时播放

以上是关于使用新的 Unity VideoPlayer 和 VideoClip API 播放视频的主要内容,如果未能解决你的问题,请参考以下文章

在 Agora.io 视频通话后 Unity VideoPlayer 音频中断

unity5.6.1 videoPlayer

Unity⭐️VideoPlayer

VideoPlayer与安卓

Unity 视频播放器,基于VideoPlayer,实现滑动进度条,显示视频时长,全屏显示,音量调节

Unity3d 2021版本播放视频组件VideoPlayer报错The type name ‘VideoPlayer‘ could not be found in the namespace...