[수정2]Qt mp3파일 앨범사진 추출에 관련해서 질문이 있습니다.
글쓴이: lalupo20 / 작성시간: 월, 2023/01/16 - 8:07오후
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)); }
아래와 같은 코드를 작성했는데 작동하지 않네요.
예제 프로젝트에서 메타데이터와 관련 있는 부분을 다 올려봅니다.
제가 빼먹은게 있는지 한번만 봐주셨으면 해서 올립니다.
Forums:
추가로 곡명이나 앨범명 가수명은 정상적으로 받아왔습니다.
추가로 곡명이나 앨범명 가수명은 정상적으로 받아왔습니다.
글쎄요... 음
글쎄요... 음
이것도 안되네요.
혹시나 안드로이드 상에서 버그가 있는건가 싶어서 피씨용으로 설정하고 빌드해봤는데 똑같이 작동 안합니다...
그리고 위에 적어 놓은 예제 프로젝트도 이미지출력 못하는거 같구요.
기본 예제가 정상 작동 안하니 답답하네여;
mp3 파일에 이미지가 들어 있는 것은 확인
mp3 파일에 이미지가 들어 있는 것은 확인 가능한가요?
음 이거 예제 말인데 피씨 버전으로 빌드하니 이미지 출력 되네요
근데 똑같은 코드인데 왜 작동 안하는지...
제가 만든거는 피씨나 안드로이드나 둘다 이미지 출력 안되구요...
예제 소스 분석 좀 해봐야 될거 같아요.
이미지 들어있는지 확인 하는 법은 모르겠구요.
앨범이미지 들어 있는 파일들은 맞습니다...
예전에 ndk로 개발할때 taglib라는 라이브러리 써서 앨범사진 빼왔던 파일들이거든요...
mp3 플레이어로 플레이해보면 이미지가 들어있으면
mp3 플레이어로 플레이해보면 이미지가 들어있으면 플레이어 창에 사진 이미지가 나오지 않나요?
네 사진나와요
코드상으로 확인하는법 모르겠다고 말씀드린거
우선#if !defined(Q_OS_ANDROID)
우선
로 되어 있는 것을 보아 Android나 IOS는 공식적으로 미지원하는 것으로 보이네요.
그렇다고 포기하면 엔지니어가 아니죠.
여기(https://forum.qt.io/topic/127649/mp3-not-being-played-on-android)를 읽어보면 android에 qtmediaplayer plugin을 추가한 후 리소스 접근 권한을 얻으면 mp3 접근 및 play가 가능하다.... 라는 식으로 되어 있네요.
아 '!'defined 였군여;
defined인줄 알았습니다. 근데 mp3 접근은 그냥 되여...곡명, 앨범명, 가수는 받아 왔구요
이게 안되서 다시 ndk 개발로 돌아갈까 싶네요.
앨범사진 출력이 만드려고 하는 어플에서 중요한 부분이라...
아니면 이 기능빼고 만들까 싶기도 하고
댓글 달기