【问题标题】:Qt wrong duration with variable bitrateQt错误的持续时间与可变比特率
【发布时间】:2016-09-19 15:57:57
【问题描述】:

QMediaPlayer 使用可变比特率 mp3 计算错误的持续时间。是的,我知道similar topic 已经打开,但已经很旧了(2012 年)。此外,VLC 和 Clementine,使用 Qt,对于相同的 mp3 文件都可以计算出确切的持续时间。所以,我不认为这是一个 Qt 错误。

我是这样取mp3时长的:

void MainWindow::playerOnMediaStatusChanged(QMediaPlayer::MediaStatus status) {
    if (status == QMediaPlayer::BufferedMedia) {
        qint64 duration = player->duration(); //wrong 
    }
}

你能帮帮我吗?

【问题讨论】:

  • 在哪个平台上? (即使用哪个 qtmultimedia 后端)它需要在 Qt 和/或底层后端库中修复,所以最好是提交 Qt 错误
  • Qt 5.7、Windows 7 和 DirectShow 作为后端

标签: c++ qt mp3 bitrate


【解决方案1】:

QtMultiMedia::QMediaPlayer 无法识别可变比特率模式。

它会给你错误的持续时间和错误的位置。

您可以修补 QMediaPlayer 来计算实际位置/持续时间。

Python/PySide2 示例:

# Created by BaiJiFeiLong@gmail.com at 2022/2/22 21:39
import taglib
from IceSpringPathLib import Path
from PySide2 import QtMultimedia, QtCore


class PatchedMediaPlayer(QtMultimedia.QMediaPlayer):
    durationChanged: QtCore.SignalInstance = QtCore.Signal(int)
    positionChanged: QtCore.SignalInstance = QtCore.Signal(int)

    def __init__(self):
        super().__init__()
        self._realDuration = 0
        self._lastFakePosition = 0
        self._bugRate = 0.0
        super().durationChanged.connect(self._onSuperDurationChanged)
        super().positionChanged.connect(self._onSuperPositionChanged)

    def _onSuperDurationChanged(self, duration: int):
        self._bugRate = duration / self._realDuration
        self.durationChanged.emit(self._realDuration)

    def _onSuperPositionChanged(self):
        self.positionChanged.emit(self.position())

    def setMedia(self, media: QtMultimedia.QMediaContent, stream: QtCore.QIODevice = None, realDuration=None) -> None:
        self.blockSignals(True)
        super().setMedia(media, stream)
        self.blockSignals(False)
        self._realDuration = realDuration
        self._lastFakePosition = 0
        self._bugRate = 0.0
        if realDuration is None:
            filename = media.canonicalUrl().toLocalFile()
            file = taglib.File(filename)
            bitrate = file.bitrate
            file.close()
            self._realDuration = Path(filename).stat().st_size * 8 // bitrate

    def setPosition(self, position: int) -> None:
        assert self._bugRate != 0 or position == 0
        fakePosition = int(position * self._bugRate)
        super().setPosition(int(position * self._bugRate))
        self._lastFakePosition = fakePosition

    def duration(self) -> int:
        return self._realDuration

    def position(self) -> int:
        elapsed = super().position() - self._lastFakePosition
        lastPosition = 0 if self._lastFakePosition == 0 else int(self._lastFakePosition / self._bugRate)
        realPosition = lastPosition + elapsed
        realPosition = max(realPosition, 0)
        realPosition = min(realPosition, self._realDuration)
        return realPosition

要求:pip install pytaglib==1.4.6,或任何其他获取真实比特率的库

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-25
    • 2022-10-15
    • 2015-06-12
    • 1970-01-01
    • 2013-12-01
    • 2016-11-01
    相关资源
    最近更新 更多