如何在QML中暂停最后一帧的视频?

时间:2014-01-15 13:33:36

标签: video qml qt5

我正在尝试停止播放QML视频,并在播放完成后显示其最后一帧。有人知道怎么做这个吗? (对不起,这似乎并不像听起来那么简单......)

目前,我的问题是视频元素在播放完成后变得不可见/隐藏。 (onVisibleChanged永远不会被调用。)

当我在代码中使用onStatusChanged中的hack时,视频会在结束后消失一段时间,然后显示视频结束。

我正在做的只是:

Video {
    anchors.fill: parent
    fillMode: VideoOutput.PreserveAspectFit;
    source: "path/to/file"
    autoPlay: true

    onStatusChanged: {
        console.warn("StatusChanged:"+status+"|"+MediaPlayer.Loaded)
        if (status == MediaPlayer.EndOfMedia)
        {
        // seek a bit before the end of the video since the last frames
        // are the same here, anyway
            seek(metaData.duration-200)
            play()
            pause()
        }
    }
    onVisibleChanged:
    {
        console.log(visible)
    }
}

我可能遗漏了一些东西,但我在文档中找不到关于这个主题的任何内容。此外,使用单独的MediaPlayerVideoOutput不会改变行为。

为了记录,我在Windows上使用最新的Qt 5.2(msvc2010 + OpenGL-build)。

4 个答案:

答案 0 :(得分:4)

几年后,我面临着同样的问题。但是,我找到了一种解决方法(对于Qt> = 5.9),使我可以在结束后100毫秒内暂停视频:

问题似乎与notifyInterval属性有关(在Qt 5.9中引入)。默认情况下,它设置为1000毫秒(与其他答案中观察到的1000毫秒相同,我相信这不是巧合)。因此,在视频即将结束时将其更改为非常小的值,可以捕获到非常接近末端的位置并在那里暂停视频:

Video {
    id: videoelem
    source: "file:///my/video.mp4"
    notifyInterval: videoelem.duration>2000 ? 1000 : 50
    onPositionChanged: {
        if(position > videoelem.duration-2*notifyInterval) {
            if(notifyInterval == 1000)
                notifyInterval = 50
            else if(notifyInterval == 50)
                videoelem.pause()
        }
    }
    onStatusChanged: {
        if(status == MediaPlayer.Loaded)
            videoelem.play()
    }
}

希望这对某人有帮助!

答案 1 :(得分:3)

我仍然在寻找更好的解决方案。我提出的是在视频结束之前暂停一下视频:

MediaPlayer {
    autoLoad: true
    id: video

    onPositionChanged: {
        if (video.position > 1000 && video.duration - video.position < 1000) {
            video.pause();
        }
    }
}

为什么一秒钟?在我的机器上,如果你试图在结束前大约500毫秒暂停它,视频会设法运行完成并从视图中消失,甚至没有注册pause()电话。因此,1秒对我来说是一个很好的安全价值。

坦率地说,如果有更明确的方式告诉MediaPlayer在视频结尾处做什么,我更喜欢。我知道Gstreamer是Qt在Linux和Mac上使用的,它会在视频几乎结束时通知您,以便您可以决定下一步该做什么 - 例如暂停视频或无缝循环播放。

答案 2 :(得分:3)

我分享你的痛苦(主要是对OSX和iOS感兴趣,同样的问题发生在那里)。我唯一的解决方案是将每个视频(至少是“预制”应用资源,而不是网络上的动态内容)与最终帧的png图像配对。当视频开始时,启用它下面的图像显示(尽管在那时它实际上不可见)。当视频突然结束时,图像将保持可见。

这在iOS上运行得很好,但在(某些?)Mac上,视频和图像之间可能会有轻微的亮度跳跃(猜测:与OSX显示偏好有关的屏幕校准不会影响视频?)

要在最后一帧上冻结的MediaPlayer或VideoOutput元素类型的选项确实会简单得多。

我考虑但未尝试的另一种可能性是堆叠两个视频。顶部的那个是主要播放器,但是下面的那个将被视为,例如,视频的最后一毫秒并暂停。然后当主视频结束并消失时...就像在视频的最后一帧显示在下面一样好。这基本上与基于图像的解决方案相同,但下面的图像是使用视频播放器动态创建的。我发现移动硬件的视频和它的Qt包装足够气质(不可否认的是更早回到Qt5的早期)真的不想尝试做任何过于聪明的事情。

答案 3 :(得分:0)

在 MediaPlayer 元素中:根据持续时间在结束前 100 毫秒暂停视频

       MediaPlayer {
            id: video1
            onPlaybackStateChanged: {  
                if(playbackState==1){
                    durTrig.stop();
                    durTrig.interval=duration-100;
                    durTrig.restart();
                 }
            }
        }
        Timer:{
            id:durTrig
            running:false
            repeat: false
            onTriggered:{   
               video1.pause();
            }
        }