42

MovieTexture is finally deprecated after Unity 5.6.0b1 release and new API that plays video on both Desktop and Mobile devices is now released.

VideoPlayer and VideoClip can be used to play video and retrieve texture for each frame if needed.

I've managed to get the video working but coduldn't get the audio to play as-well from the Editor on Windows 10. Anyone know why audio is not playing?

//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");
}
Programmer
  • 121,791
  • 22
  • 236
  • 328
  • did you convert to post to community yourself? – Daahrien Jan 04 '17 at 20:28
  • @Lestat I did not but I would have if I could. It looks like [Martijn Pieters](http://stackoverflow.com/users/100297/martijn-pieters) did since this question was abused by new Users who only posted questions as an answer. He had to delete multiple of those answers/questions. – Programmer Jan 04 '17 at 20:34
  • I have created a video tutorial on using VideoPlayer. Here's the link. https://youtu.be/nGA3jMBDjHk. – Luzan Baral Mar 15 '17 at 17:34
  • Also if you are loading multiple videos and facing the lag in App, this might help. http://stackoverflow.com/questions/42801468/unity-app-freezes-when-loading-multiple-videos-on-same-scene/42829081#42829081 – Luzan Baral Mar 17 '17 at 05:03
  • It seems VideoPlayer.prepare() runs on the MAIN THREAD! Especially on Android. The result is an app that hangs while prepare() is working! Rending this new interface almost unusable. And you can't run it on the bckd thread either. Anybody found a work around? – TatiOverflow Sep 21 '17 at 02:00
  • No. It runs in the background and does not block the main Thread. Please post your code to pastebin then link it here and I will take a look. Also mention your Unity version. – Programmer Sep 21 '17 at 02:07
  • I have code sample here https://github.com/tati-nacmedia/testvplayer/blob/master/Assets/VideoPlayerController.cs i have put a unity package here too https://github.com/tati-nacmedia/testvplayer/blob/master/testvplayerpackage.unitypackage it plays well on windows, iOS, but lags massively on Android. I've read somewhere a unity dev saying it doesn't support async on Android. Dont remember where. I have added prepare delay to demonstrate the lag using coroutine. – TatiOverflow Sep 21 '17 at 07:28

4 Answers4

65

Found the problem. Below is the FIXED code that plays Video and Audio:

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

Why Audio was not playing:

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

must be called before videoPlayer.Prepare(); not after it. This is took hours of experiment to find this this was the problem I was having.


Stuck at "Preparing Video"?

Wait 5 seconds after videoPlayer.Prepare(); is called then exit the while loop.

Replace:

while (!videoPlayer.isPrepared)
{
    Debug.Log("Preparing Video");
    yield return null;
}

with:

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

This should work but you may experience buffering when the video starts playing. While using this temporary fix, my suggestion is to file for bug with the title of "videoPlayer.isPrepared always true" because this is a bug.

Some people also fixed it by changing:

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

to

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

Play Video From URL:

Replace:

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

with:

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

then Remove:

public VideoClip videoToPlay; and videoPlayer.clip = videoToPlay; as these are not needed anymore.

Play Video From StreamingAssets folder:

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;

All supported video formats:

  • ogv
  • vp8
  • webm
  • mov
  • dv
  • mp4
  • m4v
  • mpg
  • mpeg

Extra supported video formats on Windows:

  • avi
  • asf
  • wmf

Some of these formats don't work on some platforms. See this post for more information on supported video formats.

Programmer
  • 121,791
  • 22
  • 236
  • 328
  • I tried to use your code for playing video on Unity 5.6.0b10 by adding an .ogv video. But when I hit play, I can only see Preparing video on Console. And I am also confused does the GameObject has to be RawImage, and what should be on Image? Can you help me solve my problem too? – Luzan Baral Mar 08 '17 at 11:09
  • @LuzanBaral *"And I am also confused does the GameObject has to be RawImage, and what should be on Image?"* No. I used `RawImage` instead of the `Image` component because it is the most efficient way to do this. If you use the Image component for this, you would have to convert the Video `Texture` to `Sprite` then to `Image`. This is expensive. – Programmer Mar 08 '17 at 11:38
  • Note that `RawImage image;` is only used to display the Texture from the Video. Create it by going to GameOjbect --> UI --> RawImage then drag the RawImage to the image variable from the script in the answer. You also need to drag the video to play to the videoToPlay slot in the script. – Programmer Mar 08 '17 at 11:41
  • I did the same, but still when I hit play I see only Preparing Video in infinite loop. http://imgur.com/h2Hv9Ku – Luzan Baral Mar 08 '17 at 12:03
  • 1
    Sorry for poking you every now and while, but for me the video was not playing, and that was because of `videoPlayer.playOnAwake = false; audioSource.playOnAwake = false;` I changed the values to `true`. I get it now, I think I'll have to develop script to control play and pause for the video now. – Luzan Baral Mar 08 '17 at 12:09
  • BTW do you have any idea how can I play video from URL, and can we add other video formats like .mp4 from URL. – Luzan Baral Mar 08 '17 at 12:10
  • @LuzanBaral Check my updated answer. Let me know if there is another question. – Programmer Mar 08 '17 at 12:58
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/137563/discussion-between-luzan-baral-and-programmer). – Luzan Baral Mar 08 '17 at 13:59
  • BTW did you also figured out the way to play Video on full screen. – Luzan Baral Mar 17 '17 at 05:06
  • is there a way we can save videos on services like Dropbox, Box, Google Drive to play the video using `VideoSource.Url` – Luzan Baral Apr 11 '17 at 06:15
  • 1
    I don't think so but if you are able to store the video on any of those services with url that ends with .mp4 or a valid video file name then you may be able to play it. Remember that these services are not meant for that. You need a dedicated server for that as it is expensive to stream videos. When I say expensive, I mean Bandwidth. – Programmer Apr 11 '17 at 07:10
  • This does not working for me have done required changes yet not able to make it work :( //We want to play from url videoPlayer.source = VideoSource.Url; videoPlayer.url = "http://www.quirksmode.org/html5/videos/big_buck_bunny.mp4"; Anyone get it working? Any suggestion? @Programmer – Harschell Jun 08 '17 at 12:48
  • 1
    @Harschell Please file for a bug report if this does not work for you. – Programmer Jun 08 '17 at 14:34
  • it works for me fine in my editor, but when i run it on my android phone it does not play the video @Programmer – Martin j Jul 11 '17 at 12:37
  • I am not sure the method(local/online) you are using to play the video but try with **Unity 2017** which fixes most VideoPlayer bugs on Android. If that doesn't work then file for a bug report. Always tell them information about your Android device. – Programmer Jul 11 '17 at 12:45
  • @Programmer sorry my mistake i forget to give internet permission in the inspecter from AUTO to Require – Martin j Jul 11 '17 at 12:45
  • No problem. Glad you found it to be useful. – Programmer Jul 11 '17 at 12:46
  • @Programmer which all video formats are supported in this video player . Is m3u8 format supported... i was able to play the mp4 type but not able to play m3u8 format – Martin j Jul 12 '17 at 08:40
  • Edited the answer to add that. M3U is not mentioned there so I think it's not supported. You can ask for this support on Unity's [forum](https://forum.unity3d.com/threads/correct-video-format-for-video-playback.446011/#post-2886983). Maybe they will add it. – Programmer Jul 12 '17 at 09:14
  • @Programmer just want to ask if this is compatible in Android/IOS? – Bluetree Dec 01 '17 at 09:01
  • 1
    @Bluetree Yes. The new `VideoPlayer` should work on any platform. – Programmer Dec 01 '17 at 09:02
  • This worked for me, but the audio was out of sync. My file formats were .ogv and .wav, and I used pre-added components and GetComponent<>() instead of adding new components – shieldgenerator7 Dec 05 '17 at 19:49
  • Hello there! I'm able to load the video from the internal Memory on Android and iOS but the Audio doesn't play on editor or in the devices. It's the only trouble I'm facing right now. I just Download the video file and then I load the file inside the VideoPlayer with this scripts. Does I miss something? – Salvador Lemus Jan 11 '18 at 22:28
  • @SalvadorLemus Did you use the code in this answer? If not then copy and paste it to make sure nothing else changes. The audio should play fine with this code – Programmer Jan 11 '18 at 22:31
  • @Programmer Yes, I use the code in this site but I'm not able to hear the video sound. Actually I just start a new Unity project and put the VideoPlayer component inside the main camera, then set the videoSource as a URL type and paste this link "http://www.quirksmode.org/html5/videos/big_buck_bunny.mp4". The sound doesn't work. – Salvador Lemus Jan 12 '18 at 16:50
  • Ok. It looks like that when I want to use a URL as a input for the VideoPlayer the audio doesn't work out of the box. To get around this I attach an Audio Source to the VideoPlayer object and in the editor set the VideoSource as URL, then change the AudioOuputMode to Audio Source and pass my Audio Source component. This solve the audio trouble with the streaming videos. – Salvador Lemus Jan 12 '18 at 17:21
  • @SalvadorLemus *"I attach an Audio Source to the VideoPlayer object and in the editor set the VideoSource as URL, then change the AudioOuputMode to Audio Source and pass my Audio Source component"* Sorry but that's what the code in this answer is doing. See the `gameObject.AddComponent()`, `VideoAudioOutputMode.AudioSource`, `videoPlayer.EnableAudioTrack(0, true);` and `videoPlayer.SetTargetAudioSource(0, audioSource);`. You are doing something wrong but I am glad you got it fixed. – Programmer Jan 12 '18 at 18:54
  • 1
    @Programmer How do i get the length of videoPlayer.url? I am not using VideoClip. – Suraksha Ajith Aug 20 '18 at 10:04
  • @SurakshaAjith Sounds complicated since `videoPlayer.clip` is null. I suggest you ask new question and let me know when you do so. I will do some experiment and if I come with a way to find that. – Programmer Aug 20 '18 at 16:07
  • 1
    @Programmer Thank for the reply but i found a work around, I used C# `System.TimeSpan` to solve the problem. This code might help someone `double time = videoplayer.frameCount / videoplayer.frameRate; System.TimeSpan VideoUrlLength = System.TimeSpan.FromSeconds(time);` – Suraksha Ajith Aug 21 '18 at 07:38
  • @Programmer instead of using a coroutine to loop until `videoPlayer.isPrepared` is true, shouldn't we just use the `VideoPlayer.prepareCompleted` event? That should also fix the issue with needing `WaitForSeconds()`. – Daevin Aug 30 '18 at 13:31
  • @Daevin The issue with the `VideoPlayer` events is that when it the VideoPlayer was first released, these events sometimes were called and *sometimes were not called.* I got tired of filing for bug reports on them and don't know if they still work. They still have issues on some platforms. When they are not called, your next code wouldn't execute. You would have to add an `Update` function then implement a timer to exit when they are not called otherwise your app would seat there and do nothing. – Programmer Aug 30 '18 at 17:24
  • The idea of the method I used is to have one function to handle the video instead of depending callback functions and the `Update`. Also, you can easily add a Prepare timeout in that coroutine function too so that you can tell the user that there's something wrong with the video when loading it.. Something you can't do with event without the Update function. You can also show the video time like I did in that same function but you would need the `Update` function if you go with events. Note that if `videoPlayer.isPrepared` is not working properly, the prepareCompleted will also have issues. – Programmer Aug 30 '18 at 17:38
  • @Programmer ah, gotcha, that makes sense. – Daevin Aug 30 '18 at 18:23
12

Similar to what the other answers have been saying. You could use callbacks for when preparing and end of video states. Rather than using coroutines and yield return.

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

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

void EndReached(VideoPlayer vp) {
    // do something
}
Groshh
  • 140
  • 1
  • 11
  • Sure, there's a few more audio bugs that I've encountered. Where I found using the callback methods saved me a lot of headaches. Particularly if you end up trying to play one video following another. – Groshh Apr 28 '17 at 09:30
  • 2
    This sounds like a much more reasonable solution than coroutines – shieldgenerator7 Dec 05 '17 at 19:50
2

I used @Programmer 's answer to play videos from a URL, but I couldn't get any sound to play. Eventually I found the answer in the comments of a YouTube tutorial.

To get the audio to play for a movie loaded via URL, you need to add the following line before the call to EnableAudioTrack:

videoPlayer.controlledAudioTrackCount = 1;
TarkaDaal
  • 18,798
  • 7
  • 34
  • 51
  • Interesting. Haven't had issues with audios from url videos but this will be helpful to others. It could be a bug in the Editor. – Programmer Jul 10 '18 at 13:34
-2

By now the VideoPlayer should be updated enough you don't need to write code to get to work correctly. Here are the settings I found to have the most desirable effect: Optimal Settings

These settings are:

Video Player:

  • Play On Awake: True
  • Wait For First Frame: False
  • Audio Output Mode: None

Audio Source:

  • Play On Awake: True

Don't forget to have a VideoClip for the VideoPlayer and an AudioClip for the AudioSource. The file formats I found to work the best are .ogv for video and .wav for audio.

shieldgenerator7
  • 1,507
  • 17
  • 22
  • *"VideoPlayer should be updated enough you don't need to write code to get to work correctly"* Not really. You still need to write some code on some platforms and some(long) videos otherwise the video will be freezing. The fix is calling the `Prepare()` function which can only be done from code. – Programmer Dec 12 '17 at 08:13
  • @Programmer ok good point. I only had a short video so I didn't need the code to make it play on start up – shieldgenerator7 Dec 13 '17 at 09:27