You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 23:01:08