c++ ffmpeg打开摄像头推流
时间: 2023-03-21 13:01:48 浏览: 649
要使用FFmpeg打开摄像头并推流,您可以使用以下命令:
```
ffmpeg -f v4l2 -video_size 640x480 -i /dev/video0 -f flv rtmp://server/live/stream_key
```
这个命令将使用v4l2作为输入格式打开视频设备,设置视频大小为640x480,指定设备为/dev/video0,将视频流推送到RTMP服务器的rtmp://server/live/地址,并指定流的关键字为stream_key。
如果您想要在Windows上使用FFmpeg打开摄像头并推流,您可以使用以下命令:
```
ffmpeg -f dshow -i video="Your Camera Name" -video_size 640x480 -framerate 30 -f flv rtmp://server/live/stream_key
```
这个命令将使用dshow作为输入格式打开视频设备,指定设备为“Your Camera Name”,设置视频大小为640x480,帧率为30,将视频流推送到RTMP服务器的rtmp://server/live/地址,并指定流的关键字为stream_key。
请注意,您需要将命令中的地址和关键字替换为您实际使用的服务器地址和流关键字。另外,要确保您的FFmpeg版本支持所需的输入格式和编解码器。
相关问题
c++ ffmpeg打开摄像头推流rtsp
您可以使用ffmpeg来打开摄像头并将视频流推送到RTSP服务器。以下是一个基本的示例命令:
```
ffmpeg -f v4l2 -i /dev/video0 -vcodec libx264 -preset ultrafast -tune zerolatency -f rtsp rtsp://<RTSP SERVER IP>:<PORT>/<STREAM NAME>
```
这个命令的解释如下:
- `-f v4l2`: 使用Video4Linux2作为输入设备
- `-i /dev/video0`: 输入设备的地址,这里是摄像头设备
- `-vcodec libx264`: 使用x264编码器进行视频编码
- `-preset ultrafast`: 使用“超快速”编码速度进行编码
- `-tune zerolatency`: 用于实时流,减少延迟
- `-f rtsp`: 指定输出格式为RTSP
- `rtsp://<RTSP SERVER IP>:<PORT>/<STREAM NAME>`: RTSP服务器的地址和端口,以及流的名称。
您需要将`<RTSP SERVER IP>`替换为RTSP服务器的IP地址,`<PORT>`替换为RTSP服务器使用的端口,`<STREAM NAME>`替换为您希望为流指定的名称。例如,如果您要将流推送到名为“test”的RTSP流上,命令可能会像这样:
```
ffmpeg -f v4l2 -i /dev/video0 -vcodec libx264 -preset ultrafast -tune zerolatency -f rtsp rtsp://192.168.1.100:554/test
```
这将从/dev/video0读取摄像头流,将其编码为H.264,并将其作为RTSP流推送到192.168.1.100的554端口上的名为“test”的流中。
LINUX C++ ffmpeg 摄像头 推流 代码示例
这里提供一个简单的示例代码,使用FFmpeg推送摄像头采集到的视频流:
```c++
#include <iostream>
#include <thread>
#include <chrono>
#include <opencv2/opencv.hpp>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
using namespace std;
using namespace cv;
int main(int argc, char* argv[])
{
// 打开摄像头
VideoCapture cap(0);
if (!cap.isOpened())
{
cerr << "Failed to open camera!" << endl;
return -1;
}
// 初始化FFmpeg
av_register_all();
avformat_network_init();
// 创建输出上下文
AVFormatContext* outctx = nullptr;
if (avformat_alloc_output_context2(&outctx, nullptr, "flv", "rtmp://localhost/live/test") < 0)
{
cerr << "Failed to create output context!" << endl;
return -1;
}
// 添加视频流
AVCodecID codec_id = AV_CODEC_ID_H264;
AVCodec* codec = avcodec_find_encoder(codec_id);
if (!codec)
{
cerr << "Failed to find encoder!" << endl;
return -1;
}
AVStream* outstream = avformat_new_stream(outctx, codec);
if (!outstream)
{
cerr << "Failed to create stream!" << endl;
return -1;
}
outstream->codecpar->codec_id = codec_id;
outstream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
outstream->codecpar->width = cap.get(CV_CAP_PROP_FRAME_WIDTH);
outstream->codecpar->height = cap.get(CV_CAP_PROP_FRAME_HEIGHT);
outstream->codecpar->format = AV_PIX_FMT_YUV420P;
// 打开编码器
if (avcodec_open2(outstream->codec, codec, nullptr) < 0)
{
cerr << "Failed to open encoder!" << endl;
return -1;
}
// 打开输出流
if (!(outctx->oformat->flags & AVFMT_NOFILE))
{
if (avio_open(&outctx->pb, outctx->url, AVIO_FLAG_WRITE) < 0)
{
cerr << "Failed to open output stream!" << endl;
return -1;
}
}
// 写文件头
if (avformat_write_header(outctx, nullptr) < 0)
{
cerr << "Failed to write header!" << endl;
return -1;
}
// 初始化图像转换器
SwsContext* swsctx = sws_getContext(cap.get(CV_CAP_PROP_FRAME_WIDTH), cap.get(CV_CAP_PROP_FRAME_HEIGHT), AV_PIX_FMT_BGR24,
outstream->codecpar->width, outstream->codecpar->height, outstream->codecpar->format, SWS_BICUBIC, nullptr, nullptr, nullptr);
if (!swsctx)
{
cerr << "Failed to create image converter!" << endl;
return -1;
}
// 循环读取视频帧并推送
Mat frame;
AVFrame* avframe = av_frame_alloc();
avframe->format = outstream->codecpar->format;
avframe->width = outstream->codecpar->width;
avframe->height = outstream->codecpar->height;
av_frame_get_buffer(avframe, 32);
while (true)
{
cap >> frame;
if (frame.empty())
break;
// 转换图像格式
uint8_t* data[AV_NUM_DATA_POINTERS] = { 0 };
data[0] = frame.data;
int linesize[AV_NUM_DATA_POINTERS] = { 0 };
linesize[0] = frame.step;
sws_scale(swsctx, data, linesize, 0, frame.rows, avframe->data, avframe->linesize);
// 编码并发送视频帧
AVPacket pkt = { 0 };
av_init_packet(&pkt);
int ret = avcodec_send_frame(outstream->codec, avframe);
if (ret < 0)
{
cerr << "Failed to send frame!" << endl;
break;
}
while (ret >= 0)
{
ret = avcodec_receive_packet(outstream->codec, &pkt);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
break;
else if (ret < 0)
{
cerr << "Error while encoding frame!" << endl;
break;
}
// 发送数据包
av_packet_rescale_ts(&pkt, outstream->codec->time_base, outstream->time_base);
pkt.stream_index = outstream->index;
ret = av_interleaved_write_frame(outctx, &pkt);
if (ret < 0)
cerr << "Failed to write packet!" << endl;
av_packet_unref(&pkt);
}
// 等待一段时间
this_thread::sleep_for(chrono::milliseconds(30));
}
// 写文件尾
av_write_trailer(outctx);
// 释放资源
avcodec_close(outstream->codec);
avcodec_free_context(&outstream->codec);
avformat_free_context(outctx);
av_frame_free(&avframe);
sws_freeContext(swsctx);
return 0;
}
```
请注意修改代码中的推流地址和编码器参数,以适应你的需求。
阅读全文