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

Everyplay - Help with rendering a Video Thumbnail to a sprite

Discussion in 'Unity Everyplay' started by JayCally80, Sep 9, 2014.

  1. JayCally80

    JayCally80

    Joined:
    Aug 6, 2014
    Posts:
    38
    Need some Everyplay help.

    Trying to rendering a video thumbnail to a sprite. I was trying to figure it out on my own but am so failing at it. I contacted Everyplay support and they point me back to the docs and said to check out "Rendering Thumbnail to a Texture", then use Sprite.Create to get a sprite from that Texture. I'm still unsure on how to do this. I thought I could use EveryplayThumbnailPool.cs from the "Helper scripts" folder to capture a thumbnail automatically during game play. But don't know how to set it to a sprite.

    I have a gameobject (EveryplayScreen) with a sprite renderer attached to it with the Sprite set to none. I want to set the Sprite to the Everyplay thumbnail.

    Please help! Its driving me crazy.
     
  2. JayCally80

    JayCally80

    Joined:
    Aug 6, 2014
    Posts:
    38
    After some research and going through the EveryplayThumbnailPool.cs, I think I'm making some progress on this. The script is getting the texture array from the EveryplayThumbnailPool.cs using the first texture for the Sprite.Create. I am getting an error on the last line of code though.

    The error is:
    error CS0119: Expression denotes a `method group', where a `variable', `value' or `type' was expected


    From the Sprite.Create doc entry, this should work. Can anyone tell me what I'm doing wrong?

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class EveryplayThumbnail : MonoBehaviour {
    5.  
    6.     private EveryplayThumbnailPool thumbnailPool;
    7.     private Texture2D everyplayTexture;
    8.  
    9.     void Awake() {
    10.         EveryplayThumbnailPool thumbnailPool = GetComponent<EveryplayThumbnailPool>();
    11.         everyplayTexture = thumbnailPool.thumbnailTextures[1];
    12.     }
    13.    
    14.     void Start() {
    15.        
    16.         //create a sprite and set it to the sprite renderer
    17.         GetComponent<SpriteRenderer>.sprite = Sprite.Create(everyplayTexture, new Rect(0,0,400,400), new Vector2(0,0), 1f);
    18.        
    19.     }
    20.    
    21. }
     
  3. JayCally80

    JayCally80

    Joined:
    Aug 6, 2014
    Posts:
    38
    Think I figured it out. Forgot to write .() after GetComponent<SpriteRenderer>

    Only problem is I can only test it on a mobile device and don't have my iOS developer account active. Waiting for some extra funds to sign up. Indie game dev problems. lol
     
  4. trinta

    trinta

    Unity Technologies

    Joined:
    Jun 5, 2013
    Posts:
    24
    Hi JayCally80,

    Just replied to you via email, but might as well post the solution here as well. While the approach is suitable, the EveryplayThumbnailPool script is mostly meant for situations where you want to take multiple screenshots, and hence it uses more memory.

    To render a thumbnail to a sprite, you should:
    1. Have Everyplay render the thumbnail to a texture
    2. Register a listener for the thumbnail to be ready
    3. Grab a screenshot with TakeThumbnail
    4. Create a Sprite with Sprite.Create from the texture
    5. ???
    6. Profit

    Some example code:

    Code (csharp):
    1.  
    2. /* First do the necessary preparations */
    3. // Our 100x100 thumbnail texture (size can be whatever you want)
    4. public Texture2D myThumbnailTexture;
    5.  
    6. public void Awake() {
    7.     myThumbnailTexture = new Texture2D(100,100);
    8. }
    9.  
    10. // Our thumbnail ready listener
    11. // Called when the thumbnail is available
    12. public void OnThumbnailReady() {
    13.     /* Here you can create a sprite from myThumbnailTexture */
    14. }
    15.  
    16. // Where ever you initialise, configure Everyplay to render the thumbnail to a texture
    17. public void MyGameRecordingInitStuff() {
    18.  
    19.     // Tell Everyplay to put the thumbnail to a texture
    20.     Everyplay.SetThumbnailTargetTextureId(myThumbnailtexture.GetNativeTextureID());
    21.     Everyplay.SetThumbnailTargetWidth(100);
    22.     Everyplay.SetThumbaillTargetHeight(100);
    23.  
    24.     // Add thumbnail take listener
    25.     Everyplay.ThumbnailReadyAtTextureId += OnThumbnailReady;
    26.  
    27.     // Thunderbirds are go!
    28.     Everyplay.StartRecording();
    29. }
    30.  
    And don't forget to use TakeThumbnail() to actually grab the thumbnail.

    Disclaimer: I have not tried this code out! Proceed at your own risk.
     
    Last edited: Sep 10, 2014
  5. pmjo

    pmjo

    Unity Technologies

    Joined:
    Sep 17, 2013
    Posts:
    245
    If you are using the default file based thumbnail instead of the texture based thumbnail you can do it like this:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class LastThumbnailSpriteFromFile : MonoBehaviour {
    5.  
    6.     private SpriteRenderer mSpriteRenderer;
    7.     private string mLastThumbnailPath = null;
    8.     private bool mThumbnailReady = false;
    9.  
    10.     void Awake() {
    11.         mSpriteRenderer = GetComponent<SpriteRenderer>();
    12.  
    13.         // Listen for recording started/stopped and thumbnail ready
    14.         Everyplay.ThumbnailReadyAtFilePath += ThumbnailReadyAtFilePath;
    15.         Everyplay.RecordingStarted += RecordingStarted;
    16.         Everyplay.RecordingStopped += RecordingStopped;
    17.      
    18.         // Start recording here.. or somewhere else.. did test with Everyplay test buttons..
    19.         //Everyplay.StartRecording();
    20.     }
    21.  
    22.     void RecordingStarted() {
    23.         mThumbnailReady = false;
    24.         mLastThumbnailPath = null;
    25.     }
    26.  
    27.     void ThumbnailReadyAtFilePath(string filePath) {
    28.         mLastThumbnailPath = filePath;
    29.         mThumbnailReady = true;
    30.     }
    31.  
    32.     void RecordingStopped() {
    33.         if(mThumbnailReady) {
    34.             if(mLastThumbnailPath != null) {
    35.                 Everyplay.LoadThumbnailFromFilePath(mLastThumbnailPath, ThumbnailLoaded, null);
    36.             }
    37.         }
    38.     }
    39.  
    40.     void ThumbnailLoaded(Texture2D texture) {
    41.         if(texture != null) {
    42.             // Create a sprite out of the texture
    43.             Sprite thumbnailSprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));
    44.          
    45.             // Set the new sprite to the sprite renderer
    46.             mSpriteRenderer.sprite = thumbnailSprite;
    47.         }
    48.     }
    49. }
    50.  
    Just drag and drop this script on your SpriteRenderer and it will automatically show the last thumbnail if it was available when the recording gets stopped.
     
    Last edited: Sep 10, 2014
  6. pmjo

    pmjo

    Unity Technologies

    Joined:
    Sep 17, 2013
    Posts:
    245
    If you want to use the texture thumbnail based approach instead you can do something like this:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class LastThumbnailSprite : MonoBehaviour {
    5.  
    6.     private Texture2D myThumbnailTexture;
    7.     private Sprite myThumbnailSprite;
    8.     private SpriteRenderer mySpriteRenderer;
    9.  
    10.     private bool thumbnailReady = false;
    11.     private int thumbnailWidth = 128;
    12.     private int thumbnailHeight = 128;
    13.  
    14.     void Awake() {
    15.         mySpriteRenderer = GetComponent<SpriteRenderer>();
    16.  
    17.         // Texture based thumbnail is always rendered in landscape
    18.         float aspectRatio = Screen.height / (float)Screen.width;
    19.         thumbnailHeight = Mathf.RoundToInt(thumbnailWidth * aspectRatio);
    20.  
    21.         // Create a texture for the thumbnail with screen aspect ratio
    22.         myThumbnailTexture = new Texture2D(thumbnailWidth, thumbnailHeight, TextureFormat.RGBA32, false);
    23.         myThumbnailTexture.wrapMode = TextureWrapMode.Clamp;
    24.  
    25.         // Set texture target
    26.         Everyplay.SetThumbnailTargetTextureId(myThumbnailTexture.GetNativeTextureID());
    27.         Everyplay.SetThumbnailTargetTextureWidth(thumbnailWidth);
    28.         Everyplay.SetThumbnailTargetTextureHeight(thumbnailHeight);
    29.  
    30.         // Set thumbnail ready callback
    31.         Everyplay.ThumbnailReadyAtTextureId += ThumbnailReadyAtTextureId;
    32.  
    33.         // Set recording started callback
    34.         Everyplay.RecordingStarted += RecordingStarted;
    35.         Everyplay.RecordingStopped += RecordingStopped;
    36.  
    37.         // Start recording here.. or somewhere else.. did test with Everyplay test buttons
    38.         //Everyplay.StartRecording();
    39.     }
    40.  
    41.     void RecordingStarted() {
    42.         mySpriteRenderer.sprite = null;
    43.  
    44.         // When using the texture target, TakeThumbnail is not called automatically
    45.         StartCoroutine(TakeThumbnail());
    46.     }
    47.  
    48.     void ThumbnailReadyAtTextureId(int textureId, bool portrait) {
    49.         if(textureId == myThumbnailTexture.GetNativeTextureID()) {
    50.             // You could update thumbnail here, however it might create lag during gameplay, do it after recording stopped instead
    51.             //UpdateSprite();
    52.         }
    53.     }
    54.  
    55.     void RecordingStopped() {
    56.         // Update sprite here
    57.         UpdateSprite();
    58.     }
    59.  
    60.     IEnumerator TakeThumbnail() {
    61.         // Take a thumbnail one second after recording started
    62.         yield return new WaitForSeconds(1.0f);
    63.  
    64.         Everyplay.TakeThumbnail();
    65.     }
    66.  
    67.     void UpdateSprite() {
    68.         // Create sprite out of texture (however it would be better to do this after recording is stopped because this might cause a small lag during gameplay)
    69.         myThumbnailSprite = Sprite.Create(myThumbnailTexture, new Rect(0, 0, thumbnailWidth, thumbnailHeight), Vector2.zero);
    70.      
    71.         // Set new sprite to the sprite renderer
    72.         mySpriteRenderer.sprite = myThumbnailSprite;
    73.     }
    74. }
    75.  
    Same idea, drag it on your SpriteRenderer. If your game is portrait you need to rotate it 90 degrees because in texture target based rendering Everyplay will always give the texture in landscape. Texture based thumbnail is not taken automatically so you need to call TakeThumbnail your self and in this example it will get called one second after recording is started. You may also need to play with Pixels To Units value to get it look good for your ui.
     
    Last edited: Sep 10, 2014
  7. JayCally80

    JayCally80

    Joined:
    Aug 6, 2014
    Posts:
    38
    Thanks @trinta and @pmjo. I was thinking of just grabbing the xth texture captured with EveryplayThumbnailPool.cs but, as trinta said, would use a lot more memory. I'm going to try your example. I have a trigger right before the boss fight. I could capture a thumb a few seconds after the trigger so it captures the boss fight which would be a more meaningful image for the player. This is my first product game and first time using Everyplay. Totally going to use it in other games.

    I'll post what I come up with incase others are looking for an example.
     
  8. umair_hassan

    umair_hassan

    Joined:
    Aug 14, 2014
    Posts:
    6
    Extremely exhausted... i couldn't even get how to get that thumbnail image, so that i can use it in ngui texture/sprite.
    An urgent help would be much appreciated... thanks
     
  9. pmjo

    pmjo

    Unity Technologies

    Joined:
    Sep 17, 2013
    Posts:
    245
    Sorry for the poor documentation of the Everyplay thumbnail API. These examples are old. There is no support for file based thumbnails anymore and instead of using Everyplay.SetThumbnailTargetTextureId you should be using Everyplay.SetThumbnailTargetTexture. The old way works only with OpenGL renderer but the new works also with Metal renderer (new iOS devices). You should also use Everyplay.ThumbnailTextureReady event instead of Everyplay.ThumbnailReadyAtTextureId.

    Here is the above script fixed by using the new thumbnail API instead:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.UI;
    4.  
    5. public class LastThumbnailSprite : MonoBehaviour
    6. {
    7.  
    8.     private Texture2D myThumbnailTexture;
    9.     private Sprite myThumbnailSprite;
    10.     private SpriteRenderer mySpriteRenderer;
    11.  
    12.     private bool thumbnailReady = false;
    13.     private int thumbnailWidth = 128;
    14.     private int thumbnailHeight = 128;
    15.  
    16.     void Awake ()
    17.     {
    18.         mySpriteRenderer = GetComponent<SpriteRenderer> ();
    19.  
    20.         // Texture based thumbnail is always rendered in landscape
    21.         float aspectRatio = Screen.height / (float)Screen.width;
    22.         thumbnailHeight = Mathf.RoundToInt (thumbnailWidth * aspectRatio);
    23.  
    24.         // Create a texture for the thumbnail with screen aspect ratio
    25.         myThumbnailTexture = new Texture2D (thumbnailWidth, thumbnailHeight, TextureFormat.RGBA32, false);
    26.         myThumbnailTexture.wrapMode = TextureWrapMode.Clamp;
    27.  
    28.         // Set texture target
    29.         Everyplay.SetThumbnailTargetTexture (myThumbnailTexture);
    30.  
    31.         // Set thumbnail ready callback
    32.         Everyplay.ThumbnailTextureReady += ThumbnailTextureReady;
    33.  
    34.         // Set recording started callback
    35.         Everyplay.RecordingStarted += RecordingStarted;
    36.         Everyplay.RecordingStopped += RecordingStopped;
    37.  
    38.         // Start recording here.. or somewhere else.. did test with Everyplay test buttons
    39.         //Everyplay.StartRecording();
    40.     }
    41.  
    42.     void RecordingStarted ()
    43.     {
    44.         mySpriteRenderer.sprite = null;
    45.  
    46.         // When using the texture target, TakeThumbnail is not called automatically
    47.         StartCoroutine (TakeThumbnail ());
    48.     }
    49.  
    50.     void ThumbnailTextureReady (Texture2D texture, bool portrait)
    51.     {
    52.         if (texture == myThumbnailTexture) {
    53.             // You could update thumbnail here, however it might create lag during gameplay, do it after recording stopped instead
    54.             // UpdateSprite ();
    55.         }
    56.     }
    57.  
    58.     void RecordingStopped ()
    59.     {
    60.         // Update sprite here
    61.         UpdateSprite ();
    62.     }
    63.  
    64.     IEnumerator TakeThumbnail ()
    65.     {
    66.         // Take a thumbnail one second after recording started
    67.         yield return new WaitForSeconds (1.0f);
    68.  
    69.         Everyplay.TakeThumbnail ();
    70.     }
    71.  
    72.     void UpdateSprite ()
    73.     {
    74.         // Create sprite out of texture (however it would be better to do this after recording is stopped because this might cause a small lag during gameplay)
    75.         myThumbnailSprite = Sprite.Create (myThumbnailTexture, new Rect (0, 0, thumbnailWidth, thumbnailHeight), Vector2.zero);
    76.  
    77.         // Set new sprite to the sprite renderer
    78.         mySpriteRenderer.sprite = myThumbnailSprite;
    79.     }
    80. }
    81.  
     
  10. In2Play

    In2Play

    Joined:
    Apr 25, 2016
    Posts:
    66
    Thanks for the code above. But I have a little problem on this one in my game. The game Im creating is only in portrait mode, but the thumbnail rendered is in landscape mode. So the captured result in the end is very bad. Is there any workaround for portrait games?
     
  11. pmjo

    pmjo

    Unity Technologies

    Joined:
    Sep 17, 2013
    Posts:
    245
    Can't you just increase the thumbnail resolution and rotate the sprite in your UI?
     
  12. NeilPopReach

    NeilPopReach

    Joined:
    May 19, 2016
    Posts:
    1
    Hi,

    Should the examples above still be working in 5.4.0 on iOS? I have been trying to capture a thumbnail, which I then need to resize and save out. Assigning the thumbnail to a UI.Image after calling CaptureThumbnail() does show the thumbnail. Manually trying to copy the thumbnail's texture2d pixels over to another texture2d or using Graphics.Blit to move to a render texture then readpixels to a new texture ends up giving a grey texture. The ThumbnailTextureReady callback never gets called either.

    Code (CSharp):
    1.   private void CaptureEveryplayThumbnail()
    2.     {
    3.         Debug.Log("Taking Thumbnail");
    4.         _ThumbnailTexture = new Texture2D(_ThumbnailCreator.ThumbnailWidth, _ThumbnailCreator.ThumbnailHeight);
    5.         Everyplay.ThumbnailTextureReady += ThumbnailTextureReady;
    6.         Everyplay.SetThumbnailTargetTexture(_ThumbnailTexture);
    7.         Everyplay.TakeThumbnail();
    8.  
    9.         //SetThumbnail(_ThumbnailTexture); //works here
    10.         Texture2D thumbnail = CopyEveryplayTexture(_ThumbnailTexture);
    11.         SetThumbnail(thumbnail); //grey here
    12.        
    13.     }
    14.  
    15.     public Texture2D CopyEveryplayTexture(Texture2D tex)
    16.     {
    17.  
    18.         Texture2D result = new Texture2D(tex.width, tex.height, TextureFormat.ARGB32, false);
    19.  
    20.         RenderTexture renderTexture = new RenderTexture(tex.width, tex.height, 0, RenderTextureFormat.ARGB32);
    21.  
    22.         RenderTexture oldActive = RenderTexture.active;
    23.         RenderTexture.active = renderTexture;
    24.         Graphics.Blit(tex, renderTexture, _EveryplayMaterial);
    25.  
    26.         result.ReadPixels(new Rect(0, 0, tex.width, tex.height), 0, 0);
    27.         result.Apply();
    28.         RenderTexture.active = oldActive;
    29.         return result;
    30.     }
     
  13. HaimBendanan

    HaimBendanan

    Joined:
    May 10, 2016
    Posts:
    28

    Did you solved this? I am in a similar problem. I am trying to rotate the texture because my game run in portrait, but it gives me a grey texture. If I don't rotate, the thumbnail is ok.
    I am creating a new texture when rotating using this code found on the net:
    public static Texture2D RotateTexture(this Texture2D texture, bool clockwise = true)
    {
    Texture2D target = new Texture2D(texture.height, texture.width, texture.format, false); //flip image width<>height, as we rotated the image, it might be a rect. not a square image
    target.wrapMode = texture.wrapMode;

    Color32[] pixels = texture.GetPixels32(0);
    pixels = rotateTextureGrid(pixels, texture.width, texture.height, clockwise);
    target.SetPixels32(pixels);
    target.Apply();
    return target;
    }

    private static Color32[] rotateTextureGrid(Color32[] tex, int wid, int hi, bool clockwise)
    {
    Color32[] ret = new Color32[wid * hi]; //reminder we are flipping these in the target

    for (int y = 0; y < hi; y++)
    {
    for (int x = 0; x < wid; x++)
    {
    if (clockwise)
    {
    ret[(hi - 1) - y + x * hi] = tex[x + y * wid];
    }
    else
    {
    ret[y + (wid - 1 - x) * hi] = tex[x + y * wid];
    }
    }
    }

    return ret;
    }
     
  14. HaimBendanan

    HaimBendanan

    Joined:
    May 10, 2016
    Posts:
    28
    Could you take a look at the problem I got? Thanks!
     
  15. Rick_Swash

    Rick_Swash

    Joined:
    Apr 20, 2017
    Posts:
    22
  16. pmjo

    pmjo

    Unity Technologies

    Joined:
    Sep 17, 2013
    Posts:
    245
    Your rotation probably works but are you trying to rotate the thumbnail texture or a copy of it? If you you try to get pixels from the thumbnail itself you will just get grey. You must first create a copy of it like in this thread https://forum.unity.com/threads/how-to-copy-the-everyplay-thumbnail.358970/

    However I would rotate the ui element (instead of the pixels) to avoid these unnecessary phases for better performance :)