我的一般问题是我需要在Unity3D世界中播放和控制视频的速度(没有声音),并且可能需要自己控制解码,我完全不知道如何有效地做到这一点。因此欢迎任何正确方向的提示。
我需要播放投影在Unity中的素材上的视频,我需要在运行时控制该视频的速度。当我以移动设备为目标时,我无法使用MovieTexture。有一些替代品,例如简单的电影纹理但它们不允许我控制视频的速度。
我在post中发现了一个有问题的解决方案。简而言之,作者将视频分解为帧,然后逐帧显示。这样我就可以通过简单地改变显示下一帧的时间来控制视频速度。视频没有任何声音,所以很容易。 问题在于,从内存和性能的角度来看,这是一场噩梦。该应用程序将是GB大而且效率低下。
据我所知,普通的视频播放器通过不保存和显示每一帧而只是它们之间的差异来解决这个问题。如果我能够自己做并逐帧控制,我就可以解决我的问题。
我想在运行时解码它然后显示delta。但我不知道该怎么做。所以,请指出我正确的方向,或者甚至可以给我一个解决方案,如果你有。
视频格式尚未修复,因此无论什么都是最简单的。
答案 0 :(得分:1)
你不需要简单的电影纹理就可以做到这一点,你甚至不需要让视频帧来做这件事。
使用新的Unity VideoPlayer
API,您可以检查是否可以使用VideoPlayer.canSetPlaybackSpeed
在平台上设置播放速度。如果它返回true
,您只需更改videoPlayer.playbackSpeed
属性即可设置视频播放速度。
您可以使用此answer中的代码在RawImage
上播放视频,然后添加以下代码以设置播放速度。
if (videoPlayer.canSetPlaybackSpeed)
{
videoPlayer.playbackSpeed = 1f;
}
就这么简单。
您提到您希望将图像投影到素材上。在这种情况下,您应将VideoPlayer.renderMode
设置为VideoRenderMode.MaterialOverride;
下面的代码应该将视频投影到名为“ DisplayObject ”的任何GameObject上。您还可以通过outputRenderer
或outputRenderer.material
变量中的视频访问素材。
它有用于测试目的的音频,如果您不想要在帖子中提到的音频,可以将其删除。
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;
}
}
}