在 Unity 项目中的 Gear VR 中播放大型视频文件

Playing large video files in Gear VR in Unity project

我正在创建一个 Gear VR android 应用程序来播放 30 分钟的大型视频。我读到我不应该使用 StreamingAssets 文件夹,但我没有看到任何关于我应该使用什么的信息。如果我将视频放在 Assets/videos 中,它不会包含在 android 构建中。我应该使用资源文件夹还是有其他方法来包含视频? (我的项目也在 iOS 上,但我目前在该平台上没有遇到任何问题。)

我了解到可以使用 PersistentDataPath 文件夹,但我不知道如何从 unity 将我的视频放入该文件夹。我不想在那里复制视频并且在只使用一个时有两个 600mb 文件。

Huge files can take a long time to extract and copy and sometimes they could even cause the device to run out of storage space or memory

这是事实,但你必须知道自己在做什么。您不能仅使用 WWW API 或仅使用 File.Copy/File.WriteAllBytes 函数复制文件。

1。分块复制视频然后播放。这消除了内存不足的问题。

bool copyLargeVideoToPersistentDataPath(string videoNameWithExtensionName)
{
    string path = Path.Combine(Application.streamingAssetsPath, videoNameWithExtensionName);

    string persistentPath = Path.Combine(Application.persistentDataPath, "Videos");
    persistentPath = Path.Combine(persistentPath, videoNameWithExtensionName);

    bool success = true;

    try
    {
        using (FileStream fromFile = new FileStream(path, FileMode.Open, FileAccess.Read))
        {
            using (FileStream toFile = new FileStream(persistentPath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
            {
                byte[] buffer = new byte[32 * 1024];
                int bytesRead;
                while ((bytesRead = fromFile.Read(buffer, 0, buffer.Length)) != 0)
                {
                    toFile.Write(buffer, 0, bytesRead);
                }
                Debug.Log("Done! Saved to Dir: " + persistentPath);
                Debug.Log(videoNameWithExtensionName + " Successfully Copied Video to " + persistentPath);
                text.text = videoNameWithExtensionName + " Successfully Copied Video to " + persistentPath;
            }
        }
    }
    catch (Exception e)
    {
        Debug.Log(videoNameWithExtensionName + " Failed To Copy Video. Reason: " + e.Message);
        text.text = videoNameWithExtensionName + " Failed To Copy Video. Reason: " + e.Message;
        success = false;
    }

    return success;
}

I don't want to copy the video there and have two 600mb files when only one is used.

您还有其他选择:

2 folder. (Not recommended) as this will slow down your game loading time. Worth mentioning. With the new Unity ,你可以这样加载视频:

VideoClip video = Resources.Load("videoFile", typeof(VideoClip)) as VideoClip;

不需要 AVPro 插件,在 Unity 中也不再需要。


如果需要,您也可以将 Resources 文件夹与 AVPro 插件一起使用。

只需将视频扩展名更改为 .bytes,然后将其作为字节加载。如果 AVPro 插件可以按字节播放视频,那你就可以了!

TextAsset txtAsset = (TextAsset)Resources.Load("videoFile", typeof(TextAsset));
byte[] videoFile = txtAsset.bytes;

3.使用AssetBundle加载视频。过去新视频 API 发布时不支持此功能,但现在应该支持。

IEnumerable LoadObject(string path)
{
    AssetBundleCreateRequest bundle = AssetBundle.LoadFromFileAsync(path);
    yield return bundle;

    AssetBundle myLoadedAssetBundle = bundle.assetBundle;
    if (myLoadedAssetBundle == null)
    {
        Debug.Log("Failed to load AssetBundle!");
        yield break;
    }

    AssetBundleRequest request = myLoadedAssetBundle.LoadAssetAsync<GameObject>("VideoFile");
    yield return request;

    VideoClip clip = request.asset as VideoClip;
}

4。最后,使用 StreamingAssets 文件夹,而不是复制视频,创建一个 本地服务器 HttpListener 并将其指向 StreamingAssets 路径。

现在,连接到新 并播放视频。您可以在 Whosebug 上找到许多 HttpListener 服务器的示例。 我以前这样做过,而且很有效。

我发现这是一种下载文件并将其保存到 PersistantDataPath 的方法。 http://answers.unity3d.com/questions/322526/downloading-big-files-on-ios-www-will-give-out-of.html

我看到的一个问题是,如果应用程序被暂停。 (例如取下耳机。) 下载失败。对于 650MB 的文件,基本上所有用户都可能会发生这种情况。您知道如何在 unity 暂停时继续下载吗?我也打算为此做一个新的post。

这是我现在要使用的代码。

 void DownloadFile()
{
    loadingBar.gameObject.SetActive(true);
    downloadButton.SetActive(false);
    downloadingFile = true;
    WebClient client = new WebClient();
    client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
    client.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(DownloadFileCompleted);
    client.DownloadFileAsync(new Uri(url), Application.persistentDataPath + "/" + fileName);
}

void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
    double bytesIn = double.Parse(e.BytesReceived.ToString());
    double totalBytes = double.Parse(e.TotalBytesToReceive.ToString());
    double percentage = bytesIn / totalBytes * 100;
    downloadProgressText = "Downloaded " + e.BytesReceived + " of " + e.TotalBytesToReceive;
    downloadProgress = int.Parse(Math.Truncate(percentage).ToString());
    totalBytes = e.TotalBytesToReceive;
    bytesDownloaded = e.BytesReceived;
}

void DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
    if (e.Error == null)
    {
        AllDone();
    }
}

void AllDone()
{
    Debug.Log("File Downloaded");
    FileExists = 1;
}

public void DeleteVideo()
{
    print("Delete File");
    PlayerPrefs.DeleteKey("videoDownloaded");
    FileExists = 0;
    enterButton.SetActive(false);
    downloadButton.SetActive(true);
    File.Delete(Application.persistentDataPath + "/" + fileName);
}