Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >协议转换之rtsp转rtmp推流

协议转换之rtsp转rtmp推流

作者头像
视界音你而不同
发布于 2020-07-14 08:54:52
发布于 2020-07-14 08:54:52
4.4K00
代码可运行
举报
运行总次数:0
代码可运行

近些年,每一年的风口,几乎都离不开音视频。2020年了,音视频依然很火,只不过是火的领域有所不同,从年初受疫情而爆发的视频会议,到后来为了大力发展网络经济的直播带货!不过呢,本篇我们暂时不讨论这个,咱们聊技术,说到直播,rtmp协议依然是主流!不过呢,音视频中,流媒体协议rtsp也占有很大份额!日常生活呢,我们也会遇到一些不同流媒体协议转换的问题!本篇记录实现一个rtsp转rtmp直播流的程序!闲言少叙,接下来置入主题。

需求

有一个摄像头,比如海康的监控摄像头,可以通过rtsp流的方式访问其视频画面!需要将其画面转换为rtmp协议,并实现直播!

实现思路

我们的程序,称之为rtsp2rtmp,使用该程序实现拉取摄像头rtsp视频流,并将rtmp视频流转换为rtmp视频流,然后推送到直播服务器,直播服务器采用nginx+rtmp_module的方式实现,环境搭建的步骤可以参考之前的文章:搭一个简单的直播平台,嗨起来

rtsp2rtmp,使用FFmpeg API来实现!

准备工作

  • visual studio(笔者使用vs2019)
  • FFmpeg sdk: 下载下载地址:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
https://ffmpeg.zeranoe.com/builds/

具体实现步骤

  • 打开输入流上下文
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  //av_register_all();
  avformat_network_init();


  m_strRtspUrl = rtspUrl;
  m_strRtmpUrl = rtmpUrl;

  m_pRtspAVFormatContext = NULL;
  m_nRet = 0;

  m_nVideoIndex = -1;
  m_nAudioIndex = -1;
  
  memset(errBuf, 0, 1024);

  // 1. 申请输出流上下文
  m_pRtmpAVFormatContext = NULL;
  avformat_alloc_output_context2(&m_pRtmpAVFormatContext, NULL, "flv", m_strRtmpUrl.c_str());
  if (!m_pRtmpAVFormatContext)
  {
    std::cout << "avformat_alloc_output_contex2 failed!" << std::endl;
    return false;
  }
  std::cout << "[" << m_strRtmpUrl.c_str() << "] avformat_alloc_output_context2 success " << std::endl;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  //1.打开输入流
  m_nRet = avformat_open_input(&m_pRtspAVFormatContext, m_strRtspUrl.c_str(), 0, 0);
  if (m_nRet != 0)
  {
    std::cout << "open " << m_strRtspUrl.c_str() << "error!" << std::endl;
    return m_nRet;
  }
  std::cout << "open " << m_strRtspUrl.c_str() << "success !" << std::endl;

  // 2.获得流信息
  m_nRet = avformat_find_stream_info(m_pRtspAVFormatContext, 0);
  if (m_nRet < 0)
  {
    std::cout << "avformat_find_stream_info failed" << std::endl;
    return m_nRet;
  }

  std::cout << "avformat_find_stream_info success" << std::endl;
  av_dump_format(m_pRtspAVFormatContext, 0, m_strRtspUrl.c_str(),0);



  for (int i = 0; i < m_pRtspAVFormatContext->nb_streams; i++)
  {
    if (m_pRtspAVFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) 
    {
      m_nVideoIndex = i;
    }

    if (m_pRtspAVFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) 
    { 
      m_nAudioIndex = i;
    }
  }

  • 打开输出流上下文
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  //3. 申请输出AVStream(rtmp)
  const AVCodec* outCodec = avcodec_find_decoder(m_pRtspAVFormatContext->streams[m_nVideoIndex]->codecpar->codec_id);
  m_pRtmpAVStream = avformat_new_stream(m_pRtmpAVFormatContext, outCodec);
  if (!m_pRtmpAVStream)
  {
    std::cout << "[rtmp] Failed allocating output stream!" << std::endl;
    return m_nRet;
  }

  std::cout << "[rtmp] avformat_new_stream success!" << std::endl;

  //4. stream信息复制
  AVCodecContext* rtmpOutCodec = avcodec_alloc_context3(outCodec);

  m_nRet = avcodec_parameters_to_context(rtmpOutCodec, m_pRtspAVFormatContext->streams[m_nVideoIndex]->codecpar);
  if (m_nRet < 0)
  {
    std::cout << "[rtmp] avcodec_paramertes_to_context failed " << std::endl;
    return m_nRet;
  }
  std::cout << "[rtmp] avcodec_paramertes_to_context success" << std::endl;

  m_nRet = avcodec_parameters_from_context(m_pRtmpAVStream->codecpar, rtmpOutCodec);
  if (m_nRet < 0)
  {
    std::cout << "[rtmp] avcodec_parameters_from_context failed";
    return m_nRet;
  }


  if (!(m_pRtmpAVFormatContext->flags & AVFMT_NOFILE)) {
    m_nRet = avio_open2(&m_pRtmpAVFormatContext->pb, m_strRtmpUrl.c_str(), AVIO_FLAG_WRITE, NULL, NULL);
    if (m_nRet < 0) {
      av_strerror(m_nRet, errBuf, 1024);
      //std::cout << "avio_open2 failed: " << errBuf << std::endl;
      printf("avio_open2 failed: %s\n", errBuf);
      return m_nRet;
    }
  }


  //5. 写rtmp头信息
  m_nRet = avformat_write_header(m_pRtmpAVFormatContext, NULL);
  if (m_nRet < 0)
  {
    std::cout << "[rtmp] avformat_write_header failed" << std::endl;

    av_strerror(m_nRet, errBuf, 1024);
    printf("errBuf: %s\n", errBuf);
    //std::cout << err << std::endl;
    return m_nRet;
  }

  std::cout << "[rtmp] avformat_write_header success!" << std::endl;
  • 读取输入流
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    m_nRet = av_read_frame(m_pRtspAVFormatContext, &pkt);
    if (m_nRet < 0)
    {
      break;
    }
  • 写入输出流
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    rtspStream = m_pRtspAVFormatContext->streams[pkt.stream_index];
    rtmpStream = m_pRtmpAVFormatContext->streams[pkt.stream_index];

    pkt.pts = av_rescale_q_rnd(pkt.pts, rtspStream->time_base, rtmpStream->time_base, AVRounding(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
    pkt.dts = av_rescale_q_rnd(pkt.dts, rtspStream->time_base, rtmpStream->time_base, AVRounding(AV_ROUND_NEAR_INF |AV_ROUND_PASS_MINMAX));
    pkt.duration = av_rescale_q(pkt.duration, rtspStream->time_base, rtmpStream->time_base);

    pkt.pos = -1;
    m_nRet = av_interleaved_write_frame(m_pRtmpAVFormatContext, &pkt);
    if (m_nRet < 0)
    {
      break;
    }
    av_packet_unref(&pkt);

github传送门

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
https://github.com/mlfcjob/Rtsp2Rtmp.git

欢迎star,欢迎使用修改和提交!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-07-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 视界音你而不同 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
FFmpeg4.0笔记:rtsp2rtmp
Github https://github.com/gongluck/FFmpeg4.0-study.git #include <iostream> using namespace std; extern "C" { #include "libavformat/avformat.h" #include "libavutil/time.h" } #pragma comment(lib, "avformat.lib") #pragma comment(lib, "avutil.lib") #pragma co
gongluck
2018/06/22
1.5K0
基于FFmpeg进行RTMP推流(二)
在前面一节基于FFmpeg进行RTMP推流(一)我们写了最简单的一版推流代码。但细心调试过的兄弟会发现当我们把文件换成mp4后,发现上面的代码在写入文件头时报错。也就是说上一版的代码是有bug的。
用户2929716
2018/08/23
8.8K0
基于FFmpeg进行RTMP推流(二)
基于FFmpeg进行RTMP推流(一)简介
这里的bin、include、lib就是我们刚才在FFmpeg下载的相关文件。 src是我们的项目源码目录。 新建Win32控制台应用程序、选择位置、项目名称。注意:去掉“为结局方案创建目录”的勾选
用户2929716
2018/08/23
14.2K0
基于FFmpeg进行RTMP推流(一)简介
FFmpeg流媒体处理-收流与推流
本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10623968.html
叶余
2019/04/19
10.4K1
FFmpeg流媒体处理-收流与推流
FFmpeg菜鸡互啄#第7篇#文件/rtsp推流到rtmp
关键步骤 avformat_open_input//打开输入文件/rtsp avformat_find_stream_info////获取音视频流信息 avformat_alloc_output_context2//创建输出上下文 avformat_new_stream//创建输出流 avcodec_copy_context//复制配置输出流 avio_open//打开io avformat_write_header//写入头信息 av_int
_gongluck
2018/03/08
3.3K0
FFmpeg封装格式处理4-转封装例程
源码修改自 FFmpeg 4.1 自带的例程 remuxing.c。代码非常简短:
叶余
2019/04/02
1.1K0
FFmpeg封装格式处理4-转封装例程
AVFormatContext封装层:理论与实战
AVFormatContext 是一个贯穿始终的数据结构,很多函数都用到它作为参数,是输入输出相关信息的一个容器,本文讲解 AVFormatContext 的封装层,主要包括两大数据结构:AVInputFormat,AVOutputFormat。
Gnep@97
2023/12/06
5510
AVFormatContext封装层:理论与实战
ffmpeg-视频操作
视频截取合并 __int64 index_context = 0, last_start_pts=0; std::list<AVFormatContext*> ifmt_ctx_lst; AVFormatContext *ofmt_ctx = nullptr, *ifmt_ctx = nullptr; void BeginSplitFile(const char* file, const char* out_file) { index_context = 0; AVFormatContext* ifmt
sofu456
2020/11/12
4570
如何将视频文件.h264和音频文件.mp3复用为输出文件output.mp4?
  在这个部分我们可以分三步进行:(1)打开输入视频文件上下文句柄 (2)打开输入音频文件上下文句柄 (3)打开输出文件上下文句柄
故乡的樱花开了
2023/10/22
2880
【JS】基于node-media-server搭建流媒体服务器示例
node-media-server 是一个基于 Node.js 的流媒体服务器,它提供了构建和管理实时音视频流媒体应用程序所需的功能。它是一个开源项目,具有灵活性和可扩展性,适用于各种流媒体应用场景。
DevFrank
2024/07/24
7390
ffmpeg实战实现音视频解封装!
大家好,很长一段时间没有继续更新ffmpeg的相关技术文章了,最近更多的时间和精力主要集中在给自己不断灌入新的知识,所以接下来只要有时间就会疯狂输出所学习到的技术干货!
用户6280468
2022/03/21
1.1K0
ffmpeg实战实现音视频解封装!
QT应用编程: 基于FFMPEG设计的流媒体播放器(播放rtmp视频流)
使用的FFMPEG库版本下载地址:https://download.csdn.net/download/xiaolong1126626497/12304729
DS小龙哥
2022/01/07
4.3K2
QT应用编程: 基于FFMPEG设计的流媒体播放器(播放rtmp视频流)
音视频八股文(11)-- ffmpeg avio 内存输入和内存输出。内存输出有完整代码,网上很少有的。
avio提供了一系列API,可以将数据从内存读取到缓冲区中,也可以将缓冲区中的数据写入到内存中。其实现依赖于IOContext结构体,该结构体定义了当前输入/输出事件的状态、数据、回调函数等信息,并支持通过自定义回调函数实现不同的输入/输出方式。
福大大架构师每日一题
2023/05/09
2.1K0
音视频八股文(11)-- ffmpeg avio 内存输入和内存输出。内存输出有完整代码,网上很少有的。
FFmpeg解封装实验!
大家好,我是txp,好久没有写技术原创文章了,久等了,记得之前写的播放器学习文章后面也没有继续更了;主要原因这段时间一个是由于工作的原因,二来主要是最近利用空闲时间看完了今年的第四本非技术书籍,目前又买了几本新的非技术书籍学习!在书上看到学到的知识,目前我都在总结输出!一些学习经验和工作当中的经验,我会慢慢录制视频出来,视频比文字更加生动(ps:因为之前录制的视频,不知道如何添加字幕,所以现在知道了,做就要认真做,就要把一件事情做好!)
用户6280468
2022/03/21
6760
FFmpeg解封装实验!
Android平台下使用FFmpeg进行RTMP推流(摄像头推流)
前面讲到了在Android平台下使用FFmpeg进行RTMP推流(视频文件推流),里面主要是介绍如何解析视频文件并进行推流,今天要给大家介绍如何在Android平台下获取采集的图像,并进行编码推流。同时项目工程也是在之前的代码基础上新增功能。源码仓库地址FFmpegSample,这一节对应的代码版本是v1.2。大家注意不要下载错了版本。主要涉及的代码。
用户2929716
2018/08/23
6.5K0
Android平台下使用FFmpeg进行RTMP推流(摄像头推流)
ffmpeg直播项目
一个描述数字音视频传输和播放流程的简单步骤:录制 -> 编码 -> 网络传输 -> 解码 -> 播放
Gnep@97
2023/12/30
3120
ffmpeg直播项目
ffmpeg音视频合成
原理 : 主要是拿到视频文件得视频流,然后拿到音频文件的音频流,根据时间戳一帧一帧的封装成一个新的视频文件
曾大稳
2018/09/11
3.1K1
如何通过OpenHarmony系统中集成的ffmpeg库和NAPI机制,实现更多的多媒体功能?
OpenAtom OpenHarmony(以下简称“OpenHarmony”)作为“开源”世界的“连接器”,不断为智能社会的发展提供源源不断的“源动力”。深开鸿一直以来积极投身于OpenHarmony社区建设,不断推动开源事业的发展。
小帅聊鸿蒙
2025/04/14
1180
如何通过OpenHarmony系统中集成的ffmpeg库和NAPI机制,实现更多的多媒体功能?
【C++】FFmpeg:音视频库介绍与使用示例
FFmpeg是一款开源的音视频库,提供了处理音视频文件、转码、解码、编码、播放等功能。它是一个完整的跨平台解决方案,支持多种音视频格式,并提供多种API和工具来处理音视频数据。
DevFrank
2024/07/24
7100
FFmpeg简单转码程序--视频剪辑
学习了雷神的文章,慕斯人分享精神,感其英年而逝,不胜唏嘘。他有分享一个转码程序《最简单的基于FFMPEG的转码程序》其中使用了filter(参考了ffmpeg.c中的流程),他曾说想再编写一个不需要filter的版本,可惜未有机会。恰好工作中有相关ffmpeg处理内容,故狗尾续貂,撰写本文。
jacker
2018/09/01
8.5K0
FFmpeg简单转码程序--视频剪辑
相关推荐
FFmpeg4.0笔记:rtsp2rtmp
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验