opencv 拉流并无损输出:
#include <opencv2/opencv.hpp>
#include <iostream>
#include <cstdio>
int main() {
std::string input_url = "rtmp://101.126.68.169/live/mac";
std::string output_url = "rtmp://101.126.68.169/live/processed";
// 打开输入流
cv::VideoCapture cap(input_url);
if (!cap.isOpened()) {
std::cerr << "无法打开输入流: " << input_url << std::endl;
return -1;
}
int width = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_WIDTH));
int height = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_HEIGHT));
int fps = static_cast<int>(cap.get(cv::CAP_PROP_FPS));
if (fps == 0) fps = 25; // 有些流无法正确获取fps,给个默认值
// 准备 ffmpeg 命令
std::string ffmpeg_cmd =
"ffmpeg -y -f rawvideo -pix_fmt bgr24 -s " +
std::to_string(width) + "x" + std::to_string(height) +
" -r " + std::to_string(fps) +
" -i - -c:v libx264 -pix_fmt yuv420p -preset ultrafast -f flv " +
output_url;
#ifdef _WIN32
FILE* pipe = _popen(ffmpeg_cmd.c_str(), "wb");
#else
FILE* pipe = popen(ffmpeg_cmd.c_str(), "w");
#endif
if (!pipe) {
std::cerr << "无法启动 ffmpeg 进程" << std::endl;
return -1;
}
cv::Mat frame;
while (true) {
if (!cap.read(frame)) {
std::cerr << "读取帧失败,结束" << std::endl;
break;
}
// 将帧写入 ffmpeg stdin
fwrite(frame.data, 1, frame.total() * frame.elemSize(), pipe);
}
#ifdef _WIN32
_pclose(pipe);
#else
pclose(pipe);
#endif
cap.release();
return 0;
}g++ test.cpp -o test pkg-config --cflags --libs opencv4`
调整缓冲帧数:
#include <opencv2/opencv.hpp>
#include <iostream>
#include <cstdio>
int main() {
std::string input_url = "rtmp://101.126.68.169/live/mac";
std::string output_url = "rtmp://101.126.68.169/live/processed";
// 打开输入流
cv::VideoCapture cap(input_url);
if (!cap.isOpened()) {
std::cerr << "无法打开输入流: " << input_url << std::endl;
return -1;
}
// ⚡ 设置缓冲区大小为 1,避免延时累积
cap.set(cv::CAP_PROP_BUFFERSIZE, 1);
int width = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_WIDTH));
int height = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_HEIGHT));
int fps = static_cast<int>(cap.get(cv::CAP_PROP_FPS));
if (fps == 0) fps = 25; // 有些流获取不到fps,给默认值
// 准备 ffmpeg 命令
std::string ffmpeg_cmd =
"ffmpeg -y -f rawvideo -pix_fmt bgr24 -s " +
std::to_string(width) + "x" + std::to_string(height) +
" -r " + std::to_string(fps) +
" -i - -c:v libx264 -pix_fmt yuv420p -preset ultrafast -f flv " +
output_url;
#ifdef _WIN32
FILE* pipe = _popen(ffmpeg_cmd.c_str(), "wb");
#else
FILE* pipe = popen(ffmpeg_cmd.c_str(), "w");
#endif
if (!pipe) {
std::cerr << "无法启动 ffmpeg 进程" << std::endl;
return -1;
}
cv::Mat frame;
while (true) {
// 丢掉旧帧,只取最新的
cap.grab(); // 抓取一帧但不解码
if (!cap.retrieve(frame)) {
std::cerr << "读取帧失败,结束" << std::endl;
break;
}
// 写入 ffmpeg stdin
fwrite(frame.data, 1, frame.total() * frame.elemSize(), pipe);
}
#ifdef _WIN32
_pclose(pipe);
#else
pclose(pipe);
#endif
cap.release();
return 0;
}