如何以统一的方式反向播放视频?

时间:2018-04-30 06:49:44

标签: c# unity3d video ffmpeg virtual-reality

我正在Unity中实现VR 360视频查看器,需要实现反向播放"功能。我试过的一些方法(显然失败了):

  1. 将VideoPlayer的playbackSpeed字段设置为负数。
    • 结果:视频暂停
  2. 使用此处建议的方法逐帧反转视频:How to Rewind Video Player in Unity?
    • 结果:超级延迟播放
  3. 使用Vive Media Player(基于ffmpeg构建)(https://assetstore.unity.com/packages/tools/video/vive-media-decoder-63938),而不是使用默认的VideoPlayer。逐帧反转视频并强制渲染器在每次调用Update()时渲染帧,即使解码器的状态是DecoderState.SEEK_FRAME。
  4. 代码(基于资产中的ViveMediaDecoder.cs):

        //  Video progress is triggered using Update. Progress time would be set by nativeSetVideoTime.
        void Update() {
            Debug.Log(decoderState);
            switch (decoderState) {
                case DecoderState.START:
                    if (isVideoEnabled) {
                        //  Prevent empty texture generate green screen.(default 0,0,0 in YUV which is green in RGB)
                        if (useDefault && nativeIsContentReady(decoderID)) {
                            getTextureFromNative();
                            setTextures(videoTexYch, videoTexUch, videoTexVch);
                            useDefault = false;
                        }
    
                        //  Update video frame by dspTime.
                        double setTime = AudioSettings.dspTime - globalStartTime;
    
                        //  Normal update frame.
                        if (setTime < videoTotalTime || videoTotalTime == -1.0f) {
                            if (seekPreview && nativeIsContentReady(decoderID)) {
                                setPause();
                                seekPreview = false;
                                unmute();
                            } else {
                                nativeSetVideoTime(decoderID, (float) setTime);
                                GL.IssuePluginEvent(GetRenderEventFunc(), decoderID);
                            }
                        } else {
                            isVideoReadyToReplay = true;
                        }
                    }
    
                    if (nativeIsVideoBufferEmpty(decoderID) && !nativeIsEOF(decoderID)) {
                        decoderState = DecoderState.BUFFERING;
                        hangTime = AudioSettings.dspTime - globalStartTime;
                    }
    
                    break;
    
                case DecoderState.SEEK_FRAME:
    
                        //
                        // Code Added:
                        //
    
                        setTime = AudioSettings.dspTime - globalStartTime;
                        nativeSetVideoTime(decoderID, (float) setTime);
                        GL.IssuePluginEvent(GetRenderEventFunc(), decoderID);
    
                        //
                        //
    
                    if (nativeIsSeekOver(decoderID)) {
                        globalStartTime = AudioSettings.dspTime - hangTime;
                        decoderState = DecoderState.START;
                        if (lastState == DecoderState.PAUSE) {
                            seekPreview = true;
                            mute();
                        }
                    }
                    break;
    
                case DecoderState.BUFFERING:
                    if (nativeIsVideoBufferFull(decoderID) || nativeIsEOF(decoderID)) {
                        decoderState = DecoderState.START;
                        globalStartTime = AudioSettings.dspTime - hangTime;
                    }
                    break;
    
                case DecoderState.PAUSE:
                case DecoderState.EOF:
                default:
                    break;
            }
    
            if (isVideoEnabled || isAudioEnabled) {
                if ((!isVideoEnabled || isVideoReadyToReplay) && (!isAudioEnabled || isAllAudioChEnabled || isAudioReadyToReplay)) {
                    decoderState = DecoderState.EOF;
                    isVideoReadyToReplay = isAudioReadyToReplay = false;
    
                    if (onVideoEnd != null) {
                        onVideoEnd.Invoke();
                    }
                }
            }
        }
    

    - 结果:视频暂停

    我目前通过预先生成反转视频并在用户想要倒回时切换到反转视频来解决此问题。但是,鉴于我们的项目使用了超过一个360视频并允许自定义视频,生成反转视频所需的时间和切换视频的时间长得令人无法接受。

    由于该功能直观易用,我认为必须存在一个更简单的解决方案。已经长期困在这个问题所以任何解决问题的指针都会有很大的帮助!

2 个答案:

答案 0 :(得分:0)

根据我的经验,Unity中的videoPlayer效率不高,而且在重新融合时会滞后。

通过视频渲染,我发现EasyMovieTexture资产更好。

答案 1 :(得分:0)

我认为在Unity团队没有为他们的视频播放器实现视频源之前是不可能的

您可以尝试使用AVPro视频播放器支持所有主要平台。它现在是最快的视频播放器,并且他们有支持,因此您可以在购买资产之前询问它们是否可行。