当前位置:编程学习 > wap >>

Qt5 中如何获取音乐文件的详细信息(艺术家、标题、专辑等)

Qt5中对于音频视频的操作用QMediaPlayer,不再使用以前的Phonon,文件的元数据由QMediaMetaData里面的各种枚举来决定,取值由QMediaPlayer::metaData(QMediaMetaData::Title)取音乐文件的标题等!但是经过反复尝试,获取失败。。。求解答!

外文参考:
[qt5] QMediaPlayer - i can`t get metaData 
地址:http://qt-project.org/forums/viewthread/25306 Qt5 metadata 音乐 --------------------编程问答-------------------- QMediaObject::metaData,的提取过程是异步的,你必须等待metaDataChanged信号发射后再取 --------------------编程问答--------------------
引用 1 楼 cai6811376 的回复:
QMediaObject::metaData,的提取过程是异步的,你必须等待metaDataChanged信号发射后再取

添加音乐文件:
player = new QMediaPlayer(this);
player->setPlaylist(playlist);
connect(player, SIGNAL(metaDataChanged()), this, SLOT(test()));

foreach(QString file, file_list)
{
    playlist->addMedia(QUrl::fromLocalFile(file));
    playlist->setCurrentIndex(playlist->mediaCount()-1);
}

void PlayerWidget::test()
{
QStringList string_list = player->availableMetaData();
QString duration_str = player->metaData("Duration").toString();
int channer_count =  player->metaData("ChannelCount").toInt();
QString audio_codec = player->metaData("AudioCodec").toString();
int sample_rate =  player->metaData("SampleRate").toInt();
int audio_bit_rate =  player->metaData("AudioBitRate").toInt();
QStringList auther_list =  player->metaData("Author").toStringList();
QString title = player->metaData(QMediaMetaData::Title).toString();
QString album_title = player->metaData("AlbumTitle").toString();
QStringList genre = player->metaData("Genre").toStringList();
int track_number = player->metaData("TrackNumber").toInt();
int year =  player->metaData("Year").toInt();
QStringList  contributing_artist = player->metaData("ContributingArtist").toStringList();
}

原来我是想通过connect(playlist, SIGNAL(currentIndexChanged(int)), this, SLOT(currentIndexChanged(int)));通过改变下表来获取不同文件的信息,但是一个文件的信息也获取不到。
如上所说metaDataChanged()我添加了多个文件,但是test()方法只能执行一次,只能获取一个文件的信息,求解! --------------------编程问答--------------------     既然QMediaObject::metaData,的提取过程是异步的,倘若我要在添加歌曲文件的的时候一次性直接获取所有歌曲名、艺术家、播放时长,并加到播放列表的QTableWidget,怎么做呢?
    什么时候metaDataChanged信号会发射呢? --------------------编程问答--------------------
引用 3 楼 yh694854389 的回复:
    既然QMediaObject::metaData,的提取过程是异步的,倘若我要在添加歌曲文件的的时候一次性直接获取所有歌曲名、艺术家、播放时长,并加到播放列表的QTableWidget,怎么做呢?
    什么时候metaDataChanged信号会发射呢?

亲,你这不是我想问的么?我没解决呢!待高人指点 --------------------编程问答-------------------- 我看了Qt5的例子,好像是在更换了元数据的时候才发射metaDataChanged这个信号。比方说在播放一个音频文件时,更换到另一个音频文件就会有metaDataChanged这个信号。
我看他里面是这样实现的:
1、程序初始化时:connect(player, SIGNAL(metaDataChanged()), SLOT(metaDataChanged()));
2、程序初始化时直接就调用了metaDataChanged();
3、metaDataChanged()槽函数如下:
void Player::metaDataChanged()
{
    if (player->isMetaDataAvailable()) {
        setTrackInfo(QString("%1 - %2")
                .arg(player->metaData(QMediaMetaData::AlbumArtist).toString())
                .arg(player->metaData(QMediaMetaData::Title).toString()));

        if (coverLabel) {
            QUrl url = player->metaData(QMediaMetaData::CoverArtUrlLarge).value<QUrl>();

            coverLabel->setPixmap(!url.isEmpty()
                    ? QPixmap(url.toString())
                    : QPixmap());
        }
    }
}
--------------------编程问答--------------------
引用 5 楼 wlxj8284 的回复:
我看了Qt5的例子,好像是在更换了元数据的时候才发射metaDataChanged这个信号。比方说在播放一个音频文件时,更换到另一个音频文件就会有metaDataChanged这个信号。
我看他里面是这样实现的:
1、程序初始化时:connect(player, SIGNAL(metaDataChanged()), SLOT(metaDataChanged()));
2、程序初始化时直接就调用了metaDataChanged();
3、metaDataChanged()槽函数如下:
void Player::metaDataChanged()
{
    if (player->isMetaDataAvailable()) {
        setTrackInfo(QString("%1 - %2")
                .arg(player->metaData(QMediaMetaData::AlbumArtist).toString())
                .arg(player->metaData(QMediaMetaData::Title).toString()));

        if (coverLabel) {
            QUrl url = player->metaData(QMediaMetaData::CoverArtUrlLarge).value<QUrl>();

            coverLabel->setPixmap(!url.isEmpty()
                    ? QPixmap(url.toString())
                    : QPixmap());
        }
    }
}


这个貌似只能获取当前播放的歌曲信息,那么如果有10个歌曲文件,我不去播放,又如何去分别获取呢? --------------------编程问答-------------------- 这个我感觉是不能啊,因为从这个函数可以看出,Player得到的数据都是当前的。 --------------------编程问答--------------------
引用 7 楼 wlxj8284 的回复:
这个我感觉是不能啊,因为从这个函数可以看出,Player得到的数据都是当前的。

是滴,看来只能用其他库了。。。 --------------------编程问答--------------------
引用 5 楼 wlxj8284 的回复:
我看了Qt5的例子,好像是在更换了元数据的时候才发射metaDataChanged这个信号。比方说在播放一个音频文件时,更换到另一个音频文件就会有metaDataChanged这个信号。
我看他里面是这样实现的:
1、程序初始化时:connect(player, SIGNAL(metaDataChanged()), SLOT(metaDataChanged()));
2、程序初始化时直接就调用了metaDataChanged();
3、metaDataChanged()槽函数如下:
void Player::metaDataChanged()
{
    if (player->isMetaDataAvailable()) {
        setTrackInfo(QString("%1 - %2")
                .arg(player->metaData(QMediaMetaData::AlbumArtist).toString())
                .arg(player->metaData(QMediaMetaData::Title).toString()));

        if (coverLabel) {
            QUrl url = player->metaData(QMediaMetaData::CoverArtUrlLarge).value<QUrl>();

            coverLabel->setPixmap(!url.isEmpty()
                    ? QPixmap(url.toString())
                    : QPixmap());
        }
    }
}


请问,我用Qt5.1里的player那个demo,编译运行成功,但是只能播音频,播放视频就会报错,视频文件格式是mkv,报错信息是如下。能帮忙看下是哪里的问题吗?一直找不到头绪。
(<unknown>:16616): GVFS-RemoteVolumeMonitor-WARNING **: cannot connect to the session bus: org.freedesktop.DBus.Error.NoReply: Did not receive a reply. Possible causes include: the remote application did not send a reply, the message bus security policy blocked the reply, the reply timeout expired, or the network connection was broken.

(<unknown>:16616): GStreamer-CRITICAL **: gst_ghost_pad_new: assertion `GST_IS_PAD (target)' failed

(<unknown>:16616): GStreamer-CRITICAL **: gst_object_unref: assertion `object != NULL' failed

(<unknown>:16616): GStreamer-CRITICAL **: gst_element_add_pad: assertion `GST_IS_PAD (pad)' failed

(<unknown>:16616): GStreamer-CRITICAL **: gst_pad_link: assertion `GST_IS_PAD (sinkpad)' failed
/mnt/hgfs/share/video-player/build-player-Desktop_Qt_5_1_1_GCC_64bit-Debug/player exited with code 0 --------------------编程问答-------------------- 我想到的是,如果初始化的时候将全部歌播一次,拿数据~,怎么样 --------------------编程问答-------------------- 我想能不能初始化的时候播放列表的歌全部播一次拿出想要的数据啊? --------------------编程问答--------------------
引用 11 楼 zx0450 的回复:
我想能不能初始化的时候播放列表的歌全部播一次拿出想要的数据啊?

如果为了取数据二去全部播放不太好,效率太差。我也没找到怎么全部获取信息,看来得用第三方库了。。。 --------------------编程问答-------------------- 楼主你好,请问你是用哪个第三方库实现了? --------------------编程问答--------------------
引用 13 楼 u012750421 的回复:
楼主你好,请问你是用哪个第三方库实现了?

我现在还没有实现呢,一直没时间做,使用ffmpeg、taglib都是可以的! --------------------编程问答--------------------
引用 14 楼 u011012932 的回复:
Quote: 引用 13 楼 u012750421 的回复:

楼主你好,请问你是用哪个第三方库实现了?

我现在还没有实现呢,一直没时间做,使用ffmpeg、taglib都是可以的!

感觉taglib更好点,专门读取音乐元数据,之前我看过gstreamer,操作元数据需要创建一个组件,把文件装入组件,然后从衬垫获取数据,感觉这种方法似乎并不是很好
补充:移动开发 ,  Qt
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,