解决QMediaPlayer多次获取元数据重复的问题

请看如下代码:使用队列将选中加载元数据并显示出来

void LocalDownload::loadNextSong() {
    if (!m_songQueue.isEmpty()) {
        this->m_mediaPath = m_songQueue.dequeue();  // 取出队列中的下一首歌路径
        qDebug()<<"取出歌曲 : "<<this->m_mediaPath<<"=================";
       
 // 在加载新媒体前,重置媒体状态
        this->m_player->stop();
        this->m_player->setSource(QUrl());  // 清空当前媒体源
        this->m_player->play(); 

        this->m_player->setSource(QUrl::fromLocalFile(this->m_mediaPath));
        this->m_player->play();  // 触发状态改变信号,获取元数据信息
    }
}

void LocalDownload::on_local_add_toolButton_clicked() {
    QString musicPath = QStandardPaths::standardLocations(QStandardPaths::MusicLocation).first();
    QStringList paths = QFileDialog::getOpenFileNames(this, QStringLiteral("添加音乐"), musicPath, "Music (*.mp3 *.aac *.wav)");
    if (paths.isEmpty())return;
    //QString fileName = QUrl::fromLocalFile(path).fileName();
    //qDebug() << "插入:"<<paths.size()<<"条数据";
    for(auto& path : paths) {
        //qDebug()<<"添加歌曲 :"<<path;
        this->m_songQueue.enqueue(path);
    }
    this->loadNextSong();
}
connect(m_player.get(), &QMediaPlayer::mediaStatusChanged, [=](const QMediaPlayer::MediaStatus& status) {
        if (status == QMediaPlayer::LoadedMedia) {
            //qDebug()<<"媒体状态改变,加载完成";
            //qDebug()<<"元数据加载完成";
            const QMediaMetaData data = this->m_player->metaData();
            for(auto val : data.keys()) {
                qDebug()<<val<<": "<<data.value(val).toString();
            }
            // 停止播放
            this->m_player->stop();
            //获取标题
            auto title = data.value(QMediaMetaData::Title).toString();
            if(!re.match(title).hasMatch()) {
                title = QUrl::fromLocalFile(this->m_mediaPath).fileName();
                title = title.first(title.lastIndexOf('.'));
            }
            //获取歌手
            auto singer = data.value(QMediaMetaData::ContributingArtist).toString();
            if(!re.match(singer).hasMatch())singer = QStringLiteral("网络歌手");
            //获取封面
            auto cover = data.value(QMediaMetaData::ThumbnailImage).value<QPixmap>();
            if(cover.isNull()) {
                //qDebug()<<"封面为空";
                cover = QPixmap(QString("://Res/tablisticon/pix%1.png").arg(QRandomGenerator::global()->bounded(1,11)));
            }
            //获取时长
            const auto duration = data.value(QMediaMetaData::Duration).value<qint64>();
            //信息赋值
            SongInfor tempInformation;
            tempInformation.index = this->m_locationMusicVector.size()+1;//让他先加1
            tempInformation.cover = cover;
            tempInformation.songName = title;
            tempInformation.signer = singer;
            tempInformation.duration = QTime::fromMSecsSinceStartOfDay(duration).toString("mm:ss");
            tempInformation.mediaPath = this->m_mediaPath;
            tempInformation.addTime = QDateTime::currentDateTime();
            //判重(通过元数据信息)
            auto it = std::find(this->m_locationMusicVector.begin(),
            this->m_locationMusicVector.end(),tempInformation);
            if(it == this->m_locationMusicVector.end())this->m_locationMusicVector.emplace_back(tempInformation);
            else {
                //qDebug()<<title<<"已存在,请勿重复插入";
                //加载下一首歌
                loadNextSong();
                return;
            }
            //向parent发送添加MediaPath的信号
            emit addSongInfo(tempInformation);
            //加载相关信息
            auto item = new MusicItemWidget(tempInformation, this);
            item->setFillColor(QColor(QStringLiteral("#B0EDF6")));
            item->setRadius(12);
            item->setInterval(1);
            auto index = tempInformation.index;// 捕获当前的 index
            connect(item, &MusicItemWidget::playRequest, this, [index, this] {
                emit playMusic(index);
            });
            dynamic_cast<QVBoxLayout*>(ui->local_song_list_widget->layout())->insertWidget(ui->local_song_list_widget->layout()->count() - 1, item);
            ui->local_music_number_label->setText(QString::number(this->m_locationMusicVector.size()));
            //加载下一首歌
            loadNextSong();
        }
    });

再重复选中相同的歌曲后,会出现如下情况:

 实际元数据集信息与歌曲不符,有明显的滞后嫌疑,但是我已经尽量做到在加载新媒体前,重置媒体状态,还是没用。不得已出此下策:每次加载元数据前重置player。这是迫不得已的做法,非常无奈。如下:

void LocalDownload::getMetaData() {
    //经过一段时间的搜索得到的结论,如果想不调用play()就获得元数据信息是不现实的,能做到的也就只有加载完成之后立马停止
    connect(m_player.get(), &QMediaPlayer::mediaStatusChanged, [=](const QMediaPlayer::MediaStatus& status) {
        if (status == QMediaPlayer::LoadedMedia) {
            //qDebug()<<"媒体状态改变,加载完成";
            //qDebug()<<"元数据加载完成";
            const QMediaMetaData data = this->m_player->metaData();
            for(auto val : data.keys()) {
                qDebug()<<val<<": "<<data.value(val).toString();
            }
            // 停止播放
            this->m_player->stop();
            //获取标题
            auto title = data.value(QMediaMetaData::Title).toString();
            if(!re.match(title).hasMatch()) {
                title = QUrl::fromLocalFile(this->m_mediaPath).fileName();
                title = title.first(title.lastIndexOf('.'));
            }
            //获取歌手
            auto singer = data.value(QMediaMetaData::ContributingArtist).toString();
            if(!re.match(singer).hasMatch())singer = QStringLiteral("网络歌手");
            //获取封面
            auto cover = data.value(QMediaMetaData::ThumbnailImage).value<QPixmap>();
            if(cover.isNull()) {
                //qDebug()<<"封面为空";
                cover = QPixmap(QString("://Res/tablisticon/pix%1.png").arg(QRandomGenerator::global()->bounded(1,11)));
            }
            //获取时长
            const auto duration = data.value(QMediaMetaData::Duration).value<qint64>();
            //信息赋值
            SongInfor tempInformation;
            tempInformation.index = this->m_locationMusicVector.size()+1;//让他先加1
            tempInformation.cover = cover;
            tempInformation.songName = title;
            tempInformation.signer = singer;
            tempInformation.duration = QTime::fromMSecsSinceStartOfDay(duration).toString("mm:ss");
            tempInformation.mediaPath = this->m_mediaPath;
            tempInformation.addTime = QDateTime::currentDateTime();
            //判重(通过元数据信息)
            auto it = std::find(this->m_locationMusicVector.begin(),
            this->m_locationMusicVector.end(),tempInformation);
            if(it == this->m_locationMusicVector.end())this->m_locationMusicVector.emplace_back(tempInformation);
            else {
                //qDebug()<<title<<"已存在,请勿重复插入";
                //加载下一首歌
                loadNextSong();
                return;
            }
            //向parent发送添加MediaPath的信号
            emit addSongInfo(tempInformation);
            //加载相关信息
            auto item = new MusicItemWidget(tempInformation, this);
            item->setFillColor(QColor(QStringLiteral("#B0EDF6")));
            item->setRadius(12);
            item->setInterval(1);
            auto index = tempInformation.index;// 捕获当前的 index
            connect(item, &MusicItemWidget::playRequest, this, [index, this] {
                emit playMusic(index);
            });
            dynamic_cast<QVBoxLayout*>(ui->local_song_list_widget->layout())->insertWidget(ui->local_song_list_widget->layout()->count() - 1, item);
            ui->local_music_number_label->setText(QString::number(this->m_locationMusicVector.size()));
            //加载下一首歌
            loadNextSong();
        }
    });
}

void LocalDownload::loadNextSong() {
    if (!m_songQueue.isEmpty()) {
        this->m_mediaPath = m_songQueue.dequeue();  // 取出队列中的下一首歌路径
        //qDebug()<<"取出歌曲 : "<<this->m_mediaPath<<"=================";

        /*// 在加载新媒体前,重置媒体状态
        this->m_player->stop();
        this->m_player->setSource(QUrl());  // 清空当前媒体源
        this->m_player->play();*/ //不起效果

        // 释放并重建 QMediaPlayer 对象
        this->m_player = std::make_unique<QMediaPlayer>(this);//它会自动释放之前的对象
        getMetaData();

        this->m_player->setSource(QUrl::fromLocalFile(this->m_mediaPath));
        this->m_player->play();  // 触发状态改变信号,获取元数据信息
    }
}

猜你喜欢

转载自blog.csdn.net/m0_74091159/article/details/142984676