LoginSignup
0
0

More than 1 year has passed since last update.

loopPointReachedによる動画再生終了の検出でつまづいた話

Last updated at Posted at 2021-06-06

loopPointReachedで動画再生を検出しようとしたところ、以下の問題が発生

■発生条件
動画を再生した後のVideoSourceで別の新しい動画を再生しようとした時、前の動画の再生中frameが、新しい動画の総frameより大きな値になっている。
※たとえば動画(長さ60秒)を20秒部分まで再生した後、別の動画(長さ10秒)を再生した場合など。
loopPointReachedに1つでもコールバック関数が1つも登録されていなければ発生しない様子。

■発生する問題
①新しい動画の再生開始直後に.loopPointReachedに登録されている関数が呼ばれる。
②PrepareCompletedを検出してすぐに.Play()しても、再生されない
正確には.Play()でisPlaying=trueになるが、直後に①の問題が発生することで強制的にisPlaying=falseにされる様子。

■問題が発生するコード
Start()内で関数を登録

videoPlayer.prepareCompleted += VideoPlayerOnPrepareCompleted;
videoPlayer.loopPointReached += FinishPlayingVideo;

動画再生処理

public void MovieStart(string filename)
{
    videoPlayer.url = mp4path + filename;
    videoPlayer.Prepare();
}

Prepare完了時に再生

private void VideoPlayerOnPrepareCompleted(VideoPlayer source)
{
    source.Play();
}

再生終了時の処理

private void FinishPlayingVideo(VideoPlayer vp)
{
     Debug.Log("再生終了時の処理");
}

■回避策
新しい動画を再生する前に前の動画を.frame = 0して再生時間を戻したり、再生時間を戻した状態で.Playして数frame待つ処理を入れても安定しなかった。
試行錯誤したところ、問題を回避せずに、発生させた後に影響を軽減させる方が良さそう。
①PrepareCompletedの後、少しの間は、loopPointReachedによる「再生終了」のイベントを無視させる
②PrepareCompletedの後、少し待ってから.Play()しなおす処理を入れる

■回避策を反映したコード

Start()内処理や、動画の再生処理は変更不要。

フラグ用の変数を追加。

private bool FinishPlayingVideoFlag = false;

Prepare完了時にコルーチン実行

private void VideoPlayerOnPrepareCompleted(VideoPlayer source)
{
    source.Play();
    StartCoroutine(loopPointReachedBugFix_Coroutine());
}

Prepare完了後、最大で1.3秒間の間、勝手に.isPlaying が falseになる(=問題発生)ことを検出させる。
問題が発生した場合は、改めて.Playする。
この間、FinishPlayingVideoFlagフラグを立てておく

private IEnumerator loopPointReachedBugFix_Coroutine()
{
    FinishPlayingVideoFlag = true;
    float Timer = 0;
    while (Timer < 1.3f)
    {
        yield return null;
        if (!videoPlayer.isPlaying)
        {
            Debug.Log("即終了バグ回避処理");
            videoPlayer.Play();
            break;
        }
        Timer += Time.deltaTime;
    }

    FinishPlayingVideoFlag = false;
}

フラグが立っている場合は、再生終了の検出を無視する。

private void FinishPlayingVideo(VideoPlayer vp)
{
     if (!FinishPlayingVideoFlag)
         Debug.Log("再生終了時の処理");
}

loopPointReachedの誤検知が発生するタイミングはバラツキが多いが、色々な条件で試したところ、他処理の負荷やFPSに関わらず、PrepareCompletedの直後frame~最大0.65秒程度の範囲で発生していたので、余裕をもって倍の1.3秒としている。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0