问题描述
我有一个应用,旨在帮助同步实验视频和数据信号.该应用程序有一个视频小部件和一个滑块,可以设置视频的时间位置.但是,QMediaPlayer 只会将位置设置为 500 毫秒/1000 毫秒间隔(在我的应用程序中为 500 毫秒/在人为的应用程序中为 1000 毫秒),而视频以 50 fps 拍摄,这意味着 20 毫秒间隔.这使得同步非常无用.我在位置更改前后添加了位置的输出.
任何帮助将不胜感激.
这是更改滑块时的输出:
新的滑块位置326媒体播放器更新位置 0新的滑块位置 816媒体播放器更新位置 0新的滑块位置 1306媒体播放器更新位置 0新的滑块位置 1632媒体播放器更新位置 1000新的滑块位置 1959媒体播放器更新位置 1000新的滑块位置 2449媒体播放器更新位置 2000新的滑块位置 2938媒体播放器更新位置 2000新的滑块位置 3428媒体播放器更新位置 2000新的滑块位置 3755媒体播放器更新位置 3000新的滑块位置 4081媒体播放器更新位置 3000新的滑块位置 4571媒体播放器更新位置 4000新的滑块位置 4897媒体播放器更新位置 4000新的滑块位置 5224媒体播放器更新位置 4000新滑块位置 5550媒体播放器更新位置 5000新的滑块位置 5714媒体播放器更新位置 5000新滑块位置 6040媒体播放器更新位置 5000新的滑块位置 6203媒体播放器更新位置 6000新滑块位置 6530
我还尝试设置从 mediaPlayer.position () 中检索到的特定位置,但无济于事.
这是人为的应用程序:
导入系统从 PyQt5 导入 QtWidgets从 PyQt5.QtCore 导入 QSize、Qt、QUrl从 PyQt5.QtMultimedia 导入 QMediaContent、QMediaPlayer从 PyQt5.QtMultimediaWidgets 导入 QVideoWidget从 PyQt5.QtWidgets 导入 QMainWindow、QLabel、QWidget、QSlider从 PyQt5.QtWidgets 导入 QVBoxLayout、QHBoxLayout## 参考 https://pythonprogramminglanguage.com/pyqt5-video-widget/#类主窗口(QMainWindow):def __init__ (self, parent=None):super (QMainWindow, self).__init__ (parent)## 在这里设置文件名#文件名 = '/Users/yuval/src/lab/S4560001.MP4'self.setMinimumSize (QSize (640, 480))self.setWindowTitle('视频和数据查看器和注释器')self.mediaPlayer = QMediaPlayer(无,QMediaPlayer.VideoSurface)videoWidget = QVideoWidget()videoWidget.setMinimumSize (640,200)## 位置滑块#self.positionSlider = QSlider (Qt.Horizontal)self.positionSlider.setRange (0, 0)self.positionSlider.sliderMoved.connect (self.setPosition)## 位置标签#self.positionLabel = QLabel ('00:00:000')centralWidget = QWidget (self)self.setCentralWidget (centralWidget)## 布局控件小部件#ctlLayout = QHBoxLayout()ctlLayout.setContentsMargins (0, 0, 0, 0)ctlLayout.addWidget (self.positionSlider)ctlLayout.addWidget (self.positionLabel)## 布局窗口#布局 = QVBoxLayout()layout.addWidget (videoWidget)layout.addLayout (ctlLayout)centralWidget.setLayout(布局)self.mediaPlayer.setVideoOutput (videoWidget)self.mediaPlayer.positionChanged.connect (self.positionChanged)self.mediaPlayer.durationChanged.connect (self.durationChanged)self.mediaPlayer.error.connect (self.handleError)self.mediaPlayer.setNotifyInterval (100)self.mediaPlayer.setMuted (True)打印(文件名)如果文件名 != '':self.mediaPlayer.setMedia (QMediaContent (QUrl.fromLocalFile (filename)))def positionChanged (self, position):self.positionSlider.setValue(位置)def durationChanged(自我,持续时间):self.positionSlider.setRange(0,持续时间)def setPosition(自我,位置):打印(f'新滑块位置{位置}')self.mediaPlayer.setPosition(位置)打印(f'媒体播放器更新位置{self.mediaPlayer.position()}')def handleError (self):打印('错误:' + self.mediaPlayer.errorString())如果 __name__ == '__main__':app = QtWidgets.QApplication (sys.argv)mainWin = 主窗口 ()mainWin.show()sys.exit (app.exec_())
我在 MacOS 10.14.16 (Mojave) 上运行.
Python 3.7.4
Python 包:PyQt5==5.13.0PyQt5-sip==4.19.18
端口包:py37-pyqt5 @5.12.2_0(活动)qt5 @5.12.4_0(活动)
找到了答案.问题出在 Qt5 中,他们声称"这不是错误,似乎也没有任何修复计划.它特定于 MacOS,在 Windows 上运行良好(我怀疑是 Linux).问题在于 Qt5 使用具有时间容限的 MacOS API.默认情况下,它只会使用关键帧",而可以限制其容差.Qt5 没有指定容差,因此它会调整关键帧的时间.
如果有人在 MacOS Qt5 开发团队中,如果你能解决这个问题就太好了.是的,如果我有一个开发环境,我会自己修复它(但无论如何我可能会被否决).
MacOS/AVFoundation API 是 https://developer.apple.com/documentation/avfoundation/avplayeritem/1387418-seek
I have an app that's designed to help synchronise an experiment video and data signals. The App has a video widget and a slider that can set the temporal position of the video. However, QMediaPlayer will only set the position at 500mSec/1000mSec intervals (in my app 500mSec/in the contrived app 1000mSec) while the video is shot at 50fps implying 20mSec intervals. This makes synchronisation pretty useless. I've added an output of the position before and after the position change.
Any help would be appreciated.
Here is the output when changing the slider:
New slider position 326
Media player updated position 0
New slider position 816
Media player updated position 0
New slider position 1306
Media player updated position 0
New slider position 1632
Media player updated position 1000
New slider position 1959
Media player updated position 1000
New slider position 2449
Media player updated position 2000
New slider position 2938
Media player updated position 2000
New slider position 3428
Media player updated position 2000
New slider position 3755
Media player updated position 3000
New slider position 4081
Media player updated position 3000
New slider position 4571
Media player updated position 4000
New slider position 4897
Media player updated position 4000
New slider position 5224
Media player updated position 4000
New slider position 5550
Media player updated position 5000
New slider position 5714
Media player updated position 5000
New slider position 6040
Media player updated position 5000
New slider position 6203
Media player updated position 6000
New slider position 6530
I've also tried setting specific positions that I retrieved from the mediaPlayer.position () to no avail.
Here is the contrived app:
import sys
from PyQt5 import QtWidgets
from PyQt5.QtCore import QSize, Qt, QUrl
from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtWidgets import QMainWindow, QLabel, QWidget, QSlider
from PyQt5.QtWidgets import QVBoxLayout, QHBoxLayout
#
# Reference https://pythonprogramminglanguage.com/pyqt5-video-widget/
#
class MainWindow (QMainWindow):
def __init__ (self, parent=None):
super (QMainWindow, self).__init__ (parent)
#
# Set the filename here
#
filename = '/Users/yuval/src/lab/S4560001.MP4'
self.setMinimumSize (QSize (640, 480))
self.setWindowTitle ('Video & Data Viewer and Annotator')
self.mediaPlayer = QMediaPlayer (None, QMediaPlayer.VideoSurface)
videoWidget = QVideoWidget ()
videoWidget.setMinimumSize (640,200)
#
# Position Slider
#
self.positionSlider = QSlider (Qt.Horizontal)
self.positionSlider.setRange (0, 0)
self.positionSlider.sliderMoved.connect (self.setPosition)
#
# Position Label
#
self.positionLabel = QLabel ('00:00:000')
centralWidget = QWidget (self)
self.setCentralWidget (centralWidget)
#
# Layout the Control Widgets
#
ctlLayout = QHBoxLayout ()
ctlLayout.setContentsMargins (0, 0, 0, 0)
ctlLayout.addWidget (self.positionSlider)
ctlLayout.addWidget (self.positionLabel)
#
# Layout the Window
#
layout = QVBoxLayout ()
layout.addWidget (videoWidget)
layout.addLayout (ctlLayout)
centralWidget.setLayout (layout)
self.mediaPlayer.setVideoOutput (videoWidget)
self.mediaPlayer.positionChanged.connect (self.positionChanged)
self.mediaPlayer.durationChanged.connect (self.durationChanged)
self.mediaPlayer.error.connect (self.handleError)
self.mediaPlayer.setNotifyInterval (100)
self.mediaPlayer.setMuted (True)
print (filename)
if filename != '':
self.mediaPlayer.setMedia (
QMediaContent (QUrl.fromLocalFile (filename)))
def positionChanged (self, position):
self.positionSlider.setValue (position)
def durationChanged (self, duration):
self.positionSlider.setRange (0, duration)
def setPosition (self, position):
print (f'New slider position {position}')
self.mediaPlayer.setPosition (position)
print (f'Media player updated position {self.mediaPlayer.position ()}')
def handleError (self):
print ('Error: ' + self.mediaPlayer.errorString ())
if __name__ == '__main__':
app = QtWidgets.QApplication (sys.argv)
mainWin = MainWindow ()
mainWin.show ()
sys.exit (app.exec_ ())
I'm running on MacOS 10.14.16 (Mojave).
Python 3.7.4
Python packages:PyQt5==5.13.0PyQt5-sip==4.19.18
Ports packages:py37-pyqt5 @5.12.2_0 (active)qt5 @5.12.4_0 (active)
Found the answer. The issue is in Qt5 and they "claim" it's not a bug, nor does it seem there are any plans to fix it. It's specific to MacOS and works okay on Windows (and I suspect Linux). The problem is that Qt5 uses a MacOS API that has time tolerance. By default it will only use "keyframes" while it is possible to limit its tolerance. Qt5 does not specify a tolerance therefore it adjusts the time to the keyframes.
If anyone out there is on the MacOS Qt5 development team, it would be nice if you can fix this. And yeah, if I had a development environment I would fix it myself (but I probably would have been voted down anyhow).
The MacOS / AVFoundation API is https://developer.apple.com/documentation/avfoundation/avplayeritem/1387418-seek
这篇关于PyQt QMediaPlayer setPosition 舍入位置值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!