【问题标题】:C++ OpenCV 3.4 / FFMPEG 3.4.1 VideoWriter and MP4 Output File FormatC++ OpenCV 3.4 / FFMPEG 3.4.1 VideoWriter 和 MP4 输出文件格式
【发布时间】:2018-05-31 04:34:18
【问题描述】:

我正在使用 Linux Kernel 4.9.35-ti-r44 的 ARM BeagleBone X-15 Debian 机器上运行。在我的 C++ ( Qt 5 ) 应用程序中,我想将我的 cv::Mat 帧保存为 MP4 格式的视频。我已经安装并从头开始编译了 ffmpeg 和 OpenCv 的 libx264。我可以使用 AVI 视频容器类型但不是 MP4 的 MJPEG 成功录制和查看视频。每当我尝试编写 MP4 视频时,都会收到以下形式的运行时错误:

OpenCV: FFMPEG: tag 0x44495658/'XVID' is not supported with codec id 13 and format 'mp4 / MP4 (MPEG-4 Part 14)'
OpenCV: FFMPEG: fallback to use tag 0x00000020/' ???'

我尝试了各种 Google 答案,但都没有奏效。

相关代码:

cv::Size frameSize = frame.size();

qDebug() << "Initializing Video Recording to save Video file here: " << destinationFileName;

std::string filename = destinationFileName.toStdString();
//int fcc =   CV_FOURCC('M','J','P','G');
//int fcc =   CV_FOURCC('X','2','6','4');
int fcc = CV_FOURCC('X','V','I','D');
int fps =   1;
videoRecorder = new cv::VideoWriter(filename,fcc,fps,frameSize);

...

videoRecorder->write(frame);

我已经下载并构建了最新的 OpenCV 3.4,但问题仍然存在。 如何使用 OpenCV 的视频编写器写入 MP4 文件?

当我尝试 'X','2','6','4' 格式时出现错误:

    Initializing Video Recording to save Video file here:  "/tmp/Garage.mp4"
OpenCV: FFMPEG: tag 0x34363258/'X264' is not supported with codec id 28 and format 'mp4 / MP4 (MPEG-4 Part 14)'
OpenCV: FFMPEG: fallback to use tag 0x31637661/'avc1'
[h264_v4l2m2m @ 0x81042020] Could not find a valid device
[h264_v4l2m2m @ 0x81042020] can't configure encoder
Could not open codec 'h264_v4l2m2m': Unspecified error
Starting

当我尝试 'X','V','I','D' 格式时出现错误:

Initializing Video Recording to save Video file here:  "/tmp/Garage.mp4"
OpenCV: FFMPEG: tag 0x44495658/'XVID' is not supported with codec id 13 and format 'mp4 / MP4 (MPEG-4 Part 14)'
OpenCV: FFMPEG: fallback to use tag 0x7634706d/'mp4v'
Starting

当我尝试 'M','P','E','G' 格式时出现错误:

Initializing Video Recording to save Video file here:  "/tmp/Garage.mp4"
OpenCV: FFMPEG: tag 0x4745504d/'MPEG' is not supported with codec id 2 and format 'mp4 / MP4 (MPEG-4 Part 14)'
OpenCV: FFMPEG: fallback to use tag 0x7634706d/'mp4v'
Starting

当我尝试 'H','2','6','4' 格式时出现错误:

OpenCV: FFMPEG: tag 0x34363248/'H264' is not supported with codec id 28 and format 'mp4 / MP4 (MPEG-4 Part 14)'
OpenCV: FFMPEG: fallback to use tag 0x31637661/'avc1'
[h264_v4l2m2m @ 0x7fdde340] Could not find a valid device
[h264_v4l2m2m @ 0x7fdde340] can't configure encoder
Could not open codec 'h264_v4l2m2m': Unspecified error
Starting

当我尝试 'M','P','4','V' 格式时出现错误:

Initializing Video Recording to save Video file here:  "/tmp/Garage.mp4"
OpenCV: FFMPEG: tag 0x5634504d/'MP4V' is not supported with codec id 13 and format 'mp4 / MP4 (MPEG-4 Part 14)'
OpenCV: FFMPEG: fallback to use tag 0x7634706d/'mp4v'
Starting

当我尝试 'A','V','C','1' 格式时出现错误:

Initializing Video Recording to save Video file here:  "/tmp/Garage.mp4"
OpenCV: FFMPEG: tag 0x31435641/'AVC1' is not supported with codec id 28 and format 'mp4 / MP4 (MPEG-4 Part 14)'
OpenCV: FFMPEG: fallback to use tag 0x31637661/'avc1'
[h264_v4l2m2m @ 0x810f5f50] Could not find a valid device
[h264_v4l2m2m @ 0x810f5f50] can't configure encoder
Could not open codec 'h264_v4l2m2m': Unspecified error
Starting

当我尝试 'D','I','V','X' 格式时出现错误:

Initializing Video Recording to save Video file here:  "/tmp/Garage.mp4"
OpenCV: FFMPEG: tag 0x58564944/'DIVX' is not supported with codec id 13 and format 'mp4 / MP4 (MPEG-4 Part 14)'
OpenCV: FFMPEG: fallback to use tag 0x7634706d/'mp4v'
Starting

当我尝试 0x21 格式时,我得到了错误:

Initializing Video Recording to save Video file here:  "/tmp/Garage.mp4"
OpenCV: FFMPEG: tag 0x00000021/'!???' is not found (format 'mp4 / MP4 (MPEG-4 Part 14)')'
Starting

这是我的完整课程,展示了所有尝试过的格式:

    #include "downloader.h"

Downloader::Downloader(QString url, QString destinationFile) : downloadUrl(url) , destinationFileName(destinationFile)
{

    didInitializeVideoWriter = false;

    qDebug() << "Initialized Downloader...";

}

Downloader::~Downloader() {

    videoRecorder->release();
    delete videoRecorder;

}

void Downloader::doDownload()
{
    networkManager = new QNetworkAccessManager(this);

    connect(networkManager, SIGNAL(finished(QNetworkReply*)),
            this, SLOT(replyFinished(QNetworkReply*)));

    networkManager->get(QNetworkRequest(QUrl(downloadUrl)));
}

void Downloader::writeFrame(cv::Mat frame) {

    QMutexLocker locker(&videoFrameMutex);

    videoRecorder->write(frame);

}

void Downloader::replyFinished(QNetworkReply *reply)
{

    if(reply->error())
    {
        qDebug() << "ERROR!";
        qDebug() << reply->errorString();
    }
    else
    {
        //qDebug() << reply->header(QNetworkRequest::ContentTypeHeader).toString();
        //qDebug() << reply->header(QNetworkRequest::LastModifiedHeader).toDateTime().toString();
        //qDebug() << reply->header(QNetworkRequest::ContentLengthHeader).toULongLong();
        qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
        qDebug() << reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();

        QString tempFileName = destinationFileName;
        QString jpegTempFilename = QString("%1").arg(tempFileName.replace("mp4","jpeg"));

        qDebug() << "Overwriting: " << jpegTempFilename;
        QFile *file = new QFile(jpegTempFilename);
        if(file->open(QFile::WriteOnly))
        {
            file->write(reply->readAll());
            file->flush();
            file->close();
        }
        delete file;

        cv::Mat frame = imread(jpegTempFilename.toStdString(), CV_LOAD_IMAGE_COLOR);   // CV_LOAD_IMAGE_COLOR (>0) loads the image in the BGR format
        cv::cvtColor(frame,frame,CV_BGR2RGB);

        // Now lazy load the recorder
        if ( !didInitializeVideoWriter ) {

            cv::Size frameSize = frame.size();

            qDebug() << "Initializing Video Recording to save Video file here: " << destinationFileName;

            std::string filename = destinationFileName.toStdString();
            //int fcc =   CV_FOURCC('M','J','P','G');
            int fcc =   CV_FOURCC('X','2','6','4');
            //int fcc = CV_FOURCC('X','V','I','D');
            //int fcc = CV_FOURCC('M','P','E','G');
            //int fcc = CV_FOURCC('H','2','6','4');
            //int fcc = CV_FOURCC('M','P','4','V');
            //int fcc = CV_FOURCC('A','V','C','1');
            //int fcc = CV_FOURCC('D','I','V','X');
            //int fcc = 0x21;
            //int fcc = 0x00000021;
            int fps =   1;
            videoRecorder = new cv::VideoWriter(filename,fcc,fps,frameSize);

            qDebug() << "Starting";
            frameCounter = 1;
            performanceTimer.start();

            didInitializeVideoWriter = true;

        }

        cv::putText(frame,"[REC]",cv::Point(50,50),5,1,cv::Scalar(0,0,225));

        QFuture<void> backgroundRun = QtConcurrent::run(this, &Downloader::writeFrame, frame);
        //backgroundRun.waitForFinished();

    }

    reply->deleteLater();

    qDebug() << "RequestTimer: " << performanceTimer.elapsed() << frameCounter;

    // Requests Again
    networkManager->get(QNetworkRequest(QUrl(downloadUrl)));

    frameCounter++;

    performanceTimer.restart();


}

更新 - 我尝试了 'a','v','c','1' 但不幸的是这也不起作用:

Initializing Video Recording to save Video file here:  "/tmp/Garage.mp4"
[h264_v4l2m2m @ 0x810f6aa0] Could not find a valid device
[h264_v4l2m2m @ 0x810f6aa0] can't configure encoder
Could not open codec 'h264_v4l2m2m': Unspecified error

(qt-downloader:6234): GStreamer-CRITICAL **: gst_element_make_from_uri: assertion 'gst_uri_is_valid (uri)' failed
OpenCV Error: Unspecified error (GStreamer: cannot link elements
) in CvVideoWriter_GStreamer::open, file /media/usb/opencv/modules/videoio/src/cap_gstreamer.cpp, line 1635
VIDEOIO(cvCreateVideoWriter_GStreamer (filename, fourcc, fps, frameSize, is_color)): raised OpenCV exception:

/media/usb/opencv/modules/videoio/src/cap_gstreamer.cpp:1635: error: (-2) GStreamer: cannot link elements
 in function CvVideoWriter_GStreamer::open

当我尝试 X264 FOURCC 时,mp4 文件是 48 字节并且永远不会增长:

Initializing Video Recording to save Video file here:  "/tmp/Garage.mp4"
OpenCV: FFMPEG: tag 0x34363258/'X264' is not supported with codec id 27 and format 'mp4 / MP4 (MPEG-4 Part 14)'
OpenCV: FFMPEG: fallback to use tag 0x31637661/'avc1'

静态尺寸:

debian@BeagleBoard-X15:/tmp$ ls -lrt Garage.*
-rw-r--r-- 1 debian debian     48 Dec 24 21:13 Garage.mp4
-rw-r--r-- 1 debian debian 100424 Dec 24 21:14 Garage.jpeg
debian@BeagleBoard-X15:/tmp$ hexdump Garage.mp4 
0000000 0000 2000 7466 7079 7369 6d6f 0000 0002
0000010 7369 6d6f 7369 326f 7661 3163 706d 3134
0000020 0000 0800 7266 6565 0000 0000 646d 7461
0000030

这是我的 ffmpeg 构建配置文件:

debian@BeagleBoard-X15:/tmp$ ffmpeg -buildconf
ffmpeg version N-89524-g74f408cc8e Copyright (c) 2000-2017 the FFmpeg developers
  built with gcc 6.3.0 (Debian 6.3.0-18) 20170516
  configuration: --enable-gpl --enable-libx264 --enable-pthreads --enable-static --extra-cflags=-I./x264/include --extra-ldflags=-L./x264/lib --extra-libs=-ldl
  libavutil      56.  6.100 / 56.  6.100
  libavcodec     58.  8.100 / 58.  8.100
  libavformat    58.  3.100 / 58.  3.100
  libavdevice    58.  0.100 / 58.  0.100
  libavfilter     7.  7.100 /  7.  7.100
  libswscale      5.  0.101 /  5.  0.101
  libswresample   3.  0.101 /  3.  0.101
  libpostproc    55.  0.100 / 55.  0.100

  configuration:
    --enable-gpl
    --enable-libx264
    --enable-pthreads
    --enable-static
    --extra-cflags=-I./x264/include
    --extra-ldflags=-L./x264/lib
    --extra-libs=-ldl

【问题讨论】:

  • 您可以尝试使用 ffmpeg 命令行 (trac.ffmpeg.org/wiki/Encode/MPEG-4) 对视频进行编码吗?也许您机器上的 ffmpeg 缺少 libxvid?
  • 感谢您的评论 - 我已确定已安装 libxvid。我的 make pro 文件包括 libx264 和 libxvidecore (LIBS += -lx264 LIBS += -lxvidcore)。但是,我仍然看到了问题。
  • 你是在构建 ffmpeg 时链接这些库还是只是将它们链接到你的项目?
  • 在从 apt-get 安装 ffmpeg 之后从 apt-get 安装它们 - 所以也许我的 ffmpeg 没有支持!我会尝试编译它。
  • 我重新编译了 FFMPEG 3.4.1 和 OpenCV 3.4,不幸的是,我修改后的工作中没有显示任何格式。

标签: c++ opencv ffmpeg


【解决方案1】:

我和你有类似的问题,但在 MacOS 上运行。我通过将 X264 库重新安装到最新版本来解决它,然后使用 ./configure --enable-libx264 --enable-gpl --enable-avresample --enable-shared 重新安装 FFMPEG 以将新的 X264 正确链接到 FFMPEG。然后,重新安装 OpenCV(我使用的是 3.4.4 版)来链接新的 FFMPEG。在构建 OpenCV 时,请确保 WITH FFMPEGON 否则将使用内置的 OpenCV 编码器,这将为您提供更多有限的选择。

【讨论】:

    【解决方案2】:

    您是否尝试过使用普通 C++11 中的 ust,例如:

        using namespace std;
        using namespace cv;
    
    int main(){
    
        // Create a VideoCapture object and use camera to capture the video
        VideoCapture cap(0);
    
        // Check if camera opened successfully
        if(!cap.isOpened())
        {
            cout << "Error opening video stream" << endl;
            return -1;
        }
    
        // Default resolution of the frame is obtained.The default resolution is system dependent.
        int frame_width = cap.get(CV_CAP_PROP_FRAME_WIDTH);
        int frame_height = cap.get(CV_CAP_PROP_FRAME_HEIGHT);
    
        // Define the codec and create VideoWriter object.The output is stored in 'outcpp.avi' file.
        VideoWriter video("outcpp-.avi",CV_FOURCC('M','J','P','G'),10, Size(frame_width,frame_height));
        while(1)
        {
            Mat frame;
    
            // Capture frame-by-frame
            cap >> frame;
    
            // If the frame is empty, break immediately
            if (frame.empty())
                break;
    
            // Write the frame into the file 'outcpp.avi'
            video.write(frame);
    
            // Display the resulting frame
            imshow( "Frame", frame );
    
            // Press  ESC on keyboard to  exit
            char c = (char)waitKey(1);
            if( c == 27 )
                break;
        }
    
        // When everything done, release the video capture and write object
        cap.release();
        video.release();
    
        // Closes all the windows
        destroyAllWindows();
        return 0;
    }
    

    如果它正常工作,您会遇到与我们相同的问题 :) QT 与我假设的视频编写器 Opencv 存在问题。欢迎加入俱乐部。

    另一方面,您找到解决方案了吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-06-06
      • 2020-08-28
      • 2013-01-26
      • 2015-08-23
      • 2013-11-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多