whatsapp 语音通话 音频编码(五)

2024-04-17 04:28

本文主要是介绍whatsapp 语音通话 音频编码(五),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Whatsapp VoiceCall

客户端通过websocket连接到服务器,客户端发起语音通话请求,并且完成必要的协商之后,就可以直接将语音数据发送给服务器,服务器接收到对方的语音数据之后也会通过websocket将语音数据转发给客户端

获取协商秘钥

XMPP 在发起语音通话请求的时候,需要带上一个秘钥,这个秘钥长32字节,通过特殊算法生成。这个算法需要三个参数:

  1. 自身jid
  2. 对方jid
  3. 时间戳(服务端自动获取,不需要生成)
        //发送获取秘钥请求JSONObject result = new JSONObject();result.put("command", "GetSecret");result.put("selfjid", "自己的@whatsapp.com");result.put("otherjid", "对方@whatsapp.com");SendCommand(result);//接收到服务器返回的消息, secret 字段是经过base64 编码,需要解码,解码之后是32字节{"secret": "Xh+LtW/gRxC92B4UK/gLAzqERAqL9U2ArNetO3Zy0h0=","command": "ResponseSecret"}

发起XMPP 语音请求

  1. 发起语音请求。这个请求需要通过xmpp 通道发送出去,发出去之后,WA服务器会回一个ack包,这个ack包需要通过websocket发给中转服务器
 <call to='接收方@s.whatsapp.net' id='随机生成32字节'><offer call-creator='发送方.0:0@s.whatsapp.net' call-id='随机生成32字节' device_class='2015'><privacy>联系人的token,  同步联系人的时候 privacy_token节点下 trusted_contact 数据 </privacy><audio rate='16000' enc='opus'/><net medium='3'/><capability ver='1'>AQT3CcT6</capability><enc v='2' type='msg'>从服务器获取的32字节秘钥序列化成pb之后加密</enc><encopt keygen='2'/></offer></call>
 //下面是消息pb 结构的一部分,需要将返回的32字节秘钥 设置到 Call->callKey 中,序列化之后加密message Message {optional string conversation = 1;optional SenderKeyDistributionMessage senderKeyDistributionMessage = 2;optional ImageMessage imageMessage = 3;optional ContactMessage contactMessage = 4;optional LocationMessage locationMessage = 5;optional ExtendedTextMessage extendedTextMessage = 6;optional DocumentMessage documentMessage = 7;optional AudioMessage audioMessage = 8;optional VideoMessage videoMessage = 9;optional Call call = 10;... ...... ...}message Call {optional bytes callKey = 1;optional string conversionSource = 2;optional bytes conversionData = 3;optional uint32 conversionDelaySeconds = 4;}
  1. 处理ack 回包。
    发送完第一个包之后,服务器会返回一个ack包, 需要将这个ack包转成xml格式,然后通过websocket 发送给服务器
      //xmpp 转xml 需要注意, 节点部分的值需要base64 之后再发过来<ack from='对方@s.whatsapp.net' class='call' type='offer' id='xxxx'><relay attribute_padding='1' peer_pid='0' self_pid='1' uuid='xxx' call-creator='xxx@s.whatsapp.net' call-id='xxx' joinable='1'><participant pid='0' jid='xxx@s.whatsapp.net'/><token id='0'>base64的内容</token><token id='1'>xxx</token><token id='2'>xxx</token><token id='3'>xxx</token><token id='4'>xxxx</token><key>xxxx</key><te2 protocol='1' relay_id='0' token_id='0'>base64的内容</te2><te2 protocol='1' relay_id='0' token_id='0'>base64的内容</te2><te2 relay_id='0' token_id='0'>xxx</te2><te2 relay_id='0' token_id='0'>xxx</te2><te2 protocol='1' relay_id='1' token_id='1'>xxx</te2><te2 protocol='1' relay_id='1' token_id='1'>xx</te2><te2 relay_id='1' token_id='1'>xxx</te2><te2 relay_id='1' token_id='1'>xxx</te2><te2 protocol='1' relay_id='2' token_id='3'>xxx</te2><te2 protocol='1' relay_id='2' token_id='3'>xxx</te2><te2 relay_id='2' token_id='3'>xxx</te2><te2 relay_id='2' token_id='3'>xxx</te2><te2 protocol='1' relay_id='3' token_id='2'>xxx</te2><te2 protocol='1' relay_id='3' token_id='2'>xxx</te2><te2 relay_id='3' token_id='2'>xxx</te2><te2 relay_id='3' token_id='2'>xxx</te2><te2 protocol='1' relay_id='4' token_id='4'>xxx</te2><te2 protocol='1' relay_id='4' token_id='4'>xxx</te2><te2 relay_id='4' token_id='4'>xxx</te2><te2 relay_id='4' token_id='4'>xxx</te2><hbh_key>xxx</hbh_key></relay><user jid='xxx@s.whatsapp.net'><device jid='xxx@s.whatsapp.net'/></user><rte>xxx</rte><uploadfieldstat/><userrate/><voip_settings uncompressed='1'>xxxx</voip_settings></ack>
 //将服务器回的ack 包发给中转服务器JSONObject result = new JSONObject();result.put("command", "VoiceAck");// 用于测试的音频文件ID,固定,正式部署的时候需要换成上传的文件result.put("file_uuid", "aee4d52d-6ba7-4a65-80d4-b7341b1115f0");result.put("ack", "服务器回的ack包打包成xml格式");SendCommand(result);
  1. 接收到的服务器的包必须回复ack,否则会被踢下线,下面几个常用的ack
		//接收的包<receipt from='xxx@s.whatsapp.net' id='xxx' t='xxx'><offer call-id='xxx' call-creator='xxx@s.whatsapp.net'/></receipt>//需要回复ack<ack id='xxx' to='xxx@s.whatsapp.net' class='receipt'/>
  //接收的包<call from='xxx@s.whatsapp.net' id='xxx' t='xxx'><preaccept call-id='xxx' call-creator='xxx@s.whatsapp.net'><audio rate='16000' enc='opus'/><encopt keygen='2'/><capability ver='1'>xxx</capability></preaccept></call>//需要回复ack<ack id='xxx' to='xxx.0:0@s.whatsapp.net' class='call' type='preaccept'/>
 //接收的包<call from='xxx@s.whatsapp.net' id='xxx' t='xxx'><relaylatency call-id='xxx' call-creator='xxx@s.whatsapp.net'><te latency='xxx'>xxx</te></relaylatency></call>//需要回复ack<ack id='xxx' to='xxx.0:0@s.whatsapp.net' class='call' type='relaylatency'/>
  1. 中转服务器会将一些需要发给WA服务器的包发过来,这些包需要转成xmpp 格式的数据发给WA 服务器
 <call to="xxx@s.whatsapp.net" id="xxx"><relaylatency call-creator="xxx.0:0@s.whatsapp.net" call-id="xxx"><te latency="xxx">xxx</te></relaylatency></call>

总结一下步骤:

1. 和中转服务器建立websocket 连接

2. 从中转服务器获取 加密秘钥

3. XMPP 发送call 请求,并且接收服务器返回的ack, 特别需要注意期间会收到很多包,都需要回ack,上面也列出了一些需要回ack的包

4. 将WA 服务器的ack包转成xml 格式发给中转服务器, 特别需要注意xml格式节点值需要base64 编码

5. 中转服务器会主动发送一些xml数据, 客户端需要将这些xml数据转成xmpp包发给服务器。

在这里插入图片描述

这篇关于whatsapp 语音通话 音频编码(五)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/910775

相关文章

基于Go语言实现Base62编码的三种方式以及对比分析

《基于Go语言实现Base62编码的三种方式以及对比分析》Base62编码是一种在字符编码中使用62个字符的编码方式,在计算机科学中,,Go语言是一种静态类型、编译型语言,它由Google开发并开源,... 目录一、标准库现状与解决方案1. 标准库对比表2. 解决方案完整实现代码(含边界处理)二、关键实现细

Python中edge-tts实现便捷语音合成

《Python中edge-tts实现便捷语音合成》edge-tts是一个功能强大的Python库,支持多种语言和声音选项,本文主要介绍了Python中edge-tts实现便捷语音合成,具有一定的参考价... 目录安装与环境设置文本转语音查找音色更改语音参数生成音频与字幕总结edge-tts 是一个功能强大的

解决IDEA报错:编码GBK的不可映射字符问题

《解决IDEA报错:编码GBK的不可映射字符问题》:本文主要介绍解决IDEA报错:编码GBK的不可映射字符问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录IDEA报错:编码GBK的不可映射字符终端软件问题描述原因分析解决方案方法1:将命令改为方法2:右下jav

Python使用自带的base64库进行base64编码和解码

《Python使用自带的base64库进行base64编码和解码》在Python中,处理数据的编码和解码是数据传输和存储中非常普遍的需求,其中,Base64是一种常用的编码方案,本文我将详细介绍如何使... 目录引言使用python的base64库进行编码和解码编码函数解码函数Base64编码的应用场景注意

使用Python实现文本转语音(TTS)并播放音频

《使用Python实现文本转语音(TTS)并播放音频》在开发涉及语音交互或需要语音提示的应用时,文本转语音(TTS)技术是一个非常实用的工具,下面我们来看看如何使用gTTS和playsound库将文本... 目录什么是 gTTS 和 playsound安装依赖库实现步骤 1. 导入库2. 定义文本和语言 3

VSCode中C/C++编码乱码问题的两种解决方法

《VSCode中C/C++编码乱码问题的两种解决方法》在中国地区,Windows系统中的cmd和PowerShell默认编码是GBK,但VSCode默认使用UTF-8编码,这种编码不一致会导致在VSC... 目录问题方法一:通过 Code Runner 插件调整编码配置步骤方法二:在 PowerShell

详解如何使用Python提取视频文件中的音频

《详解如何使用Python提取视频文件中的音频》在多媒体处理中,有时我们需要从视频文件中提取音频,本文为大家整理了几种使用Python编程语言提取视频文件中的音频的方法,大家可以根据需要进行选择... 目录引言代码部分方法扩展引言在多媒体处理中,有时我们需要从视频文件中提取音频,以便进一步处理或分析。本文

讯飞webapi语音识别接口调用示例代码(python)

《讯飞webapi语音识别接口调用示例代码(python)》:本文主要介绍如何使用Python3调用讯飞WebAPI语音识别接口,重点解决了在处理语音识别结果时判断是否为最后一帧的问题,通过运行代... 目录前言一、环境二、引入库三、代码实例四、运行结果五、总结前言基于python3 讯飞webAPI语音

Python如何实现读取csv文件时忽略文件的编码格式

《Python如何实现读取csv文件时忽略文件的编码格式》我们再日常读取csv文件的时候经常会发现csv文件的格式有多种,所以这篇文章为大家介绍了Python如何实现读取csv文件时忽略文件的编码格式... 目录1、背景介绍2、库的安装3、核心代码4、完整代码1、背景介绍我们再日常读取csv文件的时候经常

Python实现视频转换为音频的方法详解

《Python实现视频转换为音频的方法详解》这篇文章主要为大家详细Python如何将视频转换为音频并将音频文件保存到特定文件夹下,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. python需求的任务2. Python代码的实现3. 代码修改的位置4. 运行结果5. 注意事项