# Streaming video support

The GVR SDK for Unity includes an additional GVR video plugin that supports
streaming flat and 360° videos in both mono and stereo formats by using the
ExoPlayer library to handle decoding and rendering of video, audio, and related
streams. ExoPlayer provides all the standard playback framework for both videos
embedded in your application and streaming videos, including adaptive streaming
support, such as DASH and HLS.

> [!NOTE]
> **Note:** This plugin supports Daydream only.

## Configuring your video player

The GVR SDK for Unity provides a C# script, called `GvrVideoPlayerTexture`, that
allows you to configure your video player. The script renders the video image
into a texture created in Unity. The texture can then be placed on any mesh
renderer in the scene.

To use the script, add it to a GameObject with a Mesh Renderer component. At
runtime, the script creates another texture and uses that as the main texture of
the renderer.

### Player properties

The `GvrVideoPlayerTexture` script allows you to adjust the following properties:

![](https://developers.google.com/static/vr/images/video/video-script-properties.png)

- **Status Text**: Allows you to put in a text component that can display textual information like framerate and resolution.
- **Buffer Size**: Determines the buffer size, with a minimum value of 3 and a maximum value of 15.
- **Video Type** : Determines the video type. The options are:
  - Dash
  - HLS
  - Other (used for local video)
- **Video URL**: The video file's location.
- **Video Content ID**: The video file's Content ID.
- **Video Provider ID**: The video file's Provider ID.
- **Initial Resolution** : The target resolution for the video. The options are:
  - Lowest (Sets the video to the lowest possible resolution.)
  - 720
  - 1080
  - 2048
  - Highest (Sets the video to the highest possible resolution.)
- **Adjust Aspect Ratio**: If this box is checked, the size of the video player object will be adjusted to match the video's aspect ratio. Only applies to flat videos.

## Examples

These examples demonstrate how to build a simple video player within VR.

### Prerequisites

- [Google VR SDK for Unity](https://developers.google.com/vr/unity/download#google-vr-sdk-for-unity)
- [Unity 5.6](https://unity3d.com/get-unity/download) or newer

### Setting up your scene

The following steps set up the Daydream controller support, which all the video
player examples require.

1. Create a new 3D Unity Project.
2. [Configure the build settings to enable Daydream
   support.](https://developers.google.com/vr/unity/get-started#configure_build_settings)
3. Import the GVR SDK for Unity.
   1. Under the **Assets** menu, select **Import Package** , then **Custom
      Package**, then navigate to the Unity GVR SDK and select it.
4. Import the VideoPlayer SDK.
   1. In the **Project** panel, find the GVRVideoPlayer package located in the GoogleVR folder. Double-click the package to import it.
5. Enable support for the Daydream controller and UI.
   1. Add `GvrEditorEmulator` to the scene, located under GoogleVR/Prefabs.
   2. Add `GvrControllerMain` to the scene, located under GoogleVR/Prefabs/Controller.
   3. Add `GvrControllerPointer`, located under GoogleVR/Prefabs/UI.
   4. Add `GvrReticlePointer`, located under GoogleVR/Prefabs/UI.
   5. Create an empty game object and name it EventSystem. Add an Event System component, and then attach the `GvrPointerInputModule` script.

### Flat Video

This example shows how to create a flat video playback using DASH with a video
hosted on Google Cloud Storage.

1. This example assumes you've run the steps in [Setting up your
   scene](https://developers.google.com/vr/develop/unity/video-overview#setting_up_your_scene).
2. Configure the main camera.
   1. Set the **Position** to (0, 1, 0).
   2. Set **Target Eye** to **both**.
3. Add the video player object.
   1. Create a **Quad** object (**Game Object \> 3D Object \> Quad**).
   2. Set the **Position** to (0,1,12)
   3. Set the **Scale** to (16,9,1) for a 16:9 aspect ratio.
4. Add the video material to the video player object. This is what's shown until the video loads.
   1. In the **Mesh Renderer** component, expand **Materials** and set **element 0** to be `VideoMaterial`, or `StereoMaterial` if the video is a stereoscopic video, located under GoogleVR/Demos/Materials/VideoDemo.
5. Add the `GvrVideoTexturePlayer` script to the quad, located under GoogleVR/Scripts/Video.
6. Set the properties in `GvrVideoTextureplayer` as follows:
   1. **Video Type**: Dash
   2. **Buffer size**: 4
   3. **Video URL**: https://storage.googleapis.com/wvmedia/clear/h264/tears/tears_hd.mpd
   4. **Video Content ID**: https://storage.googleapis.com/wvmedia/clear/h264/tears/tears_hd.mpd
   5. **Video Provider ID**: (leave blank)
7. Add the `VideoControls` prefab, located under GoogleVR/Demos/Prefabs/VideoDemo.
   1. Set the **Position** to be (0,0,3).
8. Attach the Video Player to the Video Controls.
   1. Under **Video Player Reference Script** , set **Player** to the video player object.
9. At this point, your scene should have all the components as shown in the
   screenshot below.

   ![](https://developers.google.com/static/vr/images/video/scene-with-video.png)

   Save the scene and open **File \> Build Settings**.
10. Add the current scene to the scene list and make sure it's the first
    scene enabled.

11. Press **Build \& Run** to run the example.

### Spherical Video

This example shows how to create a 360° video playback using DASH with a
video hosted on Google Cloud Storage. To do this, we create a large sphere with
the camera at the center and render the video on the inside of the sphere.

1. Run all the steps in [Setting up your scene](https://developers.google.com/vr/develop/unity/video-overview#setting_up_your_scene).
2. Configure the main camera.
   1. Set the **Position** to (0, 1, 0).
   2. Set **Target Eye** to **both**.
3. Add the video player object.
   1. Create a **Sphere** object (**Game Object \> 3D Object \> Sphere**).
   2. Set the **Position** to (0,0,0).
   3. Set the **Scale** to (12,12,12).
4. Add the video material to the video player object. This is what's shown until the video loads.
   1. In the **Mesh Renderer** component, expand **Materials** and set **element 0** to be `VideoStereoInside`, located under GoogleVR/Demos/Materials/VideoDemo.
5. Add the `GvrVideoTexturePlayer` script to the sphere, located under GoogleVR/Scripts/Video
6. Set the properties in the `GvrVideoTextureplayer` script as follows:
   1. **Video Type**: Dash
   2. **Buffer size**: 4
   3. **Video URL**: https://storage.googleapis.com/daydream-deveng.appspot.com/japan360/dash/japan_day06_eagle2_shot0005-2880px_40000kbps.mpd
   4. **Video Content ID**: (leave blank)
   5. **Video Provider ID**: (leave blank)
7. Add the `VideoControls` prefab, located under GoogleVR/Demos/Prefabs/VideoDemo
   1. Set the **Position** to be (0,0,3).
8. Attach the Video Player to the Video Controls.
   1. Under **Video Player Reference Script** , set **Player** to the video player object.
9. Save the scene and open **File \> Build Settings** .
   1. Add the current scene to the scene list and make sure it's the only scene enabled.
10. Press **Build \& Run** to run the example.

## Dealing with large video assets

Locally storing videos using Asset Manager is a viable option when your APK
file is under 100 MB, the maximum allowed file size for apps on the Google Play
Store, but it is not uncommon to have video assets exceeding this limit. To work
around this limit, the resources can be stored in an OBB file as follows:

1. Place your video asset in Assets/StreamingAssets. Files in this folder will
   be copied unchanged to the target machine, where it then will be available
   from a specific folder. For more information, see [Unity's documentation on Special
   Folders.](https://docs.unity3d.com/Manual/StreamingAssets.html)

2. Change the Video Texture Player properties to:

   1. **Video Type** : **Other**
   2. **Video URL**: jar:file://${Application.dataPath}!/assets/vid_bigbuckbunny.mp4
   3. **Video Content ID**: (leave blank)
   4. **Video Provider ID**: (leave blank)

   > [!NOTE]
   > **Note:** ${Application.dataPath} will be replaced at runtime by the actual value of Application.dataPath.

3. Open **Player Settings** . Under **Publishing Settings** check the **Split
   Application Binary** checkbox. This will create the OBB file.

4. When deploying the application locally, the OBB file is copied to the
   correct location automatically. See [this page on handling OBB files via the Play Store with
   Unity](https://docs.unity3d.com/Manual/android-OBBsupport.html).

## Switching video streams

To switch the video playing without destroying and creating a new TexturePlayer
component:

1. Set the video properties to the new stream on the `GvrVideoTexturePlayer` script, specifically, the **VideoType** , **VideoURL** , **VideoContentID** and **VideoProviderID**.
2. Call `TexturePlayer.CleanupVideo()`.
3. Call `TexturePlayer.ReinitializeVideo()`. This will create a new instance of ExoPlayer.

## Callbacks

### OnVideoEvent

Because initializing the player and loading the video stream are asynchronous
operations, it can be useful to have a callback when the video is ready. This is
an alternative to polling the VideoReady property in the Update method. You can
register a callback to be called when the video is ready by invoking
`GvrVideoTexturePlayer.OnVideoEventCallBack()`.

For example:

    Getcomponent<TexturePlayer>().SetOnVideoEventCallback(eventId) => {
        Debug.Log("Video is ready!")
        UpdateStatusText();
    );

The available eventIds are:

- VideoReady
- VideoStartPlayback
- VideoFormatChanged
- VideoSurfaceSet
- VideoSizeChanged

### OnException

When something goes wrong with the video playback, the player throws an
exception. A callback can be registered to be invoked when exceptions occur by
calling `GvrVideoTexturePlayer.SetOnExceptionCallback()`. For example:

    GetComponent<TexturePlayer>().SetOnExceptionCallback(
       (type, message) => {
            Debug.LogError("Exception of type: " + type + ": " + message);
       }
    );