Задержка звука для платформы с VideoPlayer при приостановке и воспроизведении в Unity на Mac - PullRequest
0 голосов
/ 18 февраля 2019

Я работаю над адаптацией Unity к пьесе Сэмюэля Беккета - запускаю Unity 2018.3.4f1 и пишу код на C #.

У меня есть видео игры и сценарий игры;Когда игрок набирает строки сценария, видео воспроизводит набранные слова.Сценарий воспроизведения включает в себя временные метки для конца каждой строки, как они появляются в видео;когда пользователь заканчивает вводить заданную строку, значение PlayUntil с плавающей запятой увеличивается, поэтому оно равно отметке времени конца строки.PlayUntil проверяется на videoController.currentTime в FixedUpdate ();если видео продвигается дальше, чем PlayUntil, оно приостанавливает видео.

Это прекрасно работает на моем компьютере с Windows, как в редакторе, так и в сборках.Тем не менее, когда я пытаюсь воспроизвести его на своем Mac - либо в редакторе, либо в встроенной версии - возникает существенная задержка звука.Точнее говоря, первая четверть секунды или около того аудио из видео обрезается при каждом возобновлении воспроизведения после паузы.

Я пытался перекодировать видеофайл, как через Unity, так и черезVLC, для различных аудиоформатов (AAC, mp3 и т. Д.);Там нет очевидных изменений.Мое взломанное решение состоит в том, чтобы перематывать видео каждый раз, когда я снова начинаю играть, но это чертовски неприятно.Есть ли способ уменьшить обрезание звука, когда видео, воспроизводимое с помощью VideoPlayer на Mac, приостанавливается и воспроизводится?

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;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...