问题
My general problem is that I need to play and control the speed of a video (no sound) inside a Unity3D world and probably need to control the decoding myself and I have absolutely no idea how to do that efficiently. So any hints in the right direction are welcome.
I need to play a video projected on a Material in Unity and I need to control the speed of that video at runtime. As I target mobile devices I cannot use MovieTexture. There are alternatives like e.g. Easy Movie Texture but they do not allow me to control the speed of the video.
I found a problematic solution in this post. In short, the author breaks the video into its frames and then displays it frame by frame. This way I can control the video speed by simply changing the time until displaying the next frame. The video does not have any sound, so it's that easy. The problem is that this is a nightmare from a memory and performace point of view. The app would be GB big and inefficient.
So as far as I know a normal video player solves that by not saving and displaying every frame but just delta between them. If I could do that myself and control it frame by frame I'd solve my problem.
I imagine to decode it at runtime and then display the delta's. But I have no idea how to do that. So please point me in the right direction or maybe even give me a solution if you have.
The video format is not yet fixed, so whatever is easiest.
回答1:
You don't need Easy Movie Texture to do this and you don't even need to get the video frames to do this.
With the new Unity VideoPlayer
API, you can check if you can set the playback speed on the platform with VideoPlayer.canSetPlaybackSpeed. If it returns true
, you can then set the video playback speed by simply changing the videoPlayer.playbackSpeed property.
You can use the code in this answer to play video on RawImage
then add the code below to set the playback speed.
if (videoPlayer.canSetPlaybackSpeed)
{
videoPlayer.playbackSpeed = 1f;
}
It is as simple as that.
You mentioned that you want the image to be projected on a material. In this case, you should set the VideoPlayer.renderMode to VideoRenderMode.MaterialOverride;
The code below should project the video on any GameObject called "DisplayObject". You can also access the material from the video in the outputRenderer
or outputRenderer.material
variable.
It has audio for testing purposes and you can remove it if you don't want audio like you mentioned in your post.
using UnityEngine;
using UnityEngine.Video;
public class VideoSpeedControl : MonoBehaviour
{
//The material that Video will output to
Renderer outputRenderer;
private VideoPlayer videoPlayer;
//Audio
private AudioSource audioSource;
void Start()
{
outputRenderer = gameObject.AddComponent<MeshRenderer>();
//Add VideoPlayer to the GameObject
videoPlayer = gameObject.AddComponent<VideoPlayer>();
//Add AudioSource
audioSource = gameObject.AddComponent<AudioSource>();
//Disable Play on Awake for both Video and Audio
videoPlayer.playOnAwake = false;
audioSource.playOnAwake = false;
// We want to play from url
videoPlayer.source = VideoSource.Url;
videoPlayer.url = "http://www.quirksmode.org/html5/videos/big_buck_bunny.mp4";
//Set Audio Output to AudioSource
videoPlayer.audioOutputMode = VideoAudioOutputMode.AudioSource;
//Assign the Audio from Video to AudioSource to be played
videoPlayer.EnableAudioTrack(0, true);
videoPlayer.SetTargetAudioSource(0, audioSource);
//Set the mode of output
videoPlayer.renderMode = VideoRenderMode.MaterialOverride;
//Set the renderer to store the images to
//outputRenderer = videoPlayer.targetMaterialRenderer;
videoPlayer.targetMaterialProperty = "_MainTex";
//Prepare Video to prevent Buffering
videoPlayer.Prepare();
//Subscribe to prepareCompleted event
videoPlayer.prepareCompleted += OnVideoPrepared;
}
void OnVideoPrepared(VideoPlayer source)
{
Debug.Log("Done Preparing Video");
//Play Video
videoPlayer.Play();
//Play Sound
audioSource.Play();
//Change Play Speed
if (videoPlayer.canSetPlaybackSpeed)
{
videoPlayer.playbackSpeed = 1f;
}
}
bool firsrRun = true;
void Update()
{
if (firsrRun)
{
GameObject.Find("DisplayObject").GetComponent<MeshRenderer>().material = outputRenderer.material;
firsrRun = false;
}
}
}
来源:https://stackoverflow.com/questions/42954566/set-video-playback-speed-in-unity