How to play a video on a canvas with RawImage?

I am using NatCorder to record the Unity camera to an MP4 file. This works and I can view the saved MP4 file if I open it in QuickTime on macOS.

However, all attempts I made so far to play it on a Unity canvas failed. I watched a lot of YouTube videos and docs and set up a RawImage plus a VideoPlayer to play the video.

If I try to play the video, I can hear the sound. But I cannot see the video. I tried the same with another MP4 I created earlier with DaVinci, and it doesn’t work either. Both videos have the right codec (H.264).

Everything looks exactly the same as on YouTube videos, but it won’t work. I am using Unity 2019.3.15f1 and tried to play the scene on both macOS and iOS.

My code looks like this:

videoPlayer.url = ;
videoPlayer.source = VideoSource.Url;
videoPlayer.renderMode = VideoRenderMode.APIOnly; // recommended by NatCorder author
videoPlayer.Prepare();
WaitForSeconds waitForSeconds = new WaitForSeconds(1);
while (!videoPlayer.isPrepared) {
yield return waitForSeconds;
break;
}
fullscreenPreviewImage.texture = videoPlayer.texture; // this is the RawImage
fullscreenPreviewImage.color = Color.white;
videoPlayer.Play();

Hi!

First thing to know is whether Unity recognizes the video track in the file at all. You’ll know this by just dropping it in the Assets folder and see if the video clip importer preview shows the content.

One thing I see in your script is that the while loop has a break; statement in it: it shouldn’t, or else you run the risk of breaking out of the wait before the player is actually prepared. Honestly, one second (like you are doing here) is probably enough, but this construct is still risky so give it a try without the break.

Here’s the code I wrote to test it out and it does work for me. You have to make sure to set the RawImage Pos X, Pos Y, Pos Z, Width and Height to something that’s in the viewport (for me it defaulted to something almost completely out of view).

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

public class PlayVideo : MonoBehaviour
{
    public VideoPlayer videoPlayer;
    public string videoUrl;
    public RawImage rawImage;
    IEnumerator Start()
    {
        if (videoPlayer == null || rawImage == null || string.IsNullOrEmpty(videoUrl))
            yield break;

        videoPlayer.url = videoUrl;
        videoPlayer.renderMode = VideoRenderMode.APIOnly;
        videoPlayer.Prepare();
        while (!videoPlayer.isPrepared)
            yield return new WaitForSeconds(1);

        rawImage.texture = videoPlayer.texture;
        videoPlayer.Play();
    }
}

You’ll also see I omitted videoPlayer.source = VideoSource.Url;. It’s not harmful but not necessary: the VideoPlayer reverts to this source mode when you set the url.

Let me know what you find!

Dominique Leroux
A/V developer at Unity

1 Like

Thanks, Dominique, for your response! Yes, the break was my bad. I am using the event driven model now, using the prepareCompleted event, which worked.