[수정2]Qt mp3파일 앨범사진 추출에 관련해서 질문이 있습니다.

lalupo20의 이미지

    QWidget *m_metaDataFields[QMediaMetaData::NumMetaData] = {};
    QLabel *m_metaDataLabels[QMediaMetaData::NumMetaData] = {};
 
 
-----------------------------------------------------------------------------
 
Player::Player(QWidget *parent) : QWidget(parent)
{
    //! [create-objs]
    m_player = new QMediaPlayer(this);
    m_audioOutput = new QAudioOutput(this);
    m_player->setAudioOutput(m_audioOutput);
    //! [create-objs]
    connect(m_player, &QMediaPlayer::durationChanged, this, &Player::durationChanged);
    connect(m_player, &QMediaPlayer::positionChanged, this, &Player::positionChanged);
    connect(m_player, QOverload<>::of(&QMediaPlayer::metaDataChanged), this,
            &Player::metaDataChanged);
    connect(m_player, &QMediaPlayer::mediaStatusChanged, this, &Player::statusChanged);
    connect(m_player, &QMediaPlayer::bufferProgressChanged, this, &Player::bufferingProgress);
    connect(m_player, &QMediaPlayer::hasVideoChanged, this, &Player::videoAvailableChanged);
    connect(m_player, &QMediaPlayer::errorChanged, this, &Player::displayErrorMessage);
    connect(m_player, &QMediaPlayer::tracksChanged, this, &Player::tracksChanged);
 
    //! [2]
    m_videoWidget = new VideoWidget(this);
    m_videoWidget->resize(1280, 720);
    m_player->setVideoOutput(m_videoWidget);
 
    m_playlistModel = new PlaylistModel(this);
    m_playlist = m_playlistModel->playlist();
    //! [2]
    connect(m_playlist, &QMediaPlaylist::currentIndexChanged, this,
            &Player::playlistPositionChanged);
 
    // player layout
    QBoxLayout *layout = new QVBoxLayout(this);
 
    // display
    QBoxLayout *displayLayout = new QHBoxLayout;
    displayLayout->addWidget(m_videoWidget, 2);
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
    m_playlistView = new QListView();
    m_playlistView->setModel(m_playlistModel);
    m_playlistView->setCurrentIndex(m_playlistModel->index(m_playlist->currentIndex(), 0));
    connect(m_playlistView, &QAbstractItemView::activated, this, &Player::jump);
    displayLayout->addWidget(m_playlistView);
#endif
    layout->addLayout(displayLayout);
 
    // duration slider and label
    QHBoxLayout *hLayout = new QHBoxLayout;
 
    m_slider = new QSlider(Qt::Horizontal, this);
    m_slider->setRange(0, m_player->duration());
    connect(m_slider, &QSlider::sliderMoved, this, &Player::seek);
    hLayout->addWidget(m_slider);
 
    m_labelDuration = new QLabel();
    m_labelDuration->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
    hLayout->addWidget(m_labelDuration);
    layout->addLayout(hLayout);
 
    // controls
    QBoxLayout *controlLayout = new QHBoxLayout;
    controlLayout->setContentsMargins(0, 0, 0, 0);
 
    QPushButton *openButton = new QPushButton(tr("Open"), this);
    connect(openButton, &QPushButton::clicked, this, &Player::open);
    controlLayout->addWidget(openButton);
    controlLayout->addStretch(1);
 
    PlayerControls *controls = new PlayerControls();
    controls->setState(m_player->playbackState());
    controls->setVolume(m_audioOutput->volume());
    controls->setMuted(controls->isMuted());
 
    connect(controls, &PlayerControls::play, m_player, &QMediaPlayer::play);
    connect(controls, &PlayerControls::pause, m_player, &QMediaPlayer::pause);
    connect(controls, &PlayerControls::stop, m_player, &QMediaPlayer::stop);
    connect(controls, &PlayerControls::next, m_playlist, &QMediaPlaylist::next);
    connect(controls, &PlayerControls::previous, this, &Player::previousClicked);
    connect(controls, &PlayerControls::changeVolume, m_audioOutput, &QAudioOutput::setVolume);
    connect(controls, &PlayerControls::changeMuting, m_audioOutput, &QAudioOutput::setMuted);
    connect(controls, &PlayerControls::changeRate, m_player, &QMediaPlayer::setPlaybackRate);
    connect(controls, &PlayerControls::stop, m_videoWidget, QOverload<>::of(&QVideoWidget::update));
 
    connect(m_player, &QMediaPlayer::playbackStateChanged, controls, &PlayerControls::setState);
    connect(m_audioOutput, &QAudioOutput::volumeChanged, controls, &PlayerControls::setVolume);
    connect(m_audioOutput, &QAudioOutput::mutedChanged, controls, &PlayerControls::setMuted);
 
    controlLayout->addWidget(controls);
    controlLayout->addStretch(1);
 
    m_fullScreenButton = new QPushButton(tr("FullScreen"), this);
    m_fullScreenButton->setCheckable(true);
    controlLayout->addWidget(m_fullScreenButton);
 
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
    m_audioOutputCombo = new QComboBox(this);
    m_audioOutputCombo->addItem(QString::fromUtf8("Default"), QVariant::fromValue(QAudioDevice()));
    for (auto &deviceInfo : QMediaDevices::audioOutputs())
        m_audioOutputCombo->addItem(deviceInfo.description(), QVariant::fromValue(deviceInfo));
    connect(m_audioOutputCombo, QOverload<int>::of(&QComboBox::activated), this,
            &Player::audioOutputChanged);
    controlLayout->addWidget(m_audioOutputCombo);
#endif
 
    layout->addLayout(controlLayout);
 
    // tracks
    QGridLayout *tracksLayout = new QGridLayout;
 
    m_audioTracks = new QComboBox(this);
    connect(m_audioTracks, &QComboBox::activated, this, &Player::selectAudioStream);
    tracksLayout->addWidget(new QLabel(tr("Audio Tracks:")), 0, 0);
    tracksLayout->addWidget(m_audioTracks, 0, 1);
 
    m_videoTracks = new QComboBox(this);
    connect(m_videoTracks, &QComboBox::activated, this, &Player::selectVideoStream);
    tracksLayout->addWidget(new QLabel(tr("Video Tracks:")), 1, 0);
    tracksLayout->addWidget(m_videoTracks, 1, 1);
 
    m_subtitleTracks = new QComboBox(this);
    connect(m_subtitleTracks, &QComboBox::activated, this, &Player::selectSubtitleStream);
    tracksLayout->addWidget(new QLabel(tr("Subtitle Tracks:")), 2, 0);
    tracksLayout->addWidget(m_subtitleTracks, 2, 1);
 
    layout->addLayout(tracksLayout);
 
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
    // metadata
 
    QLabel *metaDataLabel = new QLabel(tr("Metadata for file:"));
    layout->addWidget(metaDataLabel);
 
    QGridLayout *metaDataLayout = new QGridLayout;
    int key = QMediaMetaData::Title;
    for (int i = 0; i < (QMediaMetaData::NumMetaData + 2) / 3; i++) {
        for (int j = 0; j < 6; j += 2) {
            m_metaDataLabels[key] = new QLabel(
                    QMediaMetaData::metaDataKeyToString(static_cast<QMediaMetaData::Key>(key)));
            if (key == QMediaMetaData::ThumbnailImage || key == QMediaMetaData::CoverArtImage)
                m_metaDataFields[key] = new QLabel;
            else
                m_metaDataFields[key] = new QLineEdit;
            m_metaDataLabels[key]->setDisabled(true);
            m_metaDataFields[key]->setDisabled(true);
            metaDataLayout->addWidget(m_metaDataLabels[key], i, j);
            metaDataLayout->addWidget(m_metaDataFields[key], i, j + 1);
            key++;
            if (key == QMediaMetaData::NumMetaData)
                break;
        }
    }
 
    layout->addLayout(metaDataLayout);
#endif
 
#if defined(Q_OS_QNX)
    // On QNX, the main window doesn't have a title bar (or any other decorations).
    // Create a status bar for the status information instead.
    m_statusLabel = new QLabel;
    m_statusBar = new QStatusBar;
    m_statusBar->addPermanentWidget(m_statusLabel);
    m_statusBar->setSizeGripEnabled(false); // Without mouse grabbing, it doesn't work very well.
    layout->addWidget(m_statusBar);
#endif
 
    setLayout(layout);
 
    if (!isPlayerAvailable()) {
        QMessageBox::warning(this, tr("Service not available"),
                             tr("The QMediaPlayer object does not have a valid service.\n"
                                "Please check the media service plugins are installed."));
 
        controls->setEnabled(false);
        if (m_playlistView)
            m_playlistView->setEnabled(false);
        openButton->setEnabled(false);
        m_fullScreenButton->setEnabled(false);
    }
 
    metaDataChanged();
}
 
----------------------------------------------------------------------
 
 
void Player::metaDataChanged()
{
    auto metaData = m_player->metaData();
    setTrackInfo(QString("%1 - %2")
                         .arg(metaData.value(QMediaMetaData::AlbumArtist).toString())
                         .arg(metaData.value(QMediaMetaData::Title).toString()));
 
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
    for (int i = 0; i < QMediaMetaData::NumMetaData; i++) {
        if (QLineEdit *field = qobject_cast<QLineEdit *>(m_metaDataFields[i]))
            field->clear();
        else if (QLabel *label = qobject_cast<QLabel *>(m_metaDataFields[i]))
            label->clear();
        m_metaDataFields[i]->setDisabled(true);
        m_metaDataLabels[i]->setDisabled(true);
    }
 
    for (auto &key : metaData.keys()) {
        int i = int(key);
        if (key == QMediaMetaData::CoverArtImage) {
            QVariant v = metaData.value(key);
            if (QLabel *cover = qobject_cast<QLabel *>(m_metaDataFields[key])) {
                QImage coverImage = v.value<QImage>();
                cover->setPixmap(QPixmap::fromImage(coverImage));
            }
        } else if (key == QMediaMetaData::ThumbnailImage) {
            QVariant v = metaData.value(key);
            if (QLabel *thumbnail = qobject_cast<QLabel *>(m_metaDataFields[key])) {
                QImage thumbnailImage = v.value<QImage>();
                thumbnail->setPixmap(QPixmap::fromImage(thumbnailImage));
            }
        } else if (QLineEdit *field = qobject_cast<QLineEdit *>(m_metaDataFields[key])) {
            QString stringValue = metaData.stringValue(key);
            field->setText(stringValue);
        }
        m_metaDataFields[i]->setDisabled(false);
        m_metaDataLabels[i]->setDisabled(false);
    }
#endif
}

일단 위 소스는 Qt 설치하면 들어 있는 예제 파일에서 따 왔습니다.

위와 같은 코드를 보고

void MainWindow::metaDataChanged() {
    metaData = mediaPlayer->metaData();
    titleLabel->setText(metaData.stringValue(QMediaMetaData::Title));
    albumLabel->setText(metaData.stringValue(QMediaMetaData::AlbumTitle));
    artistLabel->setText(metaData.stringValue(QMediaMetaData::AlbumArtist));
 
 
    QVariant var = metaData.value(QMediaMetaData::CoverArtImage);
    QImage image = var.value<QImage>();
 
    albumArtLabel->setPixmap(QPixmap::fromImage(image));
}

아래와 같은 코드를 작성했는데 작동하지 않네요.

예제 프로젝트에서 메타데이터와 관련 있는 부분을 다 올려봅니다.

제가 빼먹은게 있는지 한번만 봐주셨으면 해서 올립니다.

lalupo20의 이미지

추가로 곡명이나 앨범명 가수명은 정상적으로 받아왔습니다.

라스코니의 이미지

글쎄요... 음

QImage *image = new QImage(var.value<QImage>());
albumArtLabel->setPixmap(QPixmap::fromImage(*image));
lalupo20의 이미지

혹시나 안드로이드 상에서 버그가 있는건가 싶어서 피씨용으로 설정하고 빌드해봤는데 똑같이 작동 안합니다...

그리고 위에 적어 놓은 예제 프로젝트도 이미지출력 못하는거 같구요.

기본 예제가 정상 작동 안하니 답답하네여;

라스코니의 이미지

mp3 파일에 이미지가 들어 있는 것은 확인 가능한가요?

lalupo20의 이미지

근데 똑같은 코드인데 왜 작동 안하는지...

제가 만든거는 피씨나 안드로이드나 둘다 이미지 출력 안되구요...

예제 소스 분석 좀 해봐야 될거 같아요.

lalupo20의 이미지

앨범이미지 들어 있는 파일들은 맞습니다...

예전에 ndk로 개발할때 taglib라는 라이브러리 써서 앨범사진 빼왔던 파일들이거든요...

라스코니의 이미지

mp3 플레이어로 플레이해보면 이미지가 들어있으면 플레이어 창에 사진 이미지가 나오지 않나요?

lalupo20의 이미지

코드상으로 확인하는법 모르겠다고 말씀드린거

라스코니의 이미지

우선

#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
#endif

로 되어 있는 것을 보아 Android나 IOS는 공식적으로 미지원하는 것으로 보이네요.

그렇다고 포기하면 엔지니어가 아니죠.
여기(https://forum.qt.io/topic/127649/mp3-not-being-played-on-android)를 읽어보면 android에 qtmediaplayer plugin을 추가한 후 리소스 접근 권한을 얻으면 mp3 접근 및 play가 가능하다.... 라는 식으로 되어 있네요.

lalupo20의 이미지

defined인줄 알았습니다. 근데 mp3 접근은 그냥 되여...곡명, 앨범명, 가수는 받아 왔구요

lalupo20의 이미지

앨범사진 출력이 만드려고 하는 어플에서 중요한 부분이라...

아니면 이 기능빼고 만들까 싶기도 하고

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.