Search Unity

Bug VP8+Vorbis encoded WEBM files from URL do not "prebuffer and play" via URL

Discussion in 'Formats & External Tools' started by Lhun, Feb 1, 2022.

  1. Lhun

    Lhun

    Joined:
    Oct 24, 2015
    Posts:
    3
    Unlike h.264 and other proprietary formats supported by Unity and other abstractions in Unity's VideoPlayer component, the following behavior:

    Setting the Video Player component source to URL can also be used to read videos from web sources via http:// and https://. In these cases, Unity performs the necessary pre-buffering and error management.

    https://docs.unity3d.com/2019.4/Documentation/Manual/Video.html

    does not seem to occur as described (in at least unity 2019.4.31f1), both in compiled scenes and in editor.

    This can cause significant delay and user storage issues in playback when accessing large videos, and worse, can result in NEVER playing an asset formatted for progressive realtime playback (without manifest - not dash), which is one reason why you would use URL mode in the first place. However, Unity's readonly diagnostic variables for VideoPlayer seem to indicate that the video is "isPrepped". Monitoring of traffic between the server and Unity seems to indicate the video is attempting to fully download before playing.

    As this is the only format really supported natively in Unity, especially on Linux (and WebGL, etc) builds (and even in via Valve proton) it prevents unity creators from making truly unified cross platform applications that don't require proprietary codec licensing if any large or streaming remote video access is needed without using a third party solution (of which there are very few for Linux and even less for other build targets as well)

    This actually does not adhere to the current webm standards either, even since prior to this version of unity. The current webm example parser can be found here at this github mirror:
    https://github.com/webmproject/libwebm/tree/main/webm_parser

    I've made a little script to try and discover what's going on here. Unity reports the video is "prepped" but never actually "plays" even though it reports it is, because it's downloading essentially forever. I've attached an image of the console log during "play" and the odd result for a progressive streaming webm vp8+vorbis.

    For all intents and purposes this is just a webm with a gigantic fixed duration that is being served locally, simply using VLC's built in HTTP(S) streaming to localhost: so bandwidth and prebuffer is a non-issue and not relevant to the discussion here.

    To be clear this does work on Windows with other codecs and containers like mp4 with h.264, but as I stated before, the intent is to avoid licensed codecs and use Unity's open source and native video format.

    This same video playback method works in all other native and web based playback applications (that are not Unity) that I've tried to play it in, including Window's 10 and 11's built in video player, Google's chrome and chromium with proprietary codecs stripped, chromebooks, firefox, apple iOS safari, VLC, on mobile phone and tablet arm64 devices, smart tvs, etc.

    What makes this even more unusual is that WebRTC (which Unity supports via an in-house package: https://docs.unity3d.com/Packages/com.unity.webrtc@2.4/manual/index.html) which uses vp8 (and vp9) software encode and decode on Linux to stream real-time video, so the engine is capable of it.



    Code (CSharp):
    1. public class videoplayer : MonoBehaviour
    2. {
    3.     public VideoPlayer vid;
    4.     void Start()
    5.     {
    6.        vid.Prepare();
    7.     }
    8.     void Update()
    9.     {
    10.         ulong stats = vid.frameCount;
    11.         bool vidprepped;
    12.         vidprepped = vid.isPrepared;
    13.  
    14.         if (vidprepped == true)
    15.         {
    16.             vid.Play();
    17.         }
    18.         if (vid.isPlaying == true)
    19.         {
    20.             float fr = vid.frameRate;
    21.             Debug.Log(fr);
    22.         }
    23.  
    24.         Debug.Log("Is the videoplayer prepped? "+vidprepped);
    25.         Debug.Log("Detected video Length "+stats);
    26.  
    27.     }
    Feed the URL a long duration webm, set autoplay to off. Observe that playback does not start before the file is fully cached in memory.

    The steps to create live a WEBM "stream" (my personal goal is to get this method playable in Unity) that behaves like the above with VLC are as follows*:
    *You could also use ffmpeg to do create a stream like this with hardware encoding, but it's a bit more involved, and you would need to provide your own server for the url.

    1) Press CTRL+S
    2) Choose a capture device and stream your desktop or a webcam (you could convert from a file here but the transcode process is software based, and even more expensive - we're avoiding latency)
    3) Click "stream"
    4) Click Next, then under "new destination" choose HTTP and click "add"
    5) In the path, put something like /test.webm (the extension must be .webm or vlc will not encode)
    6) in profile, choose Video - VP80 + Vorbis (note, this is apparently fully natively supported by Unity!)
    7) click the wrench next to the profile. In the Encoding parameters reduce the bitrate to 1000 kb/s or something equally easy on your computer. Choose something reasonable like 30fps for the frame rate. In the resolution tab, choose something super small like 256x144.
    *We're doing it this way to make sure vlc is unlikely to drop frames for this test
    8) make sure "activate transcoding" is enabled.
    9) click stream.

    Make sure your stream is working by opening it in a browser or any other app that plays webm by going to

    http://localhost:8080/test.webm

    then try it in the video player in unity.

    Any feedback/testing is appreciated!
     
    Last edited: Feb 1, 2022