Search Unity

Video VideoPlayer.setUrl() and VideoPlayer.Prepare very expensive ?

Discussion in 'Audio & Video' started by ahmidou, Apr 7, 2017.

  1. ahmidou

    ahmidou

    Joined:
    Sep 17, 2012
    Posts:
    79
    Hi I'm trying to implement a system to switch between videos loaded from the hard drive at runtime.
    The problem is I'm getting massive slowdown when switching the video on the same VideoPlayer (see the picture).
    So I'm wondering if instead of one VideoPlayer I would use multiple ones, how would that scale if I have let say 20 videos?

    Note: I'm using the Adam and BigBuck Bunny 1080p videos for my tests.

    Thanks
    -A
     

    Attached Files:

  2. Saryk360

    Saryk360

    Joined:
    Apr 7, 2017
    Posts:
    8
    I don't know the answer but I'd suggest trying it out and checking it out empirically ^-^
    I'll look into it in the meantime :)
     
  3. ahmidou

    ahmidou

    Joined:
    Sep 17, 2012
    Posts:
    79
    Hi Laurent, thanks for giving a look at it.

    So I tried with multiple VideoPlayers, it's a bit better, but I'm still getting a slowdown.
    when calling VideoPlayer.Play() it prepares the video again, event if it already have been done on init.
     

    Attached Files:

  4. Saryk360

    Saryk360

    Joined:
    Apr 7, 2017
    Posts:
    8
    Let us see your code ;)
     
  5. ahmidou

    ahmidou

    Joined:
    Sep 17, 2012
    Posts:
    79
    There it is! I tried to extract the specific code, that might not work straight, but you get the idea.
    This was added on a Dropdown menu.

    Code (CSharp):
    1. public class VideoControl : MonoBehaviour {
    2.  
    3.     private int currentVP;
    4.     private Dictionary<int,VideoPlayer> videoPlayer = new Dictionary<int,VideoPlayer>();
    5.     private Dropdown dropdown;
    6.  
    7.  
    8.     void Start () {
    9.         if (Application.isEditor) absolutePath = "Assets/../Videos";
    10.         else absolutePath = Application.dataPath + "/../Videos";
    11.  
    12.         dropdown = this.GetComponent<Dropdown>();
    13.         dropdown.onValueChanged.AddListener(delegate { ValueChange(); });
    14.  
    15.         ReloadVideos();
    16.     }
    17.  
    18.  
    19.     void ReloadVideos()
    20.     {
    21.         if (Directory.Exists(absolutePath))
    22.         {
    23.             var info = new DirectoryInfo(absolutePath);
    24.             files = info.GetFiles()
    25.                 .Where(f => IsValidFileType(f.Name))
    26.                 .ToArray();
    27.  
    28.             // and load them
    29.             foreach (var file in files)
    30.             {
    31.                 dropdown.options.Add(new Dropdown.OptionData { text = name });
    32.                 int i = dropdown.options.Count()-1;
    33.  
    34.                 videoPlayer[i] = camera.gameObject.AddComponent<VideoPlayer>();
    35.                 videoPlayer[i].playOnAwake = false;
    36.                 videoPlayer[i].source = VideoSource.VideoClip;
    37.                 videoPlayer[i].targetCameraAlpha = 0;
    38.                 videoPlayer[i].url = file.FullName;
    39.                 videoPlayer[i].Prepare();
    40.             }
    41.         }
    42.     }
    43.  
    44.     IEnumerator VideoFadeOut(int index) {
    45.         isFading = true;
    46.         while (videoPlayer[index].targetCameraAlpha > 0) {
    47.             videoPlayer[index].targetCameraAlpha -= 0.02f;
    48.             yield return null;
    49.         }
    50.         videoPlayer[index].Stop();
    51.     }
    52.  
    53.     IEnumerator VideoFadeIn(int index) {
    54.         isFading = true;
    55.         while (videoPlayer[index].targetCameraAlpha < 1) {
    56.             videoPlayer[index].targetCameraAlpha += 0.02f;
    57.             yield return null;
    58.         }
    59.     }
    60.  
    61.  
    62.     public void ValueChange()
    63.     {
    64.         if (dropdown.value != 0) // first item is none
    65.         {
    66.             //stop curent playing video
    67.             if (videoPlayer.ContainsKey(currentVP) && videoPlayer[currentVP].isPlaying)
    68.             {
    69.                 StartCoroutine(VideoFadeOut(currentVP));      
    70.             }
    71.             else
    72.             {
    73.                 videoPlayer[dropdown.value -1].Play();
    74.                 StartCoroutine(VideoFadeIn(dropdown.value));
    75.                 currentVP = dropdown.value -1;
    76.             }
    77.         }
    78.         else
    79.         {
    80.             if (videoPlayer[currentVP].isPlaying)
    81.             {
    82.                 StartCoroutine(VideoFadeOut(currentVP));      
    83.             }
    84.         }
    85.     }
    86. }
    87.  
     
    Last edited: Apr 7, 2017
  6. DominiqueLrx

    DominiqueLrx

    Unity Technologies

    Joined:
    Dec 14, 2016
    Posts:
    108
    Hi ahmidou!

    Prepare() is indeed not free. Many of the implementations are currently running in the calling thread although some are asynchronous (iOS / OSX comes to mind). In the long run, they will all become asynchronous.

    But independently of this, preparing all players like you are doing does not scale. What Prepare() does behind the scene is create one codec instance per track (video, audio) and allocates textures so everything is ready for playback.

    Doing this, you may run into platform limitations: one cannot instantiate an infinite number of codecs, as these are tied to hardware resources.

    As for Prepare() getting called even if you already did, please note that Stop() will undo the preparation. So assuming you stay with your current implementation (because you can prove to yourself that you don't exceed platform limits), then I suggest using Pause() instead, which will preserve the preparation. Please let us know if this was the issue because preparation should not be redone once it has succeeded.

    Hope this helps, and thanks for letting us know that Prepare() time is important to you; a fix to make preparation in another thread is ongoing, we'll make it available as soon as possible.

    Have a good week-end,

    Dominique
    A/V developer at Unity
     
  7. ahmidou

    ahmidou

    Joined:
    Sep 17, 2012
    Posts:
    79
    Hi Dominique,
    Using one VideoPlayer per video and Pause() made it smooth.
    So I guess now my question is is it OK to have N VideoPlayers hanging around?

    Thanks and have a good week end as well

    Ahmidou.
     
  8. Makro-

    Makro-

    Joined:
    Jun 10, 2015
    Posts:
    6
    Can you give any time frame on when the other platforms (Android in particular) are becoming asynchronous?
    In our usecase we get the video url just before the video needs to start playing so atm on Android the new video player is unusable in this case because the app stalls for a while when preparing the video. On iOS it works well.
     
  9. ianmacg

    ianmacg

    Joined:
    Mar 11, 2016
    Posts:
    5
    Ping -- Dominique, can you provide any update on making Prepare asynchronous on other platforms? I'm developing for Windows/VR and VideoPlayer is currently unusable if I wish to swap video clips in and out.
     
  10. DGordon

    DGordon

    Joined:
    Dec 8, 2013
    Posts:
    352
    Can we please get an update on this? This is a very important issue for any android experience using multiple videos. We have upwards of 100 256x256 short videos right now used for tutorials in a VR experience, and the entire app hitches down to about 10fps when the video prepares. There's no way we can launch with this as is. So either this gets fixed, or we ditch the video player.

    Is this currently being worked on? Is it high priority or low priority? Can we get an ETA? If not through you, what are the proper channels to inquire into this?

    Again, this isn't a theoretical issue. Its completely crippling our ability to use the VideoPlayer on android at the moment unless we forgo a professional level of polish (which we can't).
     
  11. DGordon

    DGordon

    Joined:
    Dec 8, 2013
    Posts:
    352
    I'm going to tag you again in hopes that somebody at Unity will actually respond to one of the threads about this issue that is currently blocking a bunch of people.

    Is this being worked on for Android, and what is the ETA?

    To quote a different thread that's going on where I just left a post:

    "We completely removed any trace of the VideoPlayer from our Android app for this reason. Its absolutely ridiculous that Unity has not given any form of response to this issue. There are three threads that were opened on this. One of them directly tagged a Unity developer who had responded previously in the same thread, saying they were addressing the Android issue (half a year ago). And then neither he, nor anyone else, ever responded again.

    To be honest, this shows a tremendous lack of respect to any customer who ran into this issue. Not only did we spend time and money using a feature that was supposedly finished only to have to rip it out and implement a new system, but they have not even bothered to respond.

    I'm pretty amazed, to be honest. Usually they're pretty good about eventually responding to something that requires it, but this has been completely ignored after it was already stated they're aware of the issue, know what it is, and actively fixing it."

    Seriously ... did you really release the new VideoPlayer, only to have your customers have to rip it out due to a bug after spending time and money using it without being aware of this, and on top of that having no official response to multiple threads on this issue for months on end?

    We already ripped it out of one project, it would be nice to know if we should pretend the VideoPlayer doesn't exist on Android for any foreseeable projects as well. At this point in time, I have to assume the answer is "yes".
     
  12. apuyanam

    apuyanam

    Joined:
    Aug 10, 2017
    Posts:
    2
    @DGordon
    I am having the same problem in android, I am developing an VR app and the videos are killing my framerate.
    What system did you used to replace Unity VideoPlayer?
     
  13. DGordon

    DGordon

    Joined:
    Dec 8, 2013
    Posts:
    352
    We replaced it with Timeline. We used 2 layers, one to sequence the images in an animation and one for the audio.
     
  14. vectorCharlie_f

    vectorCharlie_f

    Joined:
    Sep 12, 2017
    Posts:
    10
    @DGordon I'm also interested in this workaround. Could you please tell me a little bit more about how to setup the image sequence on the timeline.
    Do you use the timeline to change the texture on a material every frame?
    Do you have a folder with a jpg sequence instead of a video file?

    Thank you!
     
  15. DGordon

    DGordon

    Joined:
    Dec 8, 2013
    Posts:
    352
    Yeah its as simple as it sounds. I used a timeline to change the texture on a UI Image (out specific use-case was in UGUI).
     
  16. HanSoloYolo

    HanSoloYolo

    Joined:
    May 22, 2017
    Posts:
    19
    Apologies, but could you explain the process to someone who has never used Timeline?

    I didn't even know Timeline was a Unity tool. I cannot find any reference material online that teaches me to accomplish what you are referring to. I am creating an Augmented Reality app, just for fun & learning, and playing videos reduces the framerate horribly.

    Please guide me through the process. :)
     
  17. atorisa

    atorisa

    Joined:
    Dec 1, 2013
    Posts:
    107
    2019 year. It still freeze iOS app when changing videoclips (with Prepare() or without). Any Progress on this?
     
  18. kilik128

    kilik128

    Joined:
    Jul 15, 2013
    Posts:
    810
    got this here

    VideoPlayer cannot play
    UnityEngine.Video.VideoPlayer:prepare()