Search code examples
qtmp4qtmultimediavideo-codecsqmediarecorder

Qt : How to create a video from multiple QImages


How to create a .mp4 video out of multiple QImages in a Qt application.

Looking at QMediaRecorder examples, it only knows how to grab frames from camera. There seems to be no way to pass multiple QImages or some other image data type into QMediaRecorder simply to make a video out of them which has nothing to do with the camera.

Development Environment:
Using Qt 5.9.1 commercial version with app working on Android, iOS & OSX.


Solution

  • It is hard to ascertain exactly what you need to do here, considering it is not clear just how many images you are processing.

    That being said, this is possible if you use a tool such as ffmpeg to generate the video, however it will require you to at the very least, write those images to disc.

    Here is a working example I use to generate slideshows videos for youtube. The concatenation of images is ascertained by their naming scheme as saved on the drive.

        sl << "-i" << md.sku(true) + "##%03d.png"; // Images input,
    

    as such,

    mysku##001.png // First Slide
    mysku##002.png // Second Slide
    mysku##003.png // Third Slide
    mysku##004.png // Fourth Slide
    

    VideoConvert::VideoConvert(Metadata &md, QFile &oggFile, QObject *parent) : QObject(parent)
    {
        QStringList sl;
        tt.warning(md.duration());
        tt.warning(md.length());
        QString framerate = md.duration(true);
        int hour   = QString(md.length()).split(":").at(0).toInt();
        int minute = QString(md.length()).split(":").at(1).toInt();
        int second = QString(md.length()).split(":").at(2).toInt();
    
        framerate.remove(".");
        framerate.remove(QRegularExpression("^[0]*"));
    
        sl << "-y"; // overwrite
        sl << "-framerate" << QString::number(md.images().length()) 
            + "/" + QString::number(((hour * 60) * 60) + (minute * 60) + second);
        sl << "-i" << md.sku(true) + "##%03d.png"; // Images input,
        sl << "-i" << oggFile.fileName();
        sl << "-c" << "copy";
        sl << "/home/akiva/FrogCast/" + md.title(true) + " ⟪Wiki🔊Book⟫.mp4";
        md.setName(sl.last());
    
        QEventLoop convertEvent;
        m_Convert.setReadChannelMode(QProcess::MergedChannels);
        connect(&m_Convert, SIGNAL(readyRead()), this, SLOT(convert()));
        connect(this, SIGNAL(converted()), &convertEvent, SLOT(quit()));
        tt.process("Converting Video File");
        for (int i=0; i < sl.length(); i++) {
            QTextStream(stdout) << "\t" << sl.at(i) << endl;
        }
        if (QFile("/home/akiva/FrogCast/Cereproc/ffmpeg").exists()) {
            m_Convert.start("/home/akiva/FrogCast/Cereproc/ffmpeg", sl);
        } else {
            m_Convert.start("ffmpeg", sl);
        }
        convertEvent.exec();
        disconnect(&m_Convert, SIGNAL(finished(int)), this, SLOT(convert()));
        disconnect(this, SIGNAL(converted()), &convertEvent, SLOT(quit()));
        m_Convert.waitForFinished();
    }