首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >C++ OpenCV 3.4 / FFMPEG 3.4.1 VideoWriter和MP4输出文件格式

C++ OpenCV 3.4 / FFMPEG 3.4.1 VideoWriter和MP4输出文件格式
EN

Stack Overflow用户
提问于 2017-12-18 02:30:02
回答 2查看 11.5K关注 0票数 3

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

代码语言:javascript
运行
复制
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/' ???'

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

相关代码:

代码语言:javascript
运行
复制
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‘格式时,我得到了错误:

代码语言:javascript
运行
复制
    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‘格式时,我得到了错误:

代码语言:javascript
运行
复制
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‘格式时,我得到错误:

代码语言:javascript
运行
复制
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‘格式时,我得到了错误:

代码语言:javascript
运行
复制
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‘格式时,我得到了错误:

代码语言:javascript
运行
复制
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‘格式时,我得到了错误:

代码语言:javascript
运行
复制
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‘格式时,我得到错误:

代码语言:javascript
运行
复制
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格式时,我得到错误:

代码语言:javascript
运行
复制
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

下面是我的完整类,它显示了所有尝试过的格式:

代码语言:javascript
运行
复制
    #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‘,不幸的是这也不起作用:

代码语言:javascript
运行
复制
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字节,并且永远不会增长:

代码语言:javascript
运行
复制
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'

静态大小:

代码语言:javascript
运行
复制
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 build conf:

代码语言:javascript
运行
复制
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
EN

回答 2

Stack Overflow用户

发布于 2019-01-11 07:42:58

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

票数 1
EN

Stack Overflow用户

发布于 2018-01-31 16:19:44

你有没有尝试过使用普通的C++11,比如:

代码语言:javascript
运行
复制
    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有问题,我猜。欢迎加入俱乐部。

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

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47858206

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档