I'm creating a Gear VR android app that plays a large 30 minute video. I have read that I should not use the StreamingAssets folder, but I don't see any information about what I should be using instead. If I put the video in Assets/videos it is not included in the android build. Should I be using the resources folder or is there another way to include the video? (My project is also on iOS, but I'm currently not having any problems on that platform.)
I have read that the PersistentDataPath folder can be used, but I don't know how to get my video into that folder when from unity. I don't want to copy the video there and have two 600mb files when only one is used.
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
This is true but you have to know what you are doing. You can't just copy the file with the WWW
API or with just File.Copy
/File.WriteAllBytes
function.
1.Copy the video in chunks then play it. This removes the out-of memory issue.
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.
Here are other options you have:
2. The Resources folder. (Not recommended) as this will slow down your game loading time. Worth mentioning. With the new Unity VideoPlayer
, you can load video like this:
VideoClip video = Resources.Load("videoFile", typeof(VideoClip)) as VideoClip;
AVPro plugin is not required for this and is no longer needed in Unity.
You may also be able to use the Resources folder with the AVPro plugin if that's what you want.
Just change the video extension to .bytes
then load it as bytes. If AVPro plugin can play video as bytes then there you go!
TextAsset txtAsset = (TextAsset)Resources.Load("videoFile", typeof(TextAsset));
byte[] videoFile = txtAsset.bytes;
3.Use AssetBundle to load the video. This was not supported in the past when the new Video API came out but should now be supported.
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.Finally, use StreamingAssets
folder but instead of copying the video, create a local server with HttpListener
and point it to the StreamingAssets
path.
Now, connect to with with the new VideoPlayer
and play the video. You can find many examples of HttpListener
server on stackoverflow. I have done this in the past and it worked.