Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to get meta data from media?



  • say i have a video, say h.264 (that i have confirmed will indeed play), and i'd like to glean some of its meta data BEFORE playing it. Like it's dimensions ("Resolution"), it's audio bitrate ("AudioBitRate"), and any of the other standard things like duration, title, artist, album etc.

    it's my understanding that QMediaPlayer knows nothing of this info (even though it provides APIs for them), until AFTER the underlying media in question has started playing? is there a way to, say "preroll" the media to get the meta data to be available, BEFORE playing? or must i actually, secretly play the media a bit and wait for a "meta data available" singnal?

    all i could find on the web suggests that the solution is the latter, that there is no "preroll" API i can call.

    This is the code i've come up with:

    void		QVideoWindow::WaitForMetaData(QMediaPlayer *playerP)
    {
    	if (!i_got_metaB) {
    		QGraphicsVideoItem		vidWid;
    
    		playerP->setVideoOutput(&vidWid);
    
    		//	metaDataAvailableChanged
    
    		i_playerP = playerP;
    		QObject::connect(
    			playerP,	&QMediaPlayer::mediaStatusChanged,
    			this,		&QVideoWindow::onMediaStatusChanged);
    
    		playerP->setVolume(0);
    		playerP->play();
    
    		QEventLoop		loop;
    
    		while (!i_got_metaB) {
    			//IdleDuration(0.1);
    			loop.processEvents();
    		}
    
    		QObject::disconnect(
    			playerP,	&QMediaPlayer::mediaStatusChanged,
    			this,		&QVideoWindow::onMediaStatusChanged);
    
    		i_playerP = NULL;
    
    		playerP->stop();
    		playerP->setPosition(0);
    		playerP->setVideoOutput((QVideoWidget *)NULL);
    
    		i_got_metaB = false;
    	}
    }
    
    void		QVideoWindow::onMediaStatusChanged(QMediaPlayer::MediaStatus mediaStatus)
    {
    	if (mediaStatus == QMediaPlayer::BufferedMedia) {
    		QString			outStr;
    		QTextStream		outStream(&outStr);
    
    		for (auto &item: i_playerP->availableMetaData()) {
    			outStream << item << ", ";
    		}
    
    		Logf("availz: %s\n", SuperString(outStr).utf8Z());
    
    		i_got_metaB = true;
    	}
    }
    

    At the time that WaitForMetaData() is called, i assure you that QMediaPlayer has been allocated with QMediaPlayer::VideoSurface, and the mp4 file path has been properly set with setMedia().

    I have tried using a QVideoWidget instead of a QGraphicsVideoItem, and I have tried connecting to the metaDataAvailableChanged signal too, to no avail.

    the issue is that my slot onMediaStatusChanged is never called (and yes it is properly designated as a slot in the header).

    1. this method seems ridiculously convoluted for something so potentially common and mundane
    2. does anyone have a FUNCTIONING bit of code that does what is needed, that they can paste in here?

    thanks!

    -dave



  • In windows 10, I can get meta data after setMedia, without calling play, but it is asynchronous

    auto player = new QMediaPlayer(this);
    player->setMedia(QUrl::fromLocalFile("QTSRCDIR/qtwebengine/src/3rdparty/chromium/third_party/webrtc/examples/objc/AppRTCMobile/ios/resources/foreman.mp4"));
    connect(player, &QMediaPlayer::metaDataAvailableChanged, [=](bool avaliable){
        if(avaliable) {
            for (auto key : player->availableMetaData()) {
                qDebug() << key << player->metaData(key);
            }
        }
    });
    

    output:

    "Duration" QVariant(qlonglong, 10001)
    "PixelAspectRatio" QVariant(QSize, QSize(1, 1))
    "Resolution" QVariant(QSize, QSize(352, 288))
    "VideoBitRate" QVariant(uint, 433960)
    "VideoCodec" QVariant(QString, "H.264 Video")
    "VideoFrameRate" QVariant(double, 30)
    

    Haven't tried that in other platforms though.



  • that's equivalent to my above code, which does not work. i'm on a mac, by the way.

    by "does not work" i mean the slot is never called



  • does anyone know how to use Qt to get meta data from a media file, on mac?


  • Qt Champions 2019

    @davecotter You should still try @Bonnie code as yours is not exactly the same (you're using a local event loop which is actually not needed if using assynchronous nature of Qt properly, also you call play which Bonnie doesn't).
    Also you should connect a slot to https://doc.qt.io/qt-5/qmediaplayer.html#error-1 to see whether you get any errors.
    https://doc.qt.io/qt-5/qmediaplayer.html#mediaChanged, https://doc.qt.io/qt-5/qmediaplayer.html#stateChanged and https://doc.qt.io/qt-5/qmediaplayer.html#mediaStatusChanged are also worth checking.



  • i suppose it's my fault for not being clear: i have tried a half dozen solutions, INCLUDING the one proposed by @Bonnie , and none work.

    can someone who really believes this should work on a mac please try it?

    and the point is i need the data BEFORE the function exits, hence my synchronous approach.

    note i admit this DOES work fine on windows, but that's not my problem, my problem is mac. on mac the slot is never called.

    at the risk of being overly clear / verbose, i added all this code:

    		//	error
    		connect(playerP, QOverload<QMediaPlayer::Error>::of(&QMediaPlayer::error),
    			[=](QMediaPlayer::Error error) {
    				qDebug() << error;
    			}
    		);
    
    		//	metaDataAvailableChanged
    		connect(playerP, &QMediaPlayer::metaDataAvailableChanged,
    			[=](bool avaliable) {
    				if (avaliable) {
    					for (auto key : playerP->availableMetaData()) {
    						qDebug() << key << playerP->metaData(key);
    					}
    				}
    			}
    		);
    
    		//	mediaChanged
    		connect(playerP, &QMediaPlayer::mediaChanged,
    			[=](const QMediaContent &media) {
    				qDebug() << "mediaChanged";
    			}
    		);
    
    		//	mediaStatusChanged
    		connect(playerP, &QMediaPlayer::mediaStatusChanged,
    			[=](QMediaPlayer::MediaStatus status) {
    				qDebug() << status;
    			}
    		);
    
    		//	stateChanged
    		connect(playerP, &QMediaPlayer::stateChanged,
    			[=](QMediaPlayer::State state) {
    				qDebug() << state;
    			}
    		);
    

    on mac: NONE of the slots are called.
    on win: they are called as expected:
    metaDataAvailableChanged is called first, printing out a nice list of all the meta data
    mediaStatusChanged is then called, showing "loadedMedia"


  • Qt Champions 2019

    @davecotter Sorry, I don't have Mac, so can't test.



  • there is a minimal project available in the bug report if someone would like to see the problem.

    note the major problem (no signals) only happens on mac, but there ARE problems on windows, which you can see by reading the bug report.


Log in to reply