QMediaPlayer.setPosition 如何用于 mp3?

How QMediaPlayer.setPosition works for mp3?

当我尝试从某个位置播放歌曲时遇到问题:它不起作用(歌曲从头开始播放)。

只有当歌曲是 'mp3' 歌曲而不是 'm4a' 歌曲时才会出现此问题(它们是我测试的唯一格式)。

问题似乎来自 qt(或 PyQt?),但我不确定,这是一个最小的示例,我是否遗漏了什么?

from PyQt5.QtWidgets import QApplication
from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer
from PyQt5.QtCore import QUrl

if __name__ == "__main__":
    app = QApplication([])

    player = QMediaPlayer()
    media_content = QMediaContent(QUrl.fromLocalFile("path_to_my_music_file.mp3"))
    player.setMedia(media_content)
    player.setPosition(10000)
    player.play()

    app.exec_()

setMedia() 是异步的:

Note: This function returns immediately after recording the specified source of the media. It does not wait for the media to finish loading and does not check for errors. Listen for the mediaStatusChanged() and error() signals to be notified when the media is loaded and when an error occurs during loading.

由于 MP3 文件的性质,Qt 可能需要一些时间才能正确搜索。不幸的是,据我所知,这只能在播放文件 一段时间后才能完成。

一个可能的解决方案是连接到一个自定义函数,该函数延迟 setPosition 直到媒体变得可搜索。

这是一个应该处理它的子类(我只测试了 mp3 文件,所以你应该用其他文件类型尝试它以确保它正常工作)。

class Player(QMediaPlayer):
    _delayedPos = 0
    def setPosition(self, pos):
        super().setPosition(pos)
        if pos and not self.isSeekable():
            self._delayedPos = pos
            try:
                # ensure that the connection is done only once
                self.seekableChanged.connect(self.delaySetPosition, Qt.UniqueConnection)
            except:
                pass
        else:
            self._delayedPos = 0

    def delaySetPosition(self, seekable):
        if seekable:
            self.setPosition(self._delayedPos)
        try:
            # just to be safe, in case the media changes before the previous one
            # becomes seekable
            self.seekableChanged.disconnect(self.delaySetPosition)
        except:
            pass

关注@musicamante 的回答;更强大的版本是使用以下信号之一:

最好的选择是 mediaStatusChanged,它允许您检查 QMediaPlayer::MediaStatus :

from PyQt5.QtWidgets import QApplication
from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer
from PyQt5.QtCore import QUrl

def update_position(status):
    if(status == QMediaPlayer.LoadedMedia):
        player.setPosition(10000)
        player.play()

if __name__ == "__main__":
    app = QApplication([])

    player = QMediaPlayer()
    media_content = QMediaContent(QUrl.fromLocalFile("path_to_my_music_file.mp3"))
    player.mediaStatusChanged.connect(update_position)
    player.setMedia(media_content)

    app.exec_()