- Home /
Retrieving and playing a video file stored locally on an android VR headset (Oculus Quest)
I am in the midst of making some prototypes that require me to play large video files from a unity application (10gb+). These are 360 videos that will be played in a hospital environment and therefore I am hard pressed to simply upload these videos to a server as I am doing now and streaming them. The Hospital does not allow downloads like these and the connection is not good enough to stream it effectively.
My solution to this is to add the videos to the headset manually and then simply play them from the unity application by fetching them by code as I will know where they are stored. Alas, I cannot seem to get this to work.
I have attempted to put the videos in the streaming assets folder but unity cannot even build when trying this as I get java heap space problems I have furthermore added the permissions to the Android manifest so it should have permission to fetch the video.
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
I am wondering if there is anyone that has experience with this sort of thing that would kindly shed some light on how to go about placing a video file locally in the headset (most likely in the com.< companyname>.< applicationname> folder or "persistent path" ) and then playing it from script or from the videoplayer Url/Path.
thanks kindly.
Unity 2019.2 0b1
I am trying this method and I only get a green screen when I play. It is definitely finding the video. It should not be a codec issue as the same video works if I assign the file directly to the videoplayer in unity ins$$anonymous$$d of loading through URL from storage. Not sure what to try next.
Answer by SteenPetersen · Jun 06, 2019 at 03:57 PM
Fixed this like so:
_vp = GetComponent<VideoPlayer>();
_vp.errorReceived += VideoPlayer_errorReceived;
if (Application.platform == RuntimePlatform.Android)
{
rootPath = Application.persistentDataPath.Substring(0, Application.persistentDataPath.IndexOf("Android", StringComparison.Ordinal));
path = Path.Combine(Path.Combine(rootPath, "Android/Data/_Videos"), fileName);
}
if (File.Exists(path))
_debugText.text += "\nFile has been found!\n\n";
_vp.url = path;
_vp.Play();
private void VideoPlayer_errorReceived(VideoPlayer source, string message)
{
/// So that I can see the debug message in the headset in my case
_debugText.text += message;
/// To avoid memory leaks, unsubscribe from the event
/// otherwise it could continuously send this message
_vp.errorReceived -= VideoPlayer_errorReceived;
}
Hi! I've been facing the same issue as you, and my Quest is able to find the correct video file with the android rootpath. However the native video player (exoplayer) is unable to play the video for some reason, I'll like to know if you were able to successfully play your video:)
Here's how my code looks like
string rootPath = Application.persistentDataPath.Substring(0, Application.persistentDataPath.IndexOf("Android", StringComparison.Ordinal));
string path = Path.Combine(Path.Combine(rootPath, "Android/Data/_Videos"), fileName);
if (File.Exists(path))
{
Debug.Log("path found");
}
else
{
Debug.Log("path not found");
}
Play(path);
}
public void Play(string moviePath)
{
if (moviePath != string.Empty)
{
Debug.Log("Playing Video: " + moviePath);
if (overlay.isExternalSurface)
{
OVROverlay.ExternalSurfaceObjectCreated surfaceCreatedCallback = () =>
{
Debug.Log("Playing ExoPlayer with SurfaceObject");
NativeVideoPlayer.PlayVideo(moviePath, overlay.externalSurfaceObject);
};
if (overlay.externalSurfaceObject == IntPtr.Zero)
{
overlay.externalSurfaceObjectCreated = surfaceCreatedCallback;
}
else
{
surfaceCreatedCallback.Invoke();
}
}
else
{
Debug.Log("Playing Unity VideoPlayer");
videoPlayer.url = moviePath;
videoPlayer.Prepare();
videoPlayer.Play();
}
Debug.Log("$$anonymous$$ovieSample Start");
isPlaying = true;
}
else
{
cube.SetActive(false);
Debug.LogError("No media file name provided");
}
}
Thank you so much!
Answer by Bettaxis · Oct 02, 2019 at 09:02 PM
@SteenPetersen your answer really helped me with the project I am working on. In the same vein of large 360 videos that are played through a Unity App for the Quest. I was not able to build .apks with the videos linked natively in the Unity VideoClip component as the .apk would be too huge and would result in Gradle errors, with this method, I just manually place the video files and link them using the URL, while excluding the videos from the actual Build and Project which results in a much smaller .apk that is easier to deploy.
I modified your code and used this variation, along with the Android Manifest permission additions.
VideoPlayer video;
private string rootPath;
private string path;
private string fileName = "NameOfYourVideo.mp4";
void Awake()
{
video = FindObjectOfType<VideoPlayer>();
video.errorReceived += VideoPlayer_errorReceived;
if (Application.platform == RuntimePlatform.Android)
{
rootPath = Application.persistentDataPath;
path = Path.Combine(rootPath, fileName);
}
video.url = path;
video.Play();
}
This in the URL leads to the path in the Quest at "Internal shared storage\Android\data\com.CompanyName.ProjectName\files" where I placed the large videos I needed and with this method you can also update the filename in a script to change/load different videos.
As for your question in https://answers.unity.com/questions/1638368/android-build-videoplayer-cannot-read-mp4-file.html , I encountered that error as well and I was able to resolve it by making sure the target was in the com.CompanyName.ProjectName\Files instead of the Android\Data_Videos that you placed them in. I think this has to do with how Unity accesses files at runtime (see here), putting it in the com. folder makes it work! Note that Above ~3GB videos don't seem to play on the Quest and I am unsure as to if it's a Quest limitation due to the 4GB of RAM or a Unity issue at this time. However, smaller 360 videos do work!
So it looks like the file size is another limiting factor for the Quest. I can only play files under 3GB and anything larger does not play.
This worked for me (Unity 2020.1.9f). Only difference is that I didn't manipulate any manifest files directly. Instead I just went into (Unity) Player Settings and changed Write Permission to "External (SDCard") and that proved sufficient. Now playing a 2.8GB 5K stereoscopical .mp4 video on the Quest 2 without problem.
Answer by bhupiister · Oct 08, 2020 at 12:33 AM
@SteenPetersen Drag video component from inspector. Please see video on how to how to set raw image and render texture before playing videos on unity, you will find plenty of those
private string rootPath;
public VideoPlayer video; //Drag video component
private string path;
public Button PlayButton; //Drag button from inspector
public InputField fileName; //Drag Input field from inspector
void Awake()
{
video.playOnAwake = false;
}
void Update()
{
if (video.isPlaying)
{
PlayButton.interactable = false;
}
else
{
PlayButton.interactable = true;
}
}
public void PlayVideo() //Function assigned to play button
{
if (fileName.text.Length > 0)
{
Debug.Log("Persistent data path" + Application.persistentDataPath);
rootPath = Application.persistentDataPath;
path = Path.Combine(rootPath, fileName.text + ".mp4");
//}
if (File.Exists(path))
{
video.url = path;
video.Play();
}
else
{
Debug.Log("File not found, please check file name!");
}
}
else
{
Debug.Log("Please enter file name");
}
}
Your answer
Follow this Question
Related Questions
Android build - videoplayer - cannot read .mp4 file 1 Answer
Using URL as Source In Video Player on Portable VR 1 Answer
Video system / rendering is stuck on Android OculusGO 0 Answers
Android Post build to set android:launchMode="standard" 0 Answers
Problems Building a project for Oculus Quest and Android Phone 1 Answer