国网B接口语音对讲和广播技术探究及与GB28181差别
接口描述
在谈国网B接口的语音广播和语音对讲的时候,大家会觉得,国网B接口是不是和GB28181大同小异?实际上确实信令有差别,但是因为要GB28181设备接入测的对接,再次做国网B接口就简单多了。
语音对讲和广播包括信令接口和媒体流接口,采用与“调阅实时视频”流程相同的机制,不同之处
在于用户发出的请求消息的 SDP 仅携带音频描述信息。
语音所采用的编解码算法为 ITU-T G.711A。
语音对讲和广播,被调阅的平台无需进行音频分发行为。
接口流程
语音对讲和广播的接口流程如下:

主要功能流程如下:
a) F1:平台用户,对前端系统指定的前端系统摄像机发起实时音频的调阅请求,发送 INVITE 消
息,携带 SDP 内容,通过平台转发到前端系统。
b) F2:按照 SIP 要求,如前端系统在 0.5 s 内未处理该请求,则先发送 1xx 临时响应给平台。
c) F3:前端系统接受了调阅请求的操作,则发送携带 SDP 的 200 OK 响应到平台。
d) F4:平台发送 ACK 给前端系统,确认会话建立。
e) 实时语音流开始传输,前端设备/用户根据相应的解码器解码并语音输出。
f) F5:用户结束会话,平台发送 BYE 消息到前端系统。
g) F6:前端系统发送确认,将媒体通道拆线,会话结束。
接口参数
SIP头字段如下:

SIP响应码返回码如下:

SIP参数定义:

RTP 动态 Payload 定义如下:

消息示例
INVITE sip:前端设备地址编码@前端系统所属平台域名或IP地址 SIP/2.0
From: <sip:用户地址编码@用户所属平台域名或IP地址>;tag=3101300
To: <sip:前端设备地址编码@前端系统所属平台域名或IP地址>
Contact: <sip:用户地址编码@用户所属平台域名或IP地址>
Call-ID: c47k42
Via: SIP/2.0/UDP 用户所属平台IP地址;branch=z9hG4bK
CSeq: 1 INVITE
Content-type: application/SDP
Content-Length: 消息体的长度
v=0
o=- 0 0 IN IP4 用户会话IP地址描述
s=-
c=IN IP4 用户媒体IP地址描述
m=audio 38564 RTP/AVP 8
a=rtpmap:8 PCMA/8000
a=sendrecv
语音会话请求响应如下:
SIP/2.0 200 OK
From: <sip: 用户地址编码@用户所属平台域名或IP地址>;tag=3101300
To: <sip: 前端设备地址编码@前端系统所属平台域名或IP地址>;tag=20b0660
Contact: <sip: 用户地址编码@用户所属平台域名或IP地址>
Call-ID: c47k42
Via: SIP/2.0/UDP 用户所属平台IP地址;branch=z9hG4bK
CSeq: 1 INVITE
Content-type: application/SDP
Content-Length: 消息体的长度
v=0
o=- 0 0 IN IP4 前端设备会话IP地址描述
s=-
c=IN IP4 前端设备媒体IP地址描述
m=audio 1000 RTP/AVP 8
a=rtpmap:8 PCMA/8000
a=sendrecv
代码实现
@Overridepublic void ntsOnInviteTalk(String deviceId, SessionDescription sessionDescription) {handler_.postDelayed(new Runnable() {@Overridepublic void run() {// 先振铃响应下gb28181_agent_.respondTalkInvite(180, device_id_);MediaSessionDescription audio_description = null;SDPRtpMapAttribute rtp_map_attribute = null;Vector<MediaSessionDescription> audio_des_list = session_description_.getAudioDescriptions();if (audio_des_list != null && !audio_des_list.isEmpty()) {// 先尝试获取PCMA格式for(MediaSessionDescription m : audio_des_list) {if (m != null && m.isValidAddressType() && m.isHasAddress()) {rtp_map_attribute = m.getRtpMapAttribute(SDPRtpMapAttribute.PCMA_ENCODING_NAME);if (rtp_map_attribute != null) {audio_description = m;break;}}}// 如果没有PCMA格式,尝试获取PS格式if (null == rtp_map_attribute) {for(MediaSessionDescription m : audio_des_list) {if (m != null && m.isValidAddressType() && m.isHasAddress()) {rtp_map_attribute = m.getRtpMapAttribute(SDPRtpMapAttribute.PS_ENCODING_NAME);if (rtp_map_attribute != null) {audio_description = m;break;}}}}}if (null == audio_description) {gb28181_agent_.respondTalkInvite(488, device_id_);Log.i(TAG, "ntsOnInviteTalk get audio description is null, response 488, device_id:" + device_id_);return;}if (null == rtp_map_attribute ) {gb28181_agent_.respondTalkInvite(488, device_id_);Log.i(TAG, "ntsOnInviteTalk get rtp map attribute is null, response 488, device_id:" + device_id_);return;}Log.i(TAG,"ntsOnInviteTalk, device_id:" +device_id_+", is_tcp:" + audio_description.isRTPOverTCP()+ " rtp_port:" + audio_description.getPort() + " ssrc:" + audio_description.getSSRC()+ " address_type:" + audio_description.getAddressType() + " address:" + audio_description.getAddress()+ " payload_type:" + rtp_map_attribute.getPayloadType() + " encoding_name:" + rtp_map_attribute.getEncodingName());long rtp_sender_handle = libPublisher.CreateRTPSender(0);if (0 == rtp_sender_handle) {gb28181_agent_.respondTalkInvite(488, device_id_);Log.i(TAG, "ntsOnInviteTalk CreateRTPSender failed, response 488, device_id:" + device_id_);return;}gb_talk_rtp_payload_type_ = rtp_map_attribute.getPayloadType();gb_talk_rtp_encoding_name_ = rtp_map_attribute.getEncodingName();Log.i(TAG, "gb_talk_rtp_payload_type: " + gb_talk_rtp_payload_type_ + " gb_talk_rtp_encoding_name: " + gb_talk_rtp_encoding_name_);gb_talk_rtp_encoding_name_ = "PS";libPublisher.SetRTPSenderTransportProtocol(rtp_sender_handle, audio_description.isRTPOverUDP()?0:1);libPublisher.SetRTPSenderIPAddressType(rtp_sender_handle, audio_description.isIPv4()?0:1);//libPublisher.SetRTPSenderLocalPort(rtp_sender_handle, 0);libPublisher.SetRTPSenderLocalPort(rtp_sender_handle, audio_description.getPort());libPublisher.SetRTPSenderSSRC(rtp_sender_handle, audio_description.getSSRC());libPublisher.SetRTPSenderSocketSendBuffer(rtp_sender_handle, 256*1024); // 音频配置到256KBlibPublisher.SetRTPSenderClockRate(rtp_sender_handle, rtp_map_attribute.getClockRate());libPublisher.SetRTPSenderDestination(rtp_sender_handle, audio_description.getAddress(), audio_description.getPort());gb_talk_is_receive_ = audio_description.isHasAttribute("sendrecv");Log.i(TAG, "gb_talk_is_receive: " + gb_talk_is_receive_);if (gb_talk_is_receive_) {libPublisher.EnableRTPSenderReceive(rtp_sender_handle, 1);// 收包SSRC, 暂时不设置, 因为部分平台ssrc不一致的// libPublisher.SetRTPSenderReceiveSSRC(rtp_sender_handle, audio_description.getSSRC());// 这个一定要设置libPublisher.SetRTPSenderReceivePayloadType(rtp_sender_handle, gb_talk_rtp_payload_type_, gb_talk_rtp_encoding_name_, 2, rtp_map_attribute.getClockRate());// 目前发现某些平台 PS-PCMA 是8000, 不建议设置if (gb_talk_rtp_encoding_name_.equals("PS")) {libPublisher.SetRTPSenderReceivePSClockFrequency(rtp_sender_handle, 8000);}// 如果是PCMA编码, 采样率和通道可以先不设置// libPublisher.SetRTPSenderReceiveAudioSamplingRate(rtp_sender_handle, 8000);// libPublisher.SetRTPSenderReceiveAudioChannels(rtp_sender_handle, 1);}if (libPublisher.InitRTPSender(rtp_sender_handle) != 0 ) {gb28181_agent_.respondTalkInvite(488, device_id_);libPublisher.DestoryRTPSender(rtp_sender_handle);return;}int local_port = libPublisher.GetRTPSenderLocalPort(rtp_sender_handle);if (0==local_port) {gb28181_agent_.respondTalkInvite(488, device_id_);libPublisher.DestoryRTPSender(rtp_sender_handle);return;}Log.i(TAG,"ntsOnInviteTalk get local_port:" + local_port);String local_ip_addr = IPAddrUtils.getIpAddress(context_);MediaSessionDescription main_local_audio_des = new MediaSessionDescription(audio_description.getType());main_local_audio_des.addFormat(String.valueOf(rtp_map_attribute.getPayloadType()));main_local_audio_des.addRtpMapAttribute(rtp_map_attribute);main_local_audio_des.addAttribute(new SDPAttribute("sendonly"));if (audio_description.isRTPOverTCP()) {// tcp主动链接服务端main_local_audio_des.addAttribute(new SDPAttribute("setup", "active"));main_local_audio_des.addAttribute(new SDPAttribute("connection", "new"));}main_local_audio_des.setPort(local_port);main_local_audio_des.setTransportProtocol(audio_description.getTransportProtocol());main_local_audio_des.setSSRC(audio_description.getSSRC());MediaSessionDescription sub_local_audio_des = null;if (gb_talk_is_receive_) {sub_local_audio_des = new MediaSessionDescription(audio_description.getType());sub_local_audio_des.addFormat(String.valueOf(rtp_map_attribute.getPayloadType()));sub_local_audio_des.addRtpMapAttribute(rtp_map_attribute);sub_local_audio_des.addAttribute(new SDPAttribute("recvonly"));if (audio_description.isRTPOverTCP()) {// tcp主动链接服务端sub_local_audio_des.addAttribute(new SDPAttribute("setup", "active"));sub_local_audio_des.addAttribute(new SDPAttribute("connection", "new"));}sub_local_audio_des.setPort(local_port);sub_local_audio_des.setTransportProtocol(audio_description.getTransportProtocol());sub_local_audio_des.setSSRC(audio_description.getSSRC());}if (!gb28181_agent_.respondTalkInviteOK(device_id_, audio_description.getAddressType(), local_ip_addr, main_local_audio_des, sub_local_audio_des) ) {libPublisher.DestoryRTPSender(rtp_sender_handle);Log.e(TAG, "ntsOnInviteTalk call respondPlayInviteOK failed.");return;}gb_talk_rtp_sender_handle_ = rtp_sender_handle;}private String device_id_;private SessionDescription session_description_;public Runnable set(String device_id, SessionDescription session_des) {this.device_id_ = device_id;this.session_description_ = session_des;return this;}}.set(deviceId, sessionDescription),0);}
总结
国网B接口的语音广播和语音对讲,和GB28181的还是有些差别,B接口的语音广播和语音对讲,不需要先发broadcast过来,不用设备接入端发invite请求,而是电网平台侧发invite,类似实时视频请求播放流程,感兴趣的开发者,可以根据规范仔细解读研究。
相关文章:
国网B接口语音对讲和广播技术探究及与GB28181差别
接口描述 在谈国网B接口的语音广播和语音对讲的时候,大家会觉得,国网B接口是不是和GB28181大同小异?实际上确实信令有差别,但是因为要GB28181设备接入测的对接,再次做国网B接口就简单多了。 语音对讲和广播包括信令接…...
非计算机专业如何转行成为程序员?我用亲身经历教你用这三种方法
哈喽大家好啊!我想分享一下,非计算机专业的学生如何转行成为程序员。首先,我先介绍一下我的情况。我是18年毕业的,大学学的专业是土木工程,与计算机一点关系都没有。但是在大学时,我对程序员比较感兴趣。本…...
2023年最新网络安全渗透工程师面试题汇总!不看亏大了!
技术面试问题 CTF 说一个印象深刻的CTF的题目 Padding Oracle->CBC->密码学(RSA/AES/DSA/SM) CRC32 反序列化漏洞 sql二次注入 第一次进行数据库插入数据的时候,仅仅只是使用了 addslashes 或者是借助get_magic_quotes_gpc 对其中的特殊字符进行了转义&…...
红黑树(C++实现)
文章目录 红黑树的概念红黑树的性质红黑树结点的定义红黑树的插入红黑树的查找红黑树的验证检测是否满足二叉搜索树检测是否满足红黑树的性质 红黑树与AVL树的比较包含上述功能的红黑树代码 红黑树的概念 红黑树,是一棵二叉搜索树,但在每一个结点上增加一个存储位表示结点的颜色…...
leetcode尊享面试 100 题 - 1427. 字符串的左右移
尊享面试 100 题是Leetcode会员专享题单 1427. 字符串的左右移 力扣题目链接 给定一个包含小写英文字母的字符串 s 以及一个矩阵 shift,其中 shift[i] [direction, amount]: direction 可以为 0 (表示左移)或 1 (表…...
进来看看!跨境电商要这样选品才能做出爆款
今天要聊的是跨境电商怎么做系列的第三期,前面两期聊完平台和货源之后,就到了选品。目前网络上很多都是告诉你不同平台要怎么选品。龙哥这期有些不同,不会和你说哪个品类最受欢迎,而是告诉你你要怎么去选择出适合自己、适合市场的…...
什么是深度学习?
目录 简介 深度学习的由来 深度学习未来的趋势 总结 简介 深度学习是在20世纪80年代被提出来的,主要是由加拿大的计算机科学家Geoffrey Hinton、Yoshua Bengio、Yann LeCun等人发起的。Geoffrey Hinton等人在经过多年的研究和实践之后,…...
追梦之旅【数据结构篇】——看看小白试如何利用C语言“痛”撕堆排序
追梦之旅【数据结构篇】——看看小白试如何利用C语言“痛”撕堆排序 ~😎 前言🙌堆的应用 —— 堆排序算法:堆排序算法源代码分享运行结果测试截图: 总结撒花💞 😎博客昵称:博客小梦 ὠ…...
python版pytorch模型转openvino及调用
一、openvino安装 参看官方文档https://www.intel.com/content/www/us/en/developer/tools/openvino-toolkit/download.html 安装命令是根据上面的选择生成。这里安装了pytorch和onnx依赖。 二、pytorch模型转opnvino模型推理 import os import time import cv2 import nu…...
TensorFlow 机器学习秘籍第二版:9~11
原文:TensorFlow Machine Learning Cookbook 协议:CC BY-NC-SA 4.0 译者:飞龙 本文来自【ApacheCN 深度学习 译文集】,采用译后编辑(MTPE)流程来尽可能提升效率。 不要担心自己的形象,只关心如何…...
【苏州数字力量】面经 base上海
文章目录 【苏州数字力量】面经 base上海Java基础面1.说一下常见的数据类型、大小、以及他们的封装类2.重载和重写的区别3.谈谈Java的引用方式4.String有些什么方法5.String、StringBuffer、StringBuilder的区别是什么6.谈一下static有哪些用法7.谈一下常见的访问修饰符有哪些&…...
FVM链的Themis Pro(0x,f4) 5日IDO超百万美元,或让Filecoin逆风翻盘
交易一直是DeFi乃至web3领域最经久不衰的话题,也因此催生了众多优秀的去中心化协议,如Uniswap和Curve。这些协议逐渐成为了整个系统的基石。 在永续合约方面,DYDX的出现将WEB2时代的订单簿带回了web3。其链下交易的设计,仿佛回到了…...
webserve简介
目录 I/O分类I/O模型阻塞blocking非阻塞 non-blocking(NIO)IO复用信号驱动异步 webServerHTTP简介概述工作原理HTTP请求头格式HTTP请求方法HTTP状态码 服务器编程基本框架两种高效的事件处理模式Reactor模式Proactor模拟 Proactor 模式 线程池 I/O分类 …...
分析型数据库:MPP 数据库的概念、技术架构与未来发展方向
随着企业数据量的增多,为了配合企业的业务分析、商业智能等应用场景,从而驱动数据化的商业决策,分析型数据库诞生了。由于数据分析一般涉及的数据量大,计算复杂,分析型数据库一般都是采用大规模并行计算或者分布式计算…...
微服务高级篇学习【4】之多级缓存
文章目录 前言一 多级缓存二 JVM进程缓存2.1 案例导入2.1.1 使用docker安装mysql2.1.2 修改配置2.1.3 导入项目工程2.1.4 导入商品查询页面2.1.5 反向代理 2.2 初识Caffeine2.3 实现JVM进程缓存 三 Lua脚本入门3.1 安装Lua3.2 Lua语法学习 四 实现多级缓存4.1 OpenResty简介4.2…...
知乎版ChatGPT「知海图AI」加入国产大模型乱斗,称效果与GPT-4持平
“2023知乎发现大会”上,知乎创始人、董事长兼CEO周源和知乎合作人、CTO李大海共同宣布了知乎与面壁智能联合发布“知海图AI”中文大模型。 周源据介绍,知乎与面壁智能达成深度合作,共同开发中文大模型产品并推进应用落地。目前,知…...
邮件发送配置
QQ邮箱发送和接收配置: POP3/SMTP协议 接收邮件服务器:pop.exmail.qq.com ,使用SSL,端口号995 发送邮件服务器:smtp.exmail.qq.com ,使用SSL,端口号465 海外用户可使用以下服务器 接收邮件服务器…...
【Open CASCADE -生成MFC和QT事例方式】
源代码目录 adm目录:包含编译OCCT的相关工程; adm/cmake目录:包含使用CMake构建OCCT的相关处理脚本; adm/msvc目录:包含window平台 Visual C 2010, 2012, 2013, 2015, 2017 and 2019等版本的32/64平台solutinon文件; data目录: 包…...
python 笔记:PyTrack(将GPS数据和OpenStreetMap数据进行整合)【官网例子解读】
论文笔记:PyTrack: A Map-Matching-Based Python Toolbox for Vehicle Trajectory Reconstruction_UQI-LIUWJ的博客-CSDN博客4 0 包的安装 官网的两种方式我都试过,装是能装成功,但是python import PyTrack包的时候还是显示找不到Pytrack …...
苦中作乐 ---竞赛刷题31-40(15-20)
(一)目录 L1-032 Left-pad L1-033 出生年 L1-034 点赞 L1-035 情人节 L1-039 古风排版 (二)题目 L1-032 Left-pad 根据新浪微博上的消息,有一位开发者不满NPM(Node Package Manager)的做法…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...
安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖
在Vuzix M400 AR智能眼镜的助力下,卢森堡罗伯特舒曼医院(the Robert Schuman Hospitals, HRS)凭借在无菌制剂生产流程中引入增强现实技术(AR)创新项目,荣获了2024年6月7日由卢森堡医院药剂师协会࿰…...
力扣热题100 k个一组反转链表题解
题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...
