如何用OpenCV、FFmpeg或GStreamer保存未压缩视频文件?
用OpenCV生成未压缩AVI视频的可行方案
首先必须明确:指定FFmpeg后端是让OpenCV正确生成未压缩视频的核心前提,这是解决文档与issue表述矛盾的关键——只有强制使用FFmpeg后端,codec=0的设置才会生效,输出原始未压缩流。
1. 核心C++代码实现
#include <opencv2/opencv.hpp> #include <iostream> int main() { // 帧尺寸示例,可根据实际场景替换 cv::Size frameSize(640, 480); // 建议明确设置帧率,部分FFmpeg版本对fps=0的兼容性不佳 double fps = 30.0; // 初始化VideoWriter:强制指定FFmpeg后端,codec设为0表示未压缩 cv::VideoWriter writer; bool isOpened = writer.open( "output.avi", cv::CAP_FFMPEG, // 关键:强制使用FFmpeg后端 0, // codec=0,告诉FFmpeg输出未压缩视频 fps, frameSize, true // 彩色帧设为true,灰度帧设为false ); if (!isOpened) { std::cerr << "无法初始化VideoWriter,请检查FFmpeg是否正确集成到OpenCV" << std::endl; return -1; } // 示例:写入100帧测试画面 for (int i = 0; i < 100; ++i) { cv::Mat frame(frameSize, CV_8UC3, cv::Scalar(0, 255, 0)); cv::putText(frame, std::to_string(i), cv::Point(50, 50), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255, 0, 0), 2); writer.write(frame); } writer.release(); return 0; }
2. 兼容优化:指定具体未压缩编码FOURCC
如果codec=0的方式不生效,可以直接指定未压缩编码的FOURCC值,常见选项:
- 未压缩YUV420P:
CV_FOURCC('I','Y','U','V') - 未压缩RGB24:
CV_FOURCC('R','G','B',' ')
修改后的open调用示例:
bool isOpened = writer.open( "output.avi", cv::CAP_FFMPEG, CV_FOURCC('I','Y','U','V'), fps, frameSize, true );
备选方案:OpenCV + FFmpeg管道/API组合
如果OpenCV的VideoWriter始终无法满足需求,可通过OpenCV处理帧,再用FFmpeg完成未压缩视频写入:
1. 管道方式(快速实现)
OpenCV将帧数据写入标准输出,通过管道传给FFmpeg命令行处理:
#include <opencv2/opencv.hpp> #include <cstdio> int main() { cv::Size frameSize(640, 480); double fps = 30.0; // 启动FFmpeg子进程,通过管道接收原始帧并写入未压缩AVI FILE* pipe = popen( "ffmpeg -y -f rawvideo -vcodec rawvideo -pix_fmt bgr24 -s 640x480 -r 30 -i - -vcodec rawvideo output.avi", "w" ); if (!pipe) { std::cerr << "无法启动FFmpeg管道" << std::endl; return -1; } for (int i = 0; i < 100; ++i) { cv::Mat frame(frameSize, CV_8UC3, cv::Scalar(0, 255, 0)); cv::putText(frame, std::to_string(i), cv::Point(50, 50), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255, 0, 0), 2); // 将帧数据写入管道 fwrite(frame.data, 1, frame.total() * frame.elemSize(), pipe); } pclose(pipe); return 0; }
2. FFmpeg C API方式(高定制化)
如果需要精细控制编码参数或性能优化,可以直接调用FFmpeg的C API,结合OpenCV帧数据完成写入。这种方式需要链接FFmpeg的libavformat、libavcodec等库,适合专业场景开发。
备选方案:OpenCV + GStreamer
若系统预装GStreamer且OpenCV编译时启用了GStreamer支持,可通过GStreamer后端写入未压缩视频:
#include <opencv2/opencv.hpp> int main() { cv::Size frameSize(640, 480); double fps = 30.0; // GStreamer管道:接收OpenCV的BGR帧,编码为未压缩格式并写入AVI std::string pipeline = "appsrc ! video/x-raw,format=BGR,width=640,height=480,framerate=30/1 ! avenc_rawvideo ! avienc ! filesink location=output.avi"; cv::VideoWriter writer(pipeline, cv::CAP_GSTREAMER, 0, fps, frameSize, true); if (!writer.isOpened()) { std::cerr << "无法初始化GStreamer后端的VideoWriter" << std::endl; return -1; } // 写入帧逻辑同前 for (int i = 0; i < 100; ++i) { cv::Mat frame(frameSize, CV_8UC3, cv::Scalar(0, 255, 0)); cv::putText(frame, std::to_string(i), cv::Point(50, 50), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255, 0, 0), 2); writer.write(frame); } writer.release(); return 0; }
内容的提问来源于stack exchange,提问作者user18953215
相关产品推荐
相关产品推荐

