Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Video Player custom playable

Discussion in 'Timeline' started by Solovykh, Jan 9, 2018.

  1. Solovykh

    Solovykh

    Joined:
    Aug 28, 2017
    Posts:
    59
    I'm trying to write a custom playable that allows me to scrub the timeline to scrub the video inside the video player. I have this.

    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3. using UnityEngine.Playables;
    4. using UnityEngine.Video;
    5.  
    6.  
    7. [Serializable]
    8. public class TheaterPlayableBehavior : PlayableBehaviour
    9. {
    10.     private GameObject m_Theater;
    11.  
    12.     private VideoPlayer m_VideoPlayer;
    13.  
    14.     public GameObject theater
    15.     {
    16.         set { m_Theater = value; }
    17.     }
    18.  
    19.     public override void OnGraphStart(Playable playable)
    20.     {
    21.         m_VideoPlayer = m_Theater.GetComponentInChildren<VideoPlayer>();
    22.         m_VideoPlayer.Prepare();
    23.     }
    24.  
    25.     public override void PrepareFrame(Playable playable, FrameData info)
    26.     {
    27.         m_VideoPlayer.time = playable.GetTime();
    28.  
    29.     }
    30.  
    31. }
    32.  
    33. [Serializable]
    34. public class TheaterClip : PlayableAsset
    35. {
    36.     public ExposedReference<GameObject> theater;
    37.  
    38.     public override Playable CreatePlayable(PlayableGraph graph, GameObject go)
    39.     {
    40.         ScriptPlayable<TheaterPlayableBehavior> playable = ScriptPlayable<TheaterPlayableBehavior>.Create(graph);
    41.  
    42.         playable.GetBehaviour().theater = theater.Resolve(graph.GetResolver());
    43.         return playable;
    44.     }
    45. }
    46.  
    47.  
    48.  
    For some reason the playback is really choppy. Is there a way to sync the video player playback to the timeline playback?
     
  2. customphase

    customphase

    Joined:
    Aug 19, 2012
    Posts:
    245
    2018.3.1 still has issues with timeline and custom playables, mainly some events not firing properly, and official video player playable from "default playables" pack (https://assetstore.unity.com/packages/essentials/default-playables-95266) doesnt work as well.
    I managed to modify the code above to make it work. The scrubbing/seeking is not instant, but otherwise things work fine.

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.Playables;
    4. using UnityEngine.Video;
    5.  
    6. [System.Serializable]
    7. public class TheaterPlayableBehavior : PlayableBehaviour
    8. {
    9.     [SerializeField]
    10.     private GameObject m_Theater;
    11.     [SerializeField]
    12.     private VideoPlayer m_VideoPlayer;
    13.  
    14.     FrameData.EvaluationType lastEval;
    15.  
    16.     public GameObject theater
    17.     {
    18.         set { m_Theater = value; }
    19.     }
    20.  
    21.     public override void OnGraphStart(Playable playable)
    22.     {
    23.         m_VideoPlayer = m_Theater.GetComponentInChildren<VideoPlayer>();
    24.         m_VideoPlayer.Prepare();
    25.     }
    26.  
    27.     public override void PrepareFrame(Playable playable, FrameData info)
    28.     {
    29.         if (info.evaluationType == FrameData.EvaluationType.Evaluate)
    30.         {
    31.             m_VideoPlayer.Prepare();
    32.             m_VideoPlayer.time = playable.GetTime();
    33.             m_VideoPlayer.Pause();
    34.         }
    35.         if (lastEval==FrameData.EvaluationType.Evaluate && info.evaluationType==FrameData.EvaluationType.Playback)
    36.         {
    37.             m_VideoPlayer.Play();
    38.         }
    39.         if (info.evaluationType == FrameData.EvaluationType.Playback)
    40.         {
    41.             m_VideoPlayer.time = playable.GetTime();
    42.         }
    43.         lastEval = info.evaluationType;
    44.     }
    45.  
    46.     public override void OnBehaviourPause(Playable playable, FrameData info)
    47.     {
    48.         base.OnBehaviourPause(playable, info);
    49.         if (m_VideoPlayer)
    50.         {
    51.             m_VideoPlayer.Prepare();
    52.             m_VideoPlayer.time = playable.GetTime();
    53.             m_VideoPlayer.Pause();
    54.         }
    55.         lastEval = FrameData.EvaluationType.Evaluate;
    56.     }
    57.  
    58. }
    59.  
     
    jilleJr likes this.
  3. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    First off, thanks for the post, that is definitely an improvement on the video player.

    Second, can you be more specific about what is not firing properly?
     
  4. customphase

    customphase

    Joined:
    Aug 19, 2012
    Posts:
    245
    Sure thing. Basically OnBehaviourPlay doesnt fire if you seek to anywhere on the timeline and then press play. It only fires if you follow these steps:
    1) start playback
    2) pause by pressing play button
    3) press the play button again to resume.

    Any other way it wont fire at all.

    Also frameData.seekOccured always returns true, even when you are not seeking - i.e. when you are simply playing timeline, and even in the game mode. Thats why i had to resort to using evaluationType and comparing it against last known evaluationType manually.
     
  5. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    Ah thanks - yes, OnBehaviourPlay is a misleading name. In timeline, it's more of active state for timeline. The bug is the OnBehaviourPause getting called when the graph is paused, but the playable is still active - we added an
    effectivePlayState to the frame data so you can check for that case in OnBehaviourPause. Not the ideal fix, but one that won't break every custom playable already out there. OnBehaviourPause gets called when one of three cases happens - the graph is paused, the playable is paused (i.e. disabled) or a parent node in the graph is 'paused'. The effectivePlaystate will be Playing if the playable and it's parents are active.

    frameData.seekOccured always returns true because timeline is aggressively setting the local time on all (clip) playables each frame, causing them to be 'seeked'. The evaluation type is the correct way to check, especially since 2018.2, where the graphs actually play in the editor (2018.1 and prior it was just faked via scrubbing).
     
    customphase likes this.
  6. kilik128

    kilik128

    Joined:
    Jul 15, 2013
    Posts:
    909
    somethinks working ?
     
  7. jbergs

    jbergs

    Joined:
    Feb 13, 2014
    Posts:
    26
    I'm actually curious too if it's in the pipeline to update the "default playable" example, or something integrated to add Video tracks to the timeline?
     
  8. seant_unity

    seant_unity

    Unity Technologies

    Joined:
    Aug 25, 2015
    Posts:
    1,516
    It's in the pipeline yes, but not scheduled for release in the near future.
     
    jbergs likes this.
  9. Goyoman

    Goyoman

    Joined:
    Jun 16, 2015
    Posts:
    10
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.Timeline;
    5. using UnityEngine.Video;
    6.  
    7. public class ITimeControlVideoPlayer : MonoBehaviour, ITimeControl
    8. {
    9.     [SerializeField] VideoPlayer videoPlayer;
    10.  
    11.     void Awake ()
    12.     {
    13.         videoPlayer.Prepare ();
    14.     }
    15.  
    16.     public void OnControlTimeStart ()
    17.     {
    18.         videoPlayer.Play ();
    19.     }
    20.  
    21.     public void OnControlTimeStop ()
    22.     {
    23.         videoPlayer.Pause ();
    24.     }
    25.  
    26.     public void SetTime (double time)
    27.     {
    28.         videoPlayer.time = time;
    29.     }
    30. }
    This works in 2019.1
     
  10. ibyte

    ibyte

    Joined:
    Aug 14, 2009
    Posts:
    1,047
    I was adding this class to a videoplayer and setting up 3 UI controls. I am able to hook up OnControlTimeStart and OnControlTimeStop to the button events which work but SetTime does not show up in the list?

    Update: Cannot seem t use doubles from the event UI. Floats show up.
     
    Last edited: Jun 30, 2019
  11. KristofferH

    KristofferH

    Joined:
    Oct 27, 2012
    Posts:
    52
    @Goyoman Thank you for your work. How is this script intended to be used? Do I have to modify the Default Playables video script from Unity to actually call these functions or do I just drop it on a GameObject and assign my VideoPlayer into the field?
     
  12. KristofferH

    KristofferH

    Joined:
    Oct 27, 2012
    Posts:
    52
    Hi @customphase I've tried using these modification of yours with the code above. But every time I scrub the timeline the reference to m_videoPlayer gets lost and is set to null. It works in OnGraphStart as it should, but then in PrepareFrame suddenly m_videoPlayer is null again and I get an error message. Any idea on why that is, and how to fix it? Thanks! :)