White frame before video plays in Unity instead of a custom thumbnail - unity3d

I load a thumbnail before the video starts to play, but later when the video is playing, there is first a white frame and then the video is playing. How can I avoid this white frame??
Here is my code-
video.GetComponent<RawImage>().texture = thumbnailTex;
//Play the video:
RenderTexture rt = new RenderTexture(1920, 1080, 16, RenderTextureFormat.ARGB32);
rt.Create();
video.GetComponent<RawImage>().texture =rt;
video.GetComponent<RawImage>().targetTexture=rt;
video.GetComponent<VideoPlayer>().url = "www....";
video.GetComponent<VideoPlayer>().Play();
// white frame, and then the video is playing

You need to wait first and test if the video is ready to play
It would be better if it's not already to have the above code in a coroutine. What is happening is you call play before the player has had a chance to download/load the first frame. Then display your rendertexture.
video.GetComponent().url = "...";
video.GetComponent().Prepare();
while (!video.GetComponent().isPrepared)
yield return new WaitForEndOfFrame();
video.GetComponent().frame = 0; //just incase it's not at the first frame
video.GetComponent().Play();
//now display your render texture

Thanks you very much for this solution to avoid jump frames during the playing of a video!
But there are some changes to do :
In the "Start" function, I call a coroutine :
StartCoroutine(PrepareVideoCoroutine());
In this coroutine, I put :
while (!gameOverGlassVideo.GetComponent().isPrepared) {
gameOverGlassVideo.GetComponent<VideoPlayer>().Prepare();
yield return new WaitForEndOfFrame();
}
//::: I put the line to prepare the video in the condition and NOT
outside ::://
When I want to play the video after, it's was already prepared and there will be not jumping frames!

Related

Video playback cuts off the last few seconds

I'm playing a video in unity, and short clips are fine, but longer ones cut off the last few seconds. My video is 52 seconds and stops when about 50 have played. I tried a random 2:45 video from the net, and it stopped after 2:41. I can't figure out what's happening.
I tried video clip and URL. Both have the issue.
IEnumerator playVideo(SubjectClipState clipState)
{
clipState.clipObject.videoPlayer.Stop();
clipState.clipObject.audioSource.Stop();
clipState.clipObject.videoPlayer.playOnAwake = false;
clipState.clipObject.audioSource.playOnAwake = false;
clipState.clipObject.videoPlayer.source = VideoSource.Url;
clipState.clipObject.videoPlayer.audioOutputMode = clipState.clipConfig.hasAudio ? VideoAudioOutputMode.AudioSource : VideoAudioOutputMode.None;
clipState.clipObject.videoPlayer.controlledAudioTrackCount = clipState.clipConfig.hasAudio ? Convert.ToUInt16(1) : Convert.ToUInt16(0);
clipState.clipObject.videoPlayer.EnableAudioTrack(0, clipState.clipConfig.hasAudio);
if (clipState.clipConfig.hasAudio) clipState.clipObject.videoPlayer.SetTargetAudioSource(0, clipState.clipObject.audioSource);
clipState.clipObject.videoPlayer.url = clipState.clipConfig.url;
clipState.clipObject.videoPlayer.isLooping = clipState.clipConfig.endAction.type == "loop";
clipState.clipObject.videoPlayer.Prepare();
while (!clipState.clipObject.videoPlayer.isPrepared)
{
yield return null;
}
clipState.clipObject.videoPlayer.Play();
}
Note: the videoPlayer and audioSource are set elsewhere in the code. LoopPointReached is attached.
I am playing it like this:
StartCoroutine("playVideo", subjectClipState);
LoopPointReached will break a couple seconds before it should be done. The video player x/x frames is correct. e.g. 2740/2740 frames.
ok, it turns out it was a bug with Unity 2018.2. When I upgraded to 2018.3, it didnt cut off.

Single Audiosource for multiple clips?

I have a couple of audio sources in a script, idea being that one is used for effects and the other for music. I am noticing that if an effect plays at the same time as another one, it actually stops the previous one from playing, probably because they are playing from the same audio source.
My question is, do I really have to instantiate a new audio source every time i want to play a new sound, just to make sure that one sound will not stop a currently playing one ? Is there a better way ?
The method that plays a sound effect(and the awake one) in my class are these :
void Awake() {
audioSource = GetComponents<AudioSource>()[0];
audioEffectsSource = GetComponents<AudioSource>()[1];
audioSource.volume = PlayerPrefsManager.getMasterVolume();
audioEffectsSource.volume = PlayerPrefsManager.getSFXMasterVolume();
}
public void playSoundEffect(AudioClip clip)
{
if(clip != null)
{
audioEffectsSource.clip = clip;
audioEffectsSource.volume = PlayerPrefsManager.getSFXMasterVolume();
audioEffectsSource.PlayOneShot(clip);
}
}
The script is attached to a musicmanager gameobject with 2 audiosources, one for music fx and one for sound tracks.

MovieTexture won't play audio

I'm trying to dynamically load and play a video file. No matter what I do, I cannot seem to figure out why the audio does not play.
var www = new WWW("http://unity3d.com/files/docs/sample.ogg");
var movieTexture = www.movie;
var movieAudio = www.movie.audioClip;
while (!movieTexture.isReadyToPlay) yield return 0;
// Assign movie texture and audio
var videoAnimation = videoAnimationPrefab.GetComponent<VideoAnimation>();
var videoRenderer = videoAnimation.GetVideoRenderer();
var audioSource = videoAnimation.GetAudioSource();
videoRenderer.material.mainTexture = movieTexture;
audioSource.clip = movieAudio;
// Play the movie and sound
movieTexture.Play();
audioSource.Play();
// Double check audio is playing...
Debug.Log("Audio playing: " + audioSource.isPlaying);
Every time I receive Audio playing: False
I've also tried using a GUITexture using this as a guide, but no dice. There are no errors displayed in the console.
What am I doing wrong that makes the audio never work?
Thanks in advance for any help!
Changed to:
while (!movieTexture.isReadyToPlay) yield return 0;
var movieAudio = movieTexture.audioClip;
Even though AudioClip inherits from Object, a call to movieTexture.audioClip seems to return a copied version instead of returning a reference by value to the object. So at the time I was assigning it, it had not been created yet and had to wait until the movie was "Ready to Play" until fetching the audioClip.

Can I take a photo in Unity using the device's camera?

I'm entirely unfamiliar with Unity3D's more complex feature set and am curious if it has the capability to take a picture and then manipulate it. Specifically my desire is to have the user take a selfie and then have them trace around their face to create a PNG that would then be texture mapped onto a model.
I know that the face mapping onto a model is simple, but I'm wondering if I need to write the photo/carving functionality into the encompassing Chrome app, or if it can all be done from within Unity. I don't need a tutorial on how to do it, just asking if it's something that is possible.
Yes, this is possible. You will want to look at the WebCamTexture functionality.
You create a WebCamTexture and call its Play() function which starts the camera. WebCamTexture, as any Texture, allows you to get the pixels via a GetPixels() call. This allows you to take a snapshot in when you like, and you can save this in a Texture2D. A call to EncodeToPNG() and subsequent write to file should get you there.
Do note that the code below is a quick write-up based on the documentation. I have not tested it. You might have to select a correct device if there are more than one available.
using UnityEngine;
using System.Collections;
using System.IO;
public class WebCamPhotoCamera : MonoBehaviour
{
WebCamTexture webCamTexture;
void Start()
{
webCamTexture = new WebCamTexture();
GetComponent<Renderer>().material.mainTexture = webCamTexture; //Add Mesh Renderer to the GameObject to which this script is attached to
webCamTexture.Play();
}
IEnumerator TakePhoto() // Start this Coroutine on some button click
{
// NOTE - you almost certainly have to do this here:
yield return new WaitForEndOfFrame();
// it's a rare case where the Unity doco is pretty clear,
// http://docs.unity3d.com/ScriptReference/WaitForEndOfFrame.html
// be sure to scroll down to the SECOND long example on that doco page
Texture2D photo = new Texture2D(webCamTexture.width, webCamTexture.height);
photo.SetPixels(webCamTexture.GetPixels());
photo.Apply();
//Encode to a PNG
byte[] bytes = photo.EncodeToPNG();
//Write out the PNG. Of course you have to substitute your_path for something sensible
File.WriteAllBytes(your_path + "photo.png", bytes);
}
}
For those trying to get the camera to render live feed, here's how I managed to pull it off. First, I edited Bart's answer so the texture would be assigned on Update rather than just on Start:
void Start()
{
webCamTexture = new WebCamTexture();
webCamTexture.Play();
}
void Update()
{
GetComponent<RawImage>().texture = webCamTexture;
}
Then I attached the script to a GameObject with a RawImage component. You can easily create one by Right Click -> UI -> RawImage in the Hierarchy in the Unity Editor (this requires Unity 4.6 and above). Running it should show a live feed of the camera in your view. As of this writing, Unity 5 supports the use of webcams in the free personal edition of Unity 5.
I hope this helps anyone looking for a good way to capture live camera feed in Unity.
It is possible. I highly recommend you look at WebcamTexture Unity API. It has some useful functions:
GetPixel() -- Returns pixel color at coordinates (x, y).
GetPixels() -- Get a block of pixel colors.
GetPixels32() -- Returns the pixels data in raw format.
MarkNonReadable() -- Marks WebCamTexture as unreadable
Pause() -- Pauses the camera.
Play() -- Starts the camera.
Stop() -- Stops the camera.
Bart's answer has a required modification. I used his code and the pic I was getting was black. Required modification is that we have to
convert TakePhoto to a coroutine and add
yield return new WaitForEndOfFrame();
at the start of Coroutine. (Courtsey #fafase)
For more details see
http://docs.unity3d.com/ScriptReference/WaitForEndOfFrame.html
You can also refer to
Take photo using webcam is giving black output[Unity3D]
Yes, You can. I created Android Native camera plugin that can open your Android device camera, capture image, record video and save that in the desired location of your device with just a few lines of code.
you need to find your webcam device Index by search it in the devices list and select it for webcam texture to play.
you can use this code:
using UnityEngine;
using System.Collections;
using System.IO;
using UnityEngine.UI;
using System.Collections.Generic;
public class GetCam : MonoBehaviour
{
WebCamTexture webCam;
string your_path = "C:\\Users\\Jay\\Desktop";// any path you want to save your image
public RawImage display;
public AspectRatioFitter fit;
public void Start()
{
if(WebCamTexture.devices.Length==0)
{
Debug.LogError("can not found any camera!");
return;
}
int index = -1;
for (int i = 0; i < WebCamTexture.devices.Length; i++)
{
if (WebCamTexture.devices[i].name.ToLower().Contains("your webcam name"))
{
Debug.LogError("WebCam Name:" + WebCamTexture.devices[i].name + " Webcam Index:" + i);
index = i;
}
}
if (index == -1)
{
Debug.LogError("can not found your camera name!");
return;
}
WebCamDevice device = WebCamTexture.devices[index];
webCam = new WebCamTexture(device.name);
webCam.Play();
StartCoroutine(TakePhoto());
display.texture = webCam;
}
public void Update()
{
float ratio = (float)webCam.width / (float)webCam.height;
fit.aspectRatio = ratio;
float ScaleY = webCam.videoVerticallyMirrored ? -1f : 1f;
display.rectTransform.localScale = new Vector3(1f, ScaleY, 1f);
int orient = -webCam.videoRotationAngle;
display.rectTransform.localEulerAngles = new Vector3(0, 0, orient);
}
public void callTakePhoto() // call this function in button click event
{
StartCoroutine(TakePhoto());
}
IEnumerator TakePhoto() // Start this Coroutine on some button click
{
// NOTE - you almost certainly have to do this here:
yield return new WaitForEndOfFrame();
// it's a rare case where the Unity doco is pretty clear,
// http://docs.unity3d.com/ScriptReference/WaitForEndOfFrame.html
// be sure to scroll down to the SECOND long example on that doco page
Texture2D photo = new Texture2D(webCam.width, webCam.height);
photo.SetPixels(webCam.GetPixels());
photo.Apply();
//Encode to a PNG
byte[] bytes = photo.EncodeToPNG();
//Write out the PNG. Of course you have to substitute your_path for something sensible
File.WriteAllBytes(your_path + "\\photo.png", bytes);
}
}
There is a plugin available for this type of functionality called Camera Capture Kit - https://www.assetstore.unity3d.com/en/#!/content/56673 and while the functionality provided is geared towards mobile it contains a demo of how you can use the WebCamTexture to take a still image.
If you want to do that without using a third party plugin then #FuntionR solution will help you. But, if you want to save the captured photo to the gallery (Android & iOS)then it's not possible within unity, you have to write native code to transfer photo to gallery and then call it from unity.
Here is a summarise blog which will guide you to achieve your goal.
http://unitydevelopers.blogspot.com/2018/07/pick-image-from-gallery-in-unity3d.html
Edit: Note that, the above thread describes image picking from the gallery, but the same process will be for saving the image to the gallery.

Set a ScheduledAudioFileRegion to start again

I am trying to play a sound when a button it tapped and am using the iOS 5 file player audio unit.
The file player plays audio using the ScheduledAudioFileRegion and can be scheduled to play as many frames as needed
ScheduledAudioFileRegion rgn;
memset (&rgn.mTimeStamp, 0, sizeof(rgn.mTimeStamp));
rgn.mTimeStamp.mFlags = kAudioTimeStampSampleTimeValid;
rgn.mTimeStamp.mSampleTime = 0;
rgn.mCompletionProc = NULL;
rgn.mCompletionProcUserData = NULL;
rgn.mAudioFile = audioFile;
rgn.mLoopCount = INT_MAX;
rgn.mStartFrame = 0;
rgn.mFramesToPlay = nPackets * fileASBD.mFramesPerPacket; // plays entire file.
How can I tell this file player to play the sound from the start whenever a button is pressed, or do I have to create a new region and memset it each time? I would like the sound to play when the button is pressed from start to finish but when the button is tapped again, it should start from the beginning even if the file is currently playing. Is this possible with the fileplayer audio unit?
Call AudioUnitReset to stop playback, then prime and play again. Happens instantly (or as near as makes no difference.)
Do this whenever your user presses the button:
// Reset
AudioUnitReset(filePlayerUnit, kAudioUnitScope_Global, 0);
// Prime (have to do this before every play call.)
UInt32 defaultVal = 0;
AudioUnitSetProperty(filePlayerUnit,
kAudioUnitProperty_ScheduledFilePrime,
kAudioUnitScope_Global,
0,
&defaultVal,
sizeof(defaultVal));
// Play (again)
AudioUnitSetProperty(_playerUnit,
kAudioUnitProperty_ScheduleStartTimeStamp,
kAudioUnitScope_Global,
0,
&startTime,
sizeof(startTime));
You already have your timestamps in the region. You need those, but you also have to create an AudioTimeStamp:
AudioTimeStamp startTime;
memset(&startTime, 0, sizeof(startTime));
startTime.mFlags = kAudioTimeStampSampleTimeValid;
startTime.mSampleTime = -1;
Create this, and call the associated SetProperty from the first snippet above, before you call play the first time.
Can you not just have your UIButton trigger a Stop action before calls Play..?