首页 > 其他分享 >用ZLMedia实现rtmp拉流转推流(rtmp/hls)

用ZLMedia实现rtmp拉流转推流(rtmp/hls)

时间:2023-05-31 10:46:07浏览次数:45  
标签:const string app hls rtmp include poller ZLMedia

业务场景是:有一个rtmp的源,对外提供rtmp的直播节目,地址rtmp://abc.com/live/tv,    现在的需求是要将此节目拉过来,生成HLS对外发布,或对外还是rtmp发布,比如rtmp://my.com/live/tv。   作用嘛,肯定是你懂的!   此时需要一个把rtmp数据拉过来,再推出去的动作,一般推给SRS流媒体服务器后,即可随意对外分发提供rtmp或hls。   如何实现呢?   一般的流媒体服务器,像SRS提供许多流媒体格式的输出,可以用于进行流媒体处理,但此时需要一个拉流的程序。SRS里面用的是ffmpeg程序,但是个人感觉并不是特别好用,比如在某种情况下,ffmpeg卡死了,但是SRS并不会让ffmpeg重新拉流。   这里推荐两种方法:   一、使用zlmedia 的json API实现 最简单的办法就是使用zlmedia的mediaproxy API接口,即可完成,具体可参考   MediaServer支持的HTTP API · ZLMediaKit/ZLMediaKit Wiki · GitHub    "/index/api/addStreamProxy" 二、使用zlmedia进行二次开发 如果需要用程序进行自定义实现,可以参照     https://github.com/xia-chu/ZLMediaKit/blob/master/tests/test_pusher.cpp   假定SRS运行在本机的1935端口,推给SRS后,由SRS再处理对外发布。     int main(int argc, char *argv[]) {     return domain("rtmp://abc.com/live/hks1", "rtmp://127.0.0.1/live/tv"); }  以下是我根据ZLMediaKit中的 test_pusher修改后的代码,可以从外界传递参数到程序中,实现自定义拉流并转推。    实测此功能正常运行,稳定性还不错。   程序的编译方法:在编译zlmedia的时候会自动编译test目录下的所有.cpp。     #include <signal.h> #include <iostream> #include "Util/logger.h" #include "Util/NoticeCenter.h" #include "Poller/EventPoller.h" #include "Player/PlayerProxy.h" #include "Rtmp/RtmpPusher.h" #include "Common/config.h" #include "Pusher/MediaPusher.h"   #include "Util/CMD.h"   using namespace std; using namespace toolkit; using namespace mediakit;   //推流器,保持强引用 MediaPusher::Ptr pusher; Timer::Ptr g_timer;   //声明函数 void rePushDelay(const EventPoller::Ptr &poller,const string &schema,const string &vhost,const string &app, const string &stream, const string &url);   //创建推流器并开始推流 void createPusher(const EventPoller::Ptr &poller, const string &schema,const string &vhost,const string &app, const string &stream, const string &url) {     //创建推流器并绑定一个MediaSource     pusher.reset(new MediaPusher(schema,vhost, app, stream,poller));     //可以指定rtsp推流方式,支持tcp和udp方式,默认tcp //    (*pusher)[Client::kRtpType] = Rtsp::RTP_UDP;     //设置推流中断处理逻辑     pusher->setOnShutdown([poller,schema,vhost, app, stream, url](const SockException &ex) {         WarnL << "Server connection is closed:" << ex.getErrCode() << " " << ex.what();         //重试         rePushDelay(poller,schema,vhost,app, stream, url);     });     //设置发布结果处理逻辑     pusher->setOnPublished([poller,schema,vhost, app, stream, url](const SockException &ex) {         if (ex) {             WarnL << "Publish fail:" << ex.getErrCode() << " " << ex.what();             //如果发布失败,就重试             rePushDelay(poller,schema,vhost,app, stream, url);         } else {             InfoL << "Publish success,Please play with player:" << url;         }     });     pusher->publish(url); }   //推流失败或断开延迟2秒后重试推流 void rePushDelay(const EventPoller::Ptr &poller,const string &schema,const string &vhost,const string &app, const string &stream, const string &url) {     g_timer = std::make_shared<Timer>(2,[poller,schema,vhost,app, stream, url]() {         InfoL << "Re-Publishing...";         //重新推流         createPusher(poller,schema,vhost,app, stream, url);         //此任务不重复         return false;     }, poller); }   //这里才是真正执行main函数,你可以把函数名(domain)改成main,然后就可以输入自定义url了 int domain(const string &playUrl, const string &pushUrl) {   auto poller = EventPollerPool::Instance().getPoller();     //拉一个流,生成一个RtmpMediaSource,源的名称是"app/stream"     //你也可以以其他方式生成RtmpMediaSource,比如说MP4文件(请查看test_rtmpPusherMp4.cpp代码)     MediaInfo info(pushUrl);     PlayerProxy::Ptr player(new PlayerProxy(DEFAULT_VHOST, "app", "stream",false,false,-1 , poller));     //可以指定rtsp拉流方式,支持tcp和udp方式,默认tcp //    (*player)[Client::kRtpType] = Rtsp::RTP_UDP;     player->play(playUrl.data());       //监听RtmpMediaSource注册事件,在PlayerProxy播放成功后触发     NoticeCenter::Instance().addListener(nullptr, Broadcast::kBroadcastMediaChanged,                                          [pushUrl,poller](BroadcastMediaChangedArgs) {                                              //媒体源"app/stream"已经注册,这时方可新建一个RtmpPusher对象并绑定该媒体源                                              if(bRegist && pushUrl.find(sender.getSchema()) == 0){                                                  createPusher(poller,sender.getSchema(),sender.getVhost(),sender.getApp(), sender.getId(), pushUrl);                                              }                                          });       //设置退出信号处理函数     static semaphore sem;     signal(SIGINT, [](int) { sem.post(); });// 设置退出信号     sem.wait();     pusher.reset();     g_timer.reset();     return 0; }       int main(int argc, char *argv[])  { // ./ffmpeg -loglevel info  -f flv -i rtmp://test.yunyingtx.com/live/PLTV/88888888/tv  // -vcodec copy -acodec copy -f flv -y rtmp://127.0.0.1:1936/live/tv string input; string output; try { for (int i = 0; i < argc-1; i++) { if (string(argv[i]) == "-i") input = argv[i + 1]; } for (int i = 0; i < argc - 1; i++) { if (string(argv[i]) == "-y") output = argv[i + 1]; }   } catch (std::exception &ex) { cout << ex.what() << endl; return -1; }         if (input.find("rtmp://") == string::npos || output.find("rtmp://") == string::npos) { return -1; }   EventPollerPool::setPoolSize(1);   //设置日志 LogLevel logLevel = (LogLevel)LDebug;// Logger::Instance().add(std::make_shared<ConsoleChannel>()); Logger::Instance().setWriter(std::make_shared<AsyncLogWriter>()); auto fileChannel = std::make_shared<FileChannel>("FileChannel", exeDir() + "../logs/", logLevel); fileChannel->setMaxDay(7); Logger::Instance().add(fileChannel);     DebugL << "program started." << endl; DebugL << input<<endl; DebugL << output<<endl;         return domain(input, output);//"rtmp://127.0.0.1/live/cctv13" }               zlmedia本身存在一个问题:拉流时有中断的现象,就是说rtmp源还在播,但是我们的这个程序不知道因为什么原因停止工作了,导致整个媒体处理流程中断。   经过长时间的跟踪和调试,发现ZLMediaKit在处理 rtmp的流程存在问题   https://github.com/xia-chu/ZLMediaKit/issues/455   解决办法是在ZLMediaKit的 src/Rtmp/RtmpPlayerImp.h 文件中 对onCheckMeta() 函数加入对 _delegate为空的判断,只有为空的时候才reset()。   修改前:       bool onCheckMeta(const AMFValue &val) override {         _rtmp_src = dynamic_pointer_cast<RtmpMediaSource>(_pMediaSrc);         if (_rtmp_src) {             _rtmp_src->setMetaData(val);             _set_meta_data = true;         }         _delegate.reset(new RtmpDemuxer);         _delegate->loadMetaData(val);         return true;     } 修改后 :       bool onCheckMeta(const AMFValue &val) override {         _rtmp_src = dynamic_pointer_cast<RtmpMediaSource>(_pMediaSrc);         if (_rtmp_src) {             _rtmp_src->setMetaData(val);             _set_meta_data = true;         } if (!_delegate) { _delegate.reset(new RtmpDemuxer); _delegate->loadMetaData(val); } return true;     }  

标签:const,string,app,hls,rtmp,include,poller,ZLMedia
From: https://www.cnblogs.com/kn-zheng/p/17445375.html

相关文章

  • Android平台如何实现外部RTSP|RTMP流注入轻量级RTSP服务模块(内网RTSP网关)
     技术背景今天分享的是外部RTSP或RTMP流,拉取后注入到本地轻量级RTSP服务模块,供内网小并发场景下使用,这里我们叫做内网RTSP网关模块。内网RTSP网关模块,系内置轻量级RTSP服务模块扩展,完成外部RTSP/RTMP数据拉取并注入到轻量级RTSP服务模块工作,多个内网客户端直接访问内网轻量级RTSP......
  • [技术分享]Android平台音视频推送选RTMP还是GB28181?
    技术背景早在2015年,我们发布了RTMP直播推送模块,那时候音视频直播这块场景需求,还不像现在这么普遍,我们做这块的初衷,主要是为了实现移动单兵应急指挥系统的低延迟音视频数据传输。好多开发者可能会疑惑,走RTMP怎么可能低延迟?网上看到的RTMP推拉流延迟,总归要2-3秒起,如果是自己实现框架,R......
  • LiveNVR视频平台接收无人机等移动终端RTMP推流后转成GB28181协议输出级联到GB28181视
    1、需求介绍目前很多移动终端设备(如无人机等)只支持RTMP推流输出,不支持GB28181协议。但是又有需要通过GB28181协议接入到视频平台的需求。比如有些大疆无人机产品不能直接注册国标平台,只能rtmp推流。那么,项目中如果将无人机的rtmp的推流转成GB/T281812、获取RTMP推流地址2.1、RT......
  • Rtmp s0、s1、s2握手协议的格式
    1、简单的方法从这里分析,s0、s1、s2格式:s0:1byte,version,为0x03s1:time:4bytes,当前时间time2:4bytes,拷贝自接收到的c1的开始4字节time余下随机数s2:完全拷贝自c1数据......
  • ffmpeg拉rtmp流并用SDL播放
    开发环境操作系统:win10IDE:vs2019ffmpeg版本:5.1#include<stdio.h>#define__STDC_CONSTANT_MACROS#include"libavformat/avformat.h"#include"libavutil/mathematics.h"#include"libavutil/time.h"#include"libavcodec/avcodec.h&qu......
  • Qt编写视频监控系统73-不同视频流不同类型的判断和解析(http/m3u8/rtsp/rtmp等)
    一、前言这套视频监控系统大概从2018年起步整体框架,一步步积累到现在,中间经历了无数次的各种视频文件、视频流、视频设备的播放测试,比如光视频文件就有mp4/wmv/rmvb/mkv/avi等格式,视频设备有本地USB摄像头、桌面等,视频流有rtmp/rtsp/rtp/http等,其中http开头的就有视频文件和视频......
  • Windows上搭建rtsp-simple-server流媒体服务器实现rtsp、rtmp等推流以及转流、前端htm
    上面讲了Nginx-http-flv-module+flv.js进行流媒体服务器搭建和前端播放视频流的过程。但是Nginx-http-flv-module对于Windows的支持以及推流格式的支持优先,所以下面推荐rtsp-simple-server流媒体服务器的使用。rtsp-simple-serverhttps://github.com/aler9/rtsp-simple-serverrtsp-......
  • Qt推流程序(视频文件/视频流/摄像头/桌面转成流媒体rtmp+hls+webrtc)可在网页和播放器远
    一、前言说明推流直播就是把采集阶段封包好的内容传输到服务器的过程。其实就是将现场的视频信号从手机端,电脑端,摄影机端打包传到服务器的过程。“推流”对网络要求比较高,如果网络不稳定,直播效果就会很差,观众观看直播时就会发生卡顿等现象,观看体验比较糟糕。主流推送协议有RTMP、......
  • ZLMediaKit报错,程序启动失败,请修改配置文件中端口号后重试!
    报错信息如下:2023-05-0910:33:22.819W[MediaServer][13423-MediaServer]sockutil.cpp:421bind_sock6|Bindsocketfailed:addressalreadyinuse2023-05-0910:33:22.819W[MediaServer][13423-MediaServer]main.cpp:366start_main|端口占用或无权限:Listenon:......
  • linux下安装nginx-rtmp
    1.下载安装包并且解压mkdirnginxcdnginxwgethttps://repo.huaweicloud.com/nginx/nginx-1.17.9.tar.gzwgethttps://codeload.github.com/arut/nginx-rtmp-module/tar.gz/v1.2.1tar-zxvfnginx-1.17.9.tar.gzunzipmaster.zip2.安装基础环境yuminstall-yopenss......