跨平台低延迟RTSP转RTMP推送技术方案探讨

这篇具有很好参考价值的文章主要介绍了跨平台低延迟RTSP转RTMP推送技术方案探讨。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

实现RTSP摄像头数据转RTMP推送到服务器,可以用第三方库或者工具实现,总体设计架构如下:

跨平台低延迟RTSP转RTMP推送技术方案探讨,流媒体,RTSP转RTMP,RTSP转发,RTMP转发,RTSP转推RTMP,大牛直播SDK 

一个好的转发模块,首先要低延迟!其次足够稳定、灵活、有状态反馈机制、资源占用低,跨平台,最好以接口形式提供,便于第三方系统集成,整体功能设计如下:

1. 拉流:通过RTSP直播播放SDK的数据回调接口,拿到音视频数据;

2. 转推:通过RTMP直播推送SDK的编码后数据输入接口,把回调上来的数据,传给RTMP直播推送模块,实现RTSP数据流到RTMP服务器的转发;

3. 录像:如果需要录像,借助RTSP直播播放SDK,拉到音视频数据后,直接存储MP4文件即可;

4. 快照:如果需要实时快照,拉流后,解码调用播放端快照接口,生成快照,因为快照涉及到video数据解码,如无必要,可不必开启,不然会额外消耗性能。

5. 拉流预览:如需预览拉流数据,只要调用播放端的播放接口,即可实现拉流数据预览;

6. 数据转AAC后转发:考虑到好多监控设备出来的音频可能是PCMA/PCMU的,如需要更通用的音频格式,可以转AAC后,在通过RTMP推送;

7. 转推RTMP实时静音:只需要在传audio数据的地方,加个判断即可;

8. 拉流速度反馈:通过RTSP播放端的实时码率反馈event,拿到实时带宽占用即可;

9. 整体网络状态反馈:考虑到有些摄像头可能会临时或异常关闭,RTMP服务器亦是,可以通过推拉流的event回调状态,查看那整体网络情况,如此界定:是拉不到流,还是推不到RTMP服务器。

下面分别介绍下两种技术方案:

FFmpeg技术方案

  1. 安装FFmpeg:首先,您需要安装FFmpeg。FFmpeg是一个开源的跨平台视频和音频处理工具,它支持将RTSP流转换为RTMP流。您可以从FFmpeg官方网站下载适用于Windows的二进制安装程序,并按照说明进行安装。
  2. 配置FFmpeg:安装完FFmpeg后,您需要配置其命令行参数,以便将RTSP流转换为RTMP流,并将其推送到目标服务器。您可以使用以下命令行参数:
 ffmpeg -i rtsp://[摄像头地址]/[流媒体地址] -f flv rtmp://[服务器地址]/[直播频道]

其中,​​rtsp://[摄像头地址]/[流媒体地址]​​是摄像头的RTSP流地址,​​rtmp://[服务器地址]/[直播频道]​​是目标服务器的RTMP流地址。您可以根据实际情况修改这些参数。

  1. 运行FFmpeg:配置完FFmpeg后,您可以使用命令行或脚本文件来运行FFmpeg。您可以在命令行中直接运行上述命令,或者将命令写入脚本文件(例如bat文件),然后运行脚本文件。需要注意的是,上述方案中的摄像头地址、流媒体地址、服务器地址和直播频道都需要替换为实际的地址和信息。此外,您还需要确保摄像头的RTSP流可公开访问,并且目标服务器的RTMP流地址已经配置正确。
  2. 集成到应用程序中:如果您需要在应用程序中实现实时视频流推送,您可以将FFmpeg集成到应用程序中。您可以使用FFmpeg的API或命令行接口,通过编程方式调用FFmpeg的功能,并将摄像头的RTSP流转换为RTMP流,并将其推送到目标服务器。

SDK技术方案

以大牛直播SDK的Windows平台RTSP转RTMP推送C++的demo为例:

1. 拉流:拉流和播放有些类似,但不需要播放(也就是说不要解码,资源消耗非常低),在做过基础的参数配置之后(对应demo里面OpenPullHandle()),设置音视频数据回调,然后调用StartPullStream()即可:

1.1 基础参数设置:

bool nt_stream_relay_wrapper::OpenPullHandle(const std::string& url, bool is_rtsp_tcp_mode, bool is_mute)
{
	if ( pull_handle_ != NULL )
		return true;

	if ( url.empty() )
		return false;

	duration_ = 0;

	NT_HANDLE pull_handle = NULL;

	ASSERT( pull_api_ != NULL );
	if (NT_ERC_OK != pull_api_->Open(&pull_handle, render_wnd_, 0, NULL))
	{
		return false;
	}

	ASSERT(pull_handle != NULL);

	pull_api_->SetEventCallBack(pull_handle, this, &NT_Pull_SDKEventHandle);

	pull_api_->SetBuffer(pull_handle, 0);
	pull_api_->SetFastStartup(pull_handle, 1);
	pull_api_->SetRTSPTcpMode(pull_handle, is_rtsp_tcp_mode ? 1 : 0);
	pull_api_->SetMute(pull_handle, is_mute ? 1 : 0);

	if ( NT_ERC_OK != pull_api_->SetURL(pull_handle, url.c_str()) )
	{
		pull_api_->Close(pull_handle);
		pull_handle = NULL;
		return false;
	}

	if ( setting_pos_ >= 0ll )
	{
		pull_api_->SetPos(pull_handle, setting_pos_);
	}

	pull_handle_ = pull_handle;

	return true;
}

1.2 设置音视频数据回调:

pull_api_->SetPullStreamVideoDataCallBack(pull_handle_, this, &SP_SDKPullStreamVideoDataHandle);
pull_api_->SetPullStreamAudioDataCallBack(pull_handle_, this, &SP_SDKPullStreamAudioDataHandle);

1.3 开始拉流:

auto ret = pull_api_->StartPullStream(pull_handle_);
	if ( NT_ERC_OK != ret )
	{
		if ( !is_playing_ )
		{
			pull_api_->Close(pull_handle_);
			pull_handle_ = NULL;
		}
		
		return false;
	}

拉流整体代码如下:

bool nt_stream_relay_wrapper::StartPull(const std::string& url, bool is_rtsp_tcp_mode, bool is_transcode_aac)
{
	if ( is_pulling_ )
		return false;

	if ( !OpenPullHandle(url, is_rtsp_tcp_mode) )
		return false;

	pull_api_->SetPullStreamVideoDataCallBack(pull_handle_, this, &SP_SDKPullStreamVideoDataHandle);

	pull_api_->SetPullStreamAudioDataCallBack(pull_handle_, this, &SP_SDKPullStreamAudioDataHandle);

	pull_api_->SetPullStreamAudioTranscodeAAC(pull_handle_, is_transcode_aac? 1: 0);

	auto ret = pull_api_->StartPullStream(pull_handle_);
	if ( NT_ERC_OK != ret )
	{
		if ( !is_playing_ )
		{
			pull_api_->Close(pull_handle_);
			pull_handle_ = NULL;
		}
		
		return false;
	}

	is_pulling_ = true;

	return true;
}

2. 停止拉流:

停止拉流流程比较简单,先判断是否在拉流状态,如果拉流,调用StopPullStream() 即可,如没有预览画面,调用Close()接口关闭拉流实例。

void nt_stream_relay_wrapper::StopPull()
{
	if ( !is_pulling_ )
		return;

	pull_api_->StopPullStream(pull_handle_);

	if ( !is_playing_ )
	{
		pull_api_->Close(pull_handle_);
		pull_handle_ = NULL;
	}

	is_pulling_ = false;
}

3. 拉流端预览:

拉流端预览,说白了就是播放拉流数据,流程比较简单,demo调用如下,如不需要播放声音,调用SetMute(),实时打开/关闭即可:

bool nt_stream_relay_wrapper::StartPlay(const std::string& url, bool is_rtsp_tcp_mode, bool is_mute)
{
	if ( is_playing_ )
		return false;

	if ( !OpenPullHandle(url, is_rtsp_tcp_mode, is_mute) )
		return false;

	pull_api_->SetMute(pull_handle_, is_mute ? 1 : 0);

	auto ret = pull_api_->StartPlay(pull_handle_);
	if ( NT_ERC_OK != ret )
	{
		if ( !is_pulling_ )
		{
			pull_api_->Close(pull_handle_);
			pull_handle_ = NULL;
		}

		return false;
	}

	is_playing_ = true;

	return true;
}

4. 拉流端关闭预览:

void nt_stream_relay_wrapper::StopPlay()
{
	if ( !is_playing_ )
		return;

	pull_api_->StopPlay(pull_handle_);

	if ( !is_pulling_ )
	{
		pull_api_->Close(pull_handle_);
		pull_handle_ = NULL;
	}

	is_playing_ = false;
}

5. 开始推流到RTMP服务器:

推流的流程,如之前所述,调用RTMP推送模块,然后数据源传编码后的音视频数据即可,下图的demo源码,同时展示了,RTSP流获取到后,转推RTMP的时候,数据解密的处理:

bool nt_stream_relay_wrapper::StartPush(const std::string& url)
{
	if ( is_pushing_ )
		return false;

	if ( url.empty() )
		return false;

	if ( !OpenPushHandle() )
		return false;

	auto push_handle = GetPushHandle();
	ASSERT(push_handle != nullptr);

	ASSERT(push_api_ != NULL);
	if ( NT_ERC_OK != push_api_->SetURL(push_handle, url.c_str(), NULL) )
	{
		if ( !is_started_rtsp_stream_ )
		{
			push_api_->Close(push_handle);
			SetPushHandle(nullptr);
		}

		return false;
	}

	if ( NT_ERC_OK != push_api_->StartPublisher(push_handle, NULL) )
	{
		if ( !is_started_rtsp_stream_ )
		{
			push_api_->Close(push_handle);
			SetPushHandle(nullptr);
		}

		return false;
	}

	is_pushing_ = true;

	return true;
}

6. 传递转推RTMP数据:

void nt_stream_relay_wrapper::OnVideoDataHandle(NT_HANDLE handle, NT_UINT32 video_codec_id, 
	NT_BYTE* data, NT_UINT32 size, NT_SP_PullStreamVideoDataInfo* info)
{
	if (!is_pushing_ && !is_started_rtsp_stream_)
		return;

	if ( pull_handle_ != handle )
		return;

	if (data == NULL)
		return;

	if (size < 1)
		return;

	if (info == NULL)
		return;

	std::unique_lock<std::recursive_mutex> lock(push_handle_mutex_);

	if (!is_pushing_ && !is_started_rtsp_stream_)
		return;

	if (push_handle_ == NULL)
		return;

	push_api_->PostVideoEncodedDataV2(push_handle_, video_codec_id,
		data, size, info->is_key_frame_, info->timestamp_, info->presentation_timestamp_);
}

void nt_stream_relay_wrapper::OnAudioDataHandle(NT_HANDLE handle, NT_UINT32 auido_codec_id,
	NT_BYTE* data, NT_UINT32 size, NT_SP_PullStreamAuidoDataInfo* info)
{
	if (!is_pushing_ && !is_started_rtsp_stream_)
		return;

	if (pull_handle_ != handle)
		return;

	if (data == NULL)
		return;

	if (size < 1)
		return;

	if (info == NULL)
		return;

	std::unique_lock<std::recursive_mutex> lock(push_handle_mutex_);

	if (!is_pushing_ && !is_started_rtsp_stream_)
		return;

	if (push_handle_ == NULL)
		return;

	push_api_->PostAudioEncodedData(push_handle_, auido_codec_id, data, size,
		info->is_key_frame_, info->timestamp_, 
		info->parameter_info_, info->parameter_info_size_);
}

7. 关闭实时RTMP转推

void nt_stream_relay_wrapper::StopPush()
{
	if ( !is_pushing_ )
		return;

	is_pushing_ = false;

	std::unique_lock<std::recursive_mutex> lock(push_handle_mutex_);

	if ( nullptr == push_handle_ )
		return;

	push_api_->StopPublisher(push_handle_);

	if ( !is_started_rtsp_stream_ )
	{
		push_api_->Close(push_handle_);

		push_handle_ = nullptr;
	}
}

总结

无论您选择哪种方案,需要确保以下几点:

  1. 选择一个稳定可靠的第三方库或服务,以确保转换的质量和可靠性;
  2. 了解和掌握相关的技术和协议,例如RTSP和RTMP,以及如何使用相关的库和工具进行转换和处理;
  3. 考虑性能和资源的问题,特别是在处理大量视频流或高并发的场景下。需要确保系统具有足够的处理能力和带宽,以避免延迟或丢帧等问题。

Windows平台上的RTSP转RTMP推送需要一些技术准备和规划,以及对相关协议和工具的理解和使用经验,做个基础的demo,用FFmpeg就可以,但是如果产品话,需要考虑的点实在太多了。

 文章来源地址https://www.toymoban.com/news/detail-545591.html

到了这里,关于跨平台低延迟RTSP转RTMP推送技术方案探讨的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 微信跨平台方案Donut快速上手

    Donut 是微信开发出的多端框架,用于支持使用小程序原生语法开发移动应用的框架,开发者可以一次编码,就可以编译出小程序和 Android 以及 iOS 应用,实现多端开发。能够帮助企业有效降低多端应用开发的技术门槛和研发成本,以及提升开发效率和开发体验。 目前,Donut已

    2024年02月14日
    浏览(33)
  • 一站式解决方案:Qt 跨平台开发灵活可靠

    一站式解决方案:Qt 跨平台开发灵活可靠 Qt 是一种跨平台开发工具,为开发者提供了一站式解决方案。无论您的项目目标是 Windows、Linux、macOS、嵌入式系统还是移动平台,Qt 都能胜任。这种跨平台的特性不仅节省开支,还推动了战略的快速落地。 适用范围广泛:Qt 可在多种

    2024年02月07日
    浏览(38)
  • 打破硬件壁垒:TVM 助力 AI技术跨平台部署

    随着人工智能(Artificial Intelligence,AI)在全世界信息产业中的广泛应用,深度学习模型已经成为推动AI技术革命的关键。TensorFlow、PyTorch、MXNet、Caffe等深度学习模型已经在服务器级GPU上取得了显著的成果。然而,大多数现有的系统框架只针对小范围的服务器级GPU进行过优化,

    2024年01月19日
    浏览(34)
  • 【前端进阶】跨平台开发与原生应用:技术融合的未来

    在移动设备的快速普及和大规模应用的背景下,开发应用程序的跨平台能力已成为前端开发人员不可或缺的技能。跨平台开发允许我们使用统一的代码库构建应用程序,同时在多个平台上实现原生应用的性能和体验。在本文中,我们将探讨跨平台开发的概念、优势以及目前流

    2024年02月11日
    浏览(61)
  • 【uniapp&微信小程序】跨平台使用echarts的方案选择&踩坑

    使用Uniapp(vue)开发微信小程序,想用echarts图表实现类似github热力图的效果。 简要列一些可行或不可行的方案。 有echarts官网提供的跨平台方案:在微信小程序中使用 ECharts 简单易用,图表齐全 renderjs-echarts-demo 可参考的使用总结 render.js+echarts echarts图表在移动端的应用 支持

    2024年02月13日
    浏览(53)
  • web自动化测试——跨平台设备管理方案Selenium Grid

    Selenium Grid 是 Selenium 的三大组件之一,它可以在多台机器上并行运行测试,集中管理不同的浏览器版本和浏览器配置。通过将客户端命令发送到远程浏览器的实例, Selenium Grid 允许在远程计算机 (虚拟或真实) 上执行 WebDriver 脚本. 它旨在提供一种在多台计算机上并行运行测试的

    2024年02月08日
    浏览(37)
  • .NET Core使用SkiaSharp快速生成二维码( 真正跨平台方案)

    在.NET 6之前我们一直是使用QRCoder来生成二维码(QRCoder是一个非常强大的生成二维码的组件,用到了 System.Drawing.Common  包),然后从.NET 6开始,当为非 Windows 操作系统编译引用代码时,平台分析器会发出编译时警告。异常如下: 由于 System.Drawing.Common 被设计为 Windows 技术的精

    2024年01月20日
    浏览(35)
  • 智慧养殖APP及小程序多端跨平台技术选型分析

    1. 框架选择 ------Uniapp------ 优势 :使用Vue.js语法,学习成本较低;一套代码,能同时支持APP/H5/小程序,是较为全面的跨平台框架。 ​ 开发小程序的不二选择,考虑到国内小程序应用广泛,之后可能会有所涉及。 劣势 :开发App端时,性能有瓶颈,但是也可以胜任大部分的场

    2024年02月15日
    浏览(38)
  • Unity跨平台UI解决方案:可能是最全的FairyGUI系列教程

    FairyGUI的项目文件结构 .objs 内部数据目录。注意:不要加入版本管理,因为这里的内容是不需要共享的。 assets 包内容放置目录,资源内容都在这里面,里面还可以分不同的包,便于区分管理(看下图) settings 配置文件放置目录。 ****.fairy 项目识别文件,也就是项目名称 目录

    2024年04月14日
    浏览(31)
  • 低代码开发中的Nacos配置:跨平台跳转的解决方案

    在当今低代码开发的时代,平台的易用性和灵活性非常重要。右上角平台跳转作为用户界面中常见的交互元素,对于提高用户体验具有举足轻重的地位。然而,有时候我们会遇到跳转失效的情况,这无疑给用户带来了困扰。本文以JVS低代码平台为例,探讨如何通过后台配置来

    2024年01月25日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包