0
\$\begingroup\$

I am attempting to integrate a video function which will playback short looping videos (similar to YouTube Shorts or TikTok). I therefore want the videos to download to PersistentDataPath and be played from there (rather than directly off the web) so that they are not continually consuming data/Internet resources every time you re-access them.

I would also like the videos to be able to play back while downloading rather than waiting until completion. This is the part I'm having trouble with.

Code such as the following works well for downloading the video and then playing it back:

IEnumerator StartNewVideo(){

        fileName = "VideoName.mp4";
        fileURL = "https://www.website.com/" + fileName;

        UnityEngine.Networking.UnityWebRequest www = UnityEngine.Networking.UnityWebRequest.Get(fileURL); 

        yield return www.SendWebRequest();

        if (www.result == UnityEngine.Networking.UnityWebRequest.Result.ConnectionError || www.result == UnityEngine.Networking.UnityWebRequest.Result.ProtocolError) {
                Debug.Log(www.error);
            }
            else {
                System.IO.File.WriteAllBytes(Application.persistentDataPath + "/VideoCache/" + fileName, www.downloadHandler.data);
            }
        }

        videoPlayer.url = Application.persistentDataPath + "/VideoCache/" + fileName;
        videoPlayer.Prepare();
        yield return new WaitUntil(() => videoPlayer.isPrepared);
        videoPlayer.Play();

        www.Dispose();
}

The trouble is I cannot figure out a working method to playback while the downloading is in progress.

I tried crudely something like this:

        UnityEngine.Networking.UnityWebRequest www = UnityEngine.Networking.UnityWebRequest.Get(fileURL); 
            www.SendWebRequest();
            while (www.result == UnityEngine.Networking.UnityWebRequest.Result.InProgress) {
                if (www.downloadHandler.data != null) {
                    System.IO.File.WriteAllBytes(Application.persistentDataPath + "/VideoCache/" + fileName, www.downloadHandler.data);
                    if (www.downloadProgress > 0.05f) {
                        if (!videoPlayer.isPrepared) {
                            videoPlayer.url = Application.persistentDataPath + "/VideoCache/" + fileName;
                            videoPlayer.Prepare();
                            yield return new WaitUntil(() => videoPlayer.isPrepared);
                            videoPlayer.Play();

                        }
                    }
                    
                }
                yield return null;

            }

The idea is to start preparing and playing back the video as soon as at least 5% has been downloaded. However, as soon as it attempts to start playback it gives a IOException: Sharing Violation on path presumably because it can't write data to the file and playback video from it at the same time.

There is also likely an inefficiency here because I am running System.IO.File.WriteAllBytes every time rather than just adding to the end of the file as new data becomes available.

Is there any solution that might make this work? Any ideas? Or is this basically going to be impossible? Thanks.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Is the format you have able to stream itself? You can't just take a random file type and expect it to work with only % of the total file \$\endgroup\$
    – Zibelas
    Jun 23 at 9:59
  • \$\begingroup\$ That's a good question Zibelas. I didn't think of that issue. I would be using MP4 files. Haven't decided on final encoding method. From the threads I see on Unity forum, it looks like the only solution at least previously to this issue is to simultaneously (1) Stream it from the web URL to the video player and (2) Download it at the same time so you can read from the download on subsequent playback. This unfortunately means downloading it twice though unless there is some other solution. I wonder if there is a manual workaround to stream it from the disc as you download it though. \$\endgroup\$
    – mike
    Jun 23 at 10:24
  • 1
    \$\begingroup\$ I have never done something like that before, but my approach would be to try to use the VideoPlayer component's build-in ability to play videos from http:// url's (including starting playback before the file is completely loaded) and then try to get the video data once it finished. \$\endgroup\$
    – Philipp
    Jun 23 at 11:56

0

You must log in to answer this question.

Browse other questions tagged .