How to pause a video in the last frame in QML?

I am trying to stop a QML video and show its last frame when playback is finished. Does anyone know how to do this? (Sorry, this doesn't seem as trivial as it seems).

At the moment, my problem is that the video element just becomes invisible / hidden after playback ends. ( onVisibleChanged never called.)

When I use hack onStatusChanged in my code, the video disappears a moment after the end and then shows the end of the video.

What I'm doing is simple:

 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) } } 

It is possible that I have something missing, but I could not find anything on this topic in the documents. In addition, using separate MediaPlayer and VideoOutput does not change behavior.

For recording, I use the latest version of Qt 5.2 for Windows (msvc2010 + OpenGL-build).

+6
source share
3 answers

I'm still looking for the best solution for this. What I came up with is to pause the video one second before:

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

Why is one second? On my machine, if you try to pause about 500 ms to the end, the video can be played to completion and disappear from view without even registering the pause() call. So 1 second is a good safe value for me.

Honestly, I would prefer if there was a more explicit way to tell MediaPlayer what to do at the end of the video. I know that GStreamer, which uses Qt for Linux and Mac, notifies you when the video is almost over so you can decide what to do next - for example. pause video or loop it without any problems.

+3
source

I share your pain (mostly interested in OSX and iOS, where the same problem occurs). The only solution I have is to associate each video (which is at least the β€œcanned” application resources, and not the dynamic content from the network) with the png image of their final frame. When the video starts, turn on the display of the image below it (although in fact it is not visible at this point). When the video ends abruptly, the image remains visible.

This works fine on iOS, but on (some?) Macs, there may be a slight distortion in brightness between the video and the image (fortunetelling: do I have to do something with the OSX settings screen without affecting the video?)

The option for MediaPlayer or VideoOutput element types to freeze the last frame will be much simpler.

Another opportunity that I considered, but have not tried, will add up two videos. The one on top is the main player, but the one underneath it will simply search, say, for the last millisecond of the video and pause it. Then, when the main video ends and disappears ... there is as good as the last frame of the video showing below. This is basically the same as the image-based solution, but the image below it is dynamically created using a video player. I found that the mobile video HW and Qt wrap it up quite temperamental (though earlier in the earlier days of Qt5) to really not want to try and do something too smart with it, though.

+3
source

A few years later I faced the same problem. However, I found a workaround (for Qt> = 5.9) that allows me to pause the video for 100ms after the end:

The problem seems to be related to the notifyInterval property (introduced in Qt 5.9). The default value is 1000 ms (the same as the 1000 ms observed in other answers, I do not consider this a coincidence). Thus, changing it to a very small value when the video is almost finished allows you to catch the position very close to the end and pause the video there:

 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() } } 

Hope this helps someone!

0
source

All Articles