我正在运行一个带有Linux Kernel 4.9.35-ti-r44的ARM BeagleBone X-15 Debian机器。在我的C++(Qt 5)应用程序中,我想将我的cv::Mat帧保存为MP4格式的视频。我已经安装了libx264,并从头编译了ffmpeg和OpenCv。我可以成功地使用AVI视频容器类型记录和查看MJPEG视频,但不能使用MP4。每当我尝试写入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/' ???'
我尝试过各种谷歌答案,但都没有奏效。
相关代码:
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'和'MPEG'格式时,会出现以下错误:
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