PyQt QMediaPlayer setPosition ปัดเศษค่าตำแหน่ง

ฉันมีแอปที่ออกแบบมาเพื่อช่วยซิงโครไนซ์วิดีโอการทดลองและสัญญาณข้อมูล แอปมีวิดเจ็ตวิดีโอและแถบเลื่อนที่สามารถกำหนดตำแหน่งชั่วคราวของวิดีโอได้ อย่างไรก็ตาม QMediaPlayer จะตั้งค่าตำแหน่งที่ช่วงเวลา 500mSec/1000mSec เท่านั้น (ในแอปของฉัน 500mSec/ในแอปที่วางแผนไว้ 1000mSec) ในขณะที่วิดีโอถูกถ่ายที่ 50fps ซึ่งหมายถึงช่วงเวลา 20mSec ทำให้การซิงโครไนซ์ค่อนข้างไร้ประโยชน์ ฉันได้เพิ่มผลลัพธ์ของตำแหน่งก่อนและหลังการเปลี่ยนตำแหน่งแล้ว

ความช่วยเหลือใด ๆ ที่จะได้รับการชื่นชม

นี่คือผลลัพธ์เมื่อเปลี่ยนแถบเลื่อน:

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

ฉันได้ลองตั้งค่าตำแหน่งเฉพาะที่ฉันดึงมาจาก mediaPlayer.position () โดยไม่มีประโยชน์

นี่คือแอปที่สร้างสรรค์:

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

ฉันใช้ MacOS 10.14.16 (Mojave)

หลาม 3.7.4

แพ็คเกจ Python: PyQt5==5.13.0 PyQt5-sip==4.19.18

แพ็คเกจพอร์ต: py37-pyqt5 @5.12.2_0 (ใช้งานอยู่) qt5 @5.12.4_0 (ใช้งานอยู่)


person YuvGM    schedule 11.09.2019    source แหล่งที่มา


คำตอบ (1)


พบคำตอบแล้ว ปัญหาอยู่ใน Qt5 และพวกเขา "อ้างว่า" ไม่ใช่จุดบกพร่อง และดูเหมือนว่าจะไม่มีแผนที่จะแก้ไข มันเฉพาะกับ MacOS และใช้งานได้ดีบน Windows (และฉันสงสัยว่า Linux) ปัญหาคือ Qt5 ใช้ MacOS API ที่มีความทนทานต่อเวลา โดยค่าเริ่มต้น จะใช้เฉพาะ "คีย์เฟรม" ในขณะที่สามารถจำกัดความทนทานได้ Qt5 ไม่ได้ระบุพิกัดความเผื่อ ดังนั้นจึงปรับเวลาให้กับคีย์เฟรม

หากมีใครอยู่ในทีมพัฒนา MacOS Qt5 คงจะดีถ้าคุณสามารถแก้ไขปัญหานี้ได้ และใช่ ถ้าฉันมีสภาพแวดล้อมการพัฒนา ฉันจะแก้ไขมันเอง (แต่ฉันคงถูกโหวตไม่ลงอยู่ดี)

ดู (ตั้งแต่ปี 2015) https://bugreports.qt.io/browse/QTBUG-49609?jql=project%20%3D%20QTBUG%20AND%20solution%20%3D%20Unresolved%20AND%20text%20~%20%22qmediaplayer%22%20ORDER%20BY%20priority%20DESC%2C%20updated%20DESC

MacOS / AVFoundation API คือ https://developer.apple.com/documentation/avfoundation/avplayeritem/1387418-seek

person YuvGM    schedule 16.09.2019
comment
คุณสามารถแก้ไขได้โดยการเข้ารหัสวิดีโอโดยใช้ B-frames และ P-frames น้อยลง กล่าวคือ ใช้ I-frame ให้มากขึ้น โดยเฉพาะอย่างยิ่งยังไม่ชัดเจนว่าคุณไม่สามารถหา B-frames ได้ การค้นหา P-frame นั้นง่ายกว่ามาก นอกจากนี้ยังมีการใช้หน่วยความจำน้อยลงในการเล่น แต่ขนาดไฟล์เพิ่มขึ้น - person artless noise; 29.03.2020