【问题标题】:Why is QMediaPlayer::duration() giving me a value of -1?为什么 QMediaPlayer::duration() 给我的值为-1?
【发布时间】:2017-04-15 06:38:42
【问题描述】:

这是我的代码:

QString BoatProgramming::setDuration(QString path)
{
    if (path.isNull()) { return ""; }
    QMediaPlayer mp;
    mp.setMedia(QUrl::fromLocalFile("/home/akiva/deleteme.ogg"));
    qDebug() << mp.duration(); // Outputting a value of -1

    m_Duration = QString::number(mp.duration());
    emit durationChanged();
    return m_Duration;
}

显然某处存在错误,但除了检查文件名之外,我对问题所在感到遗憾。难道只是不支持.ogg?我是在对象完全加载到内存之前调用函数吗?还是别的什么?

谢谢。

【问题讨论】:

    标签: c++ qt audio qmediaplayer vorbis


    【解决方案1】:

    QMediaPlayer::setMedia()docs 异步执行加载:

    该函数在录制指定的媒体源后立即返回。它不等待媒体完成加载,也不检查错误。监听mediaStatusChanged()error() 信号,以便在媒体加载和加载过程中发生错误时得到通知。

    这意味着在立即调用setMedia() 之后查询QMediaPlayer 以获取duration() 可能不起作用,因为QMediaPlayer 可能尚未加载媒体。

    为了保证在调用duration()之前加载已经完成,你必须监听mediaStatusChanged()信号,只有在mediaStatus()返回QMediaPlayer::LoadedMedia时才能得到duration()。这是一个最小的例子:

    #include <QtWidgets>
    #include <QtMultimedia>
    
    int main(int argc, char* argv[])
    {
        QApplication app(argc, argv);
        QLabel label; //a label to display duration
    
        QString fileName = QFileDialog::getOpenFileName(nullptr, "Open Media File");
    
        QMediaPlayer mp;
        mp.setMedia(QUrl::fromLocalFile(fileName));
        QObject::connect(&mp, &QMediaPlayer::mediaStatusChanged,
                         [&](QMediaPlayer::MediaStatus status){
            if(status == QMediaPlayer::LoadedMedia) //when loading is finished
            {
                //show duration in a label
                qint64 duration= mp.duration();
                label.setText(QString("Duration: %1 ms.\n\nThat is: %2")
                              .arg(duration)
                              .arg(QDateTime::fromTime_t(duration/1000).toUTC()
                                   .toString("hh:mm:ss")));
                label.show();
            }
        });
    
        return app.exec();
    }
    

    【讨论】:

    • 我认为这个问题是不同的。在尝试了 main 中的代码后,一切顺利,因此您的代码可以正常工作。然而,在我自己的课堂上尝试它,我可以等待一年,而那个信号永远不会触发。但是将其更改为:QObject::connect(&amp;m_MediaPlayer, &amp;QMediaPlayer::durationChanged, [&amp;](qint64 fun) 有效。
    • 顺便说一句,我试过用谷歌搜索它,但为了我的爱,我在上面找不到任何东西。 [&amp;] 的语法有什么作用?我从来没有见过这样的东西。
    • @Akiva ,这是一个 C++11 的 lambda 表达式,参见 this question[&amp;] 语法通过引用捕获 lambda 使用的变量。 NOT 对类方法中的局部变量执行此操作,您最终将在 lambda 中使用悬空引用(这可能是事情在 main 中起作用但在您的类中不起作用的原因)。如果您不习惯 lambda 表达式,请使用普通插槽来避免此类问题(即,只需将此 lambda 函数替换为您的类中定义的普通插槽即可)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-25
    • 2010-11-11
    • 1970-01-01
    • 1970-01-01
    • 2021-12-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多