在Mac上的Unity中暂停和播放时,VideoPlayer特定于平台的音频滞后

时间:2019-02-18 16:05:08

标签: c# unity3d audio video

我正在研究Samuel Beckett剧本的Unity改编版-运行Unity 2018.3.4f1并使用C#进行编码。

我有一个剧本的视频和剧本;当播放器键入脚本行时,视频将播放他们键入的单词。剧本的脚本包括视频中每行结尾的时间戳。当用户完成给定行的键入时,浮点PlayUntil会增加,因此等于行末的时间戳。在FixedUpdate()中对照videoController.currentTime检查PlayUntil;如果视频比PlayUntil先进,它将暂停视频。

在我的Windows计算机上,无论是在编辑器中还是在构建中,都可以正常使用。但是,当我尝试在Mac上(在编辑器或内置版本中)播放时,音频滞后很大。更具体地说,每次暂停后,如果视频再次开始播放,视频中音频的前四分之一秒将被切断。

我已经尝试通过Unity和VLC将视频文件转码为各种不同的音频格式(AAC,mp3等);那里没有明显的变化。我被黑客入侵的解决方案是每次我再次开始播放时都倒带视频,但这简直太糟糕了。在Mac上通过VideoPlayer播放的视频暂停播放时,是否有任何方法可以减少音频截止?

VideoController.cs:

using System.Collections;
using System.Collections.Generic;
using UnityEngine.Video;
using UnityEngine.UI;
using UnityEngine;


public class VideoController : MonoBehaviour
{
    public VideoPlayer video;
    public Slider slider;
    public float PlayUntil = 0.0f;
    public float timePaused = 0f;
    public float startTime;
//properties of the video player
bool isDone;

public float getTimePaused
{
    get { return timePaused; }
}
public bool IsPlaying
{
    get { return video.isPlaying; }
}

public bool IsPrepared
{
    get { return video.isPrepared; }
}

public bool IsDone
{
    get { return isDone;  }
}

public double currentTime
{
    get { return video.time; }
}

public ulong Duration
{
    get { return (ulong)(video.frameCount / video.frameRate); }
}


void OnEnable()
{
    video.errorReceived += errorReceived;
    video.frameReady += frameReady;
    video.prepareCompleted += prepareCompleted;
    video.seekCompleted += seekCompleted;
    video.started += started;
    video.time = 0.1f;
}

void OnDisable()
{
    video.errorReceived -= errorReceived;
    video.frameReady -= frameReady;
    video.prepareCompleted -= prepareCompleted;
    video.seekCompleted -= seekCompleted;
    video.started -= started;
}

void errorReceived(VideoPlayer v, string msg)
{
    Debug.Log("video player error: " + msg);
}

void frameReady(VideoPlayer v, long frame)
{

}

void prepareCompleted(VideoPlayer v)
{
    Debug.Log("video player finished prepping");
    isDone = false;
}

void seekCompleted(VideoPlayer v)
{
    Debug.Log("video player finished seeking");
    isDone = false;
}

void started(VideoPlayer v)
{
   //  Debug.Log("video player started");
}

private void Start()
{
    video.Prepare();
    Application.targetFrameRate = 20;
    video.targetCameraAlpha = 0.1f;
    video.time = 0.1f;
}

public void LoadVideo()
{
    string temp = Application.dataPath + "/Video/" + "NotI.mp4";
    if (video.url == temp) return;
    video.url = temp;
    video.Prepare();
    Debug.Log("can set direct audio volume: " + video.canSetDirectAudioVolume);
    Debug.Log("can set playback speed: " + video.canSetPlaybackSpeed);
    Debug.Log("can set time: " + video.canSetTime);
    Debug.Log("can step: " + video.canStep);
}

public void PlayVideo()
{
    if (!IsPrepared) return;
    if (IsPlaying) return;
    video.Play();
    timePaused += Time.time - startTime;
    startTime = 0f;

}

public void PauseVideo()
{
    if (!IsPlaying) return;
    video.Pause();
    startTime = Time.time;

}

public void Seek(float time)
{
    if (!video.canSetTime) return;
    if (!IsPrepared) return;
    video.time = time;
}

public void SetPlaybackSpeed(float speed)
{
    if (!video.canSetPlaybackSpeed) return;
    video.playbackSpeed = speed;
}

public void IncrementPlaybackSpeed()
{
    if (!video.canSetPlaybackSpeed) return;

    video.playbackSpeed += 1;
}

public void DecrementPlaybackSpeed()
{
    if (!video.canSetPlaybackSpeed) return;

    video.playbackSpeed -= 1;
}

}

~~

和处理时间的WordManager.cs:

using System.Collections;
using System.Text;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class WordManager : MonoBehaviour
{
    public List<Word> words;
    public List<Word> settings;
    // Make the main list:

    // Use the test w/ timestamps
    public TextAsset ATTTScript;

    //public static string cleanText = System.IO.File.ReadAllText("Assets/Text/AlmostToTheTickScript.txt", System.Text.Encoding.ASCII);
    //public static string[] listOfWords = cleanText.Split('\n');
    public static string cleanText;
    public static string[] listOfWords;
    public VideoController videoController;
    public WordSpawner wordSpawner;
    private static float offset = 0f;
    private bool hasActiveWord;
    private Word activeWord;
    public static int position = 0;
    public string currentWord;
    public float currentTime;
    // if you're using an offset:


    // variables for settings
    public static Vector3 settingsLocation = new Vector3(-4.0f, -1f);
    public static bool timerShowing = false;
    public static bool wpmShowing;
    public static bool accuracyShowing;
    public static bool pauseTimerShowing = false;
    public static bool progressShowing = false;
    public static string settingsString;
    public static float speedFactor = 1f;
    private float PlayUntil = 0.00f;
    private Vector3 defaultLocation = new Vector3(0f, 2.5f, 0f);
    private Vector3 secondLocation = new Vector3(0f, 2.0f, 0f);

    private void Start()
    {
        if (Application.platform == RuntimePlatform.OSXPlayer)
        {
            offset = -.15f;
        }
        cleanText = ATTTScript.ToString();
        listOfWords = cleanText.Split('\n');
        currentWord = listOfWords[position].Split('_')[0];
        currentTime = float.Parse(listOfWords[position].Split('_')[1]) + offset;
        GameObject InfoBox = GameObject.Find("InfoBox");
        if (GameObject.Find("InfoBox") != null)
        {
            InfoBoxScript info = InfoBox.GetComponent<InfoBoxScript>();
            speedFactor = info.getSpeed();
            Debug.Log("Playing at " + speedFactor + "speed");
            Debug.Log("StatsOn = " + info.getStatsOn());
            if (info.getStatsOn())
            {
                timerShowing = true;
                pauseTimerShowing = true;
                progressShowing = true;
            }
        }
        settingsString = makeSettingsString();
        Word settingsWord = new Word("settings", 9999f, wordSpawner.SpawnWord(settingsLocation));
        settingsWord.ChangeSize(14);
        settingsWord.ChangeAlign("Upper Left");
        settingsWord.ChangeWord(settingsString);
        settings.Add(settingsWord);
        AddWord();
        AddWord();
        videoController.SetPlaybackSpeed(speedFactor);
    }

    private void FixedUpdate()
    {
        //settings stuff
        if (Input.GetKeyDown(KeyCode.Tab))
        {
            timerShowing = !timerShowing;
            pauseTimerShowing = !pauseTimerShowing;
            progressShowing = !progressShowing;
        }
        settingsString = makeSettingsString();
        settings[0].ChangeWord(settingsString);

        if (!videoController.IsPrepared)
        {
            // Debug.Log("Not ready!");
            return;
        }
        if (videoController.currentTime < PlayUntil)
        {
            // Debug.Log(video.time + " < " + PlayUntil);
            videoController.PlayVideo();
        }
        else
        {
            // Debug.Log(video.time + " > " + PlayUntil);
            videoController.PauseVideo();
        }
        if (words[0].GetVector3() != defaultLocation)
        {
            words[0].MoveTowards(defaultLocation);
        }
    }
    public void AddWord()
    {
        Vector3 newWordLocation = defaultLocation;
        Word lastWord = null;
        if (words.Count == 0)
        {
            newWordLocation = defaultLocation;
        }
        else
        {
            newWordLocation = secondLocation;
        }

        if (position > listOfWords.Length - 1)
        {
            Debug.Log("Done");
            SceneManager.LoadScene(2);
        }
        currentWord = listOfWords[position].Split('_')[0];
        currentTime = float.Parse(listOfWords[position].Split('_')[1]) + offset;
        Word word = new Word(currentWord, currentTime, wordSpawner.SpawnWord(newWordLocation), lastWord);
        Debug.Log(currentWord);
        words.Add(word);
        position = position + 1;       
    }

    public void TypeLetter(char letter)
    {
        if (hasActiveWord)
        {
            if (activeWord.GetNextLetter() == letter)
            {
                activeWord.TypeLetter();
            }
        }
        else
        {
            if (words[0].GetNextLetter() == letter)
            {
                activeWord = words[0];
                hasActiveWord = true;
                words[0].TypeLetter();
            }
        }

        if (hasActiveWord && activeWord.WordTyped())
        {
            hasActiveWord = false;
            PlayUntil = activeWord.GetEndTime();
            words.Remove(activeWord);
            AddWord();
        }
        // ` = skip mode.
        if (hasActiveWord && letter == '`')
        {
            hasActiveWord = false;
            PlayUntil = activeWord.GetEndTime();
            words.Remove(activeWord);
            activeWord.RemoveWord();
            AddWord();
        }
        else if(!hasActiveWord && letter == '`')
        {
            activeWord = words[0];
            hasActiveWord = true;
            words[0].TypeLetter();
        }
    }

    private string makeSettingsString()
    {
        settingsString = "";
        if (timerShowing)
        {
            float videoTime = Mathf.Round((float)videoController.currentTime * 100.0f) / 100f;
            settingsString += "Video Time: " + videoTime + "\n";
        }
        if(pauseTimerShowing)
        {
            float timePaused = Mathf.Round(videoController.getTimePaused*100f)/100f;
            settingsString += "Time spent paused: " + timePaused + "\n";
        }
        if (progressShowing)
        {
            settingsString += "At position " + (position-2) + " of " + listOfWords.Length + "\n";
        }
        return settingsString;
    }
}

0 个答案:

没有答案