默认
发表评论 20
想开发IM:买成品怕坑?租第3方怕贵?找开源自已撸?尽量别走弯路了... 找站长给点建议
[已回复] 求助为 MobileIMSDK 添加语音或视频数据支持
阅读(68461) | 评论(20 收藏2 淘帖 1
目前想在MobileIMSDK Server里面添加对音频数据(byte[]) 的支持,初步的想法是
/*
 * Copyright (C) 2016 即时通讯网(52im.net) The MobileIMSDK Project. 
 * All rights reserved.
 * Project URL:[url=https://github.com/JackJiang2011/MobileIMSDK]https://github.com/JackJiang2011/MobileIMSDK[/url]
 *  
 * 即时通讯网(52im.net) - 即时通讯技术社区! PROPRIETARY/CONFIDENTIAL.
 * Use is subject to license terms.
 * 
 * Protocal.java at 2016-2-20 11:26:03, code by Jack Jiang.
 * You can contact author with [url=mailto:jack.jiang@52im.net]jack.jiang@52im.net[/url] or [url=mailto:jb2011@163.com]jb2011@163.com[/url].
 */
package net.openmob.mobileimsdk.server.protocal;

import java.util.UUID;

import com.google.gson.Gson;

public class Protocal {
        private int type = 0;
        private String dataContent = null;
        private byte[] audioData;
        private int from = -1;
        private int to = -1;
        private String fp = null;
        private boolean QoS = false;
        private transient int retryCount = 0;

        public Protocal(int type, byte[] audioData, int from, int to) {
                this(type, audioData, from, to, false, null);
        }

        public Protocal(int type, String dataContent, int from, int to) {
                this(type, dataContent, from, to, false, null);
        }

        public Protocal(int type, String dataContent, int from, int to, boolean QoS, String fingerPrint) {
                this.type = type;
                this.dataContent = dataContent;
                this.from = from;
                this.to = to;
                this.QoS = QoS;

                // 只有在需要QoS支持时才生成指纹,否则浪费数据传输流量
                // 目前一个包的指纹只在对象建立时创建哦
                if ((QoS) && (fingerPrint == null))
                        this.fp = genFingerPrint();
                else
                        this.fp = fingerPrint;
        }

        public Protocal(int type, byte[] audioData, int from, int to, boolean QoS, String fingerPrint) {
                this.type = type;
                this.audioData = audioData;
                this.from = from;
                this.to = to;
                this.QoS = QoS;

                // 只有在需要QoS支持时才生成指纹,否则浪费数据传输流量
                // 目前一个包的指纹只在对象建立时创建哦
                if ((QoS) && (fingerPrint == null))
                        this.fp = genFingerPrint();
                else
                        this.fp = fingerPrint;
        }

        public int getType() {
                return this.type;
        }

        public void setType(int type) {
                this.type = type;
        }

        public String getDataContent() {
                return this.dataContent;
        }

        public void setDataContent(String dataContent) {
                this.dataContent = dataContent;
        }

        public byte[] getAudioData() {
                return audioData;
        }

        public void setAudioData(byte[] audioData) {
                this.audioData = audioData;
        }

        public int getFrom() {
                return this.from;
        }

        public void setFrom(int from) {
                this.from = from;
        }

        public int getTo() {
                return this.to;
        }

        public void setTo(int to) {
                this.to = to;
        }

        public String getFp() {
                return this.fp;
        }

        public int getRetryCount() {
                return this.retryCount;
        }

        public void increaseRetryCount() {
                this.retryCount += 1;
        }

        public boolean isQoS() {
                return this.QoS;
        }

        public String toGsonString() {
                return new Gson().toJson(this);
        }

        public byte[] toBytes() {
                return CharsetHelper.getBytes(toGsonString());
        }

        public Object clone() {
                // 克隆一个Protocal对象(该对象已重置retryCount数值为0)
                Protocal cloneP = new Protocal(getType(), getDataContent(), getFrom(), getTo(), isQoS(), getFp());
                return cloneP;
        }

        public static String genFingerPrint() {
                return UUID.randomUUID().toString();
        }
}

增加byte[] 属性,然后修改ProtocalFactory 以及ProtocalType int FROM_CLIENT_TYPE_OF_AUDIO = 6;
并在ServerCoreHandler messageReceived 添加对FROM_CLIENT_TYPE_OF_AUDIO  的支持,不知道这个思路是否可行,MobileIMSDK 能否支持这种数据的发送,可能是语音,视频,文件等。

即时通讯网 - 即时通讯开发者社区! 来源: - 即时通讯开发者社区!

上一篇:[已回复] 多人登陆时,所有人都会共用第一个人登录的账号,有没有什么解决方法下一篇:[已解决] 求教 MobileIMSDK 服务器端向指定客户端推送方法
推荐方案
评论 20
移动端IM里,语音留言这些东西都是通过http协议进行中转收发,你的思路就错了吧。
详见这个帖子里的讨论:《请问有人知道语音留言聊天的主流实现方式吗?
引用:JackJiang 发表于 2017-06-10 11:08
移动端IM里,语音留言这些东西都是通过http协议进行中转收发,你的思路就错了吧。
详见这个帖子里的讨论: ...

谢谢回复,我不是要做语音留言,是需要做一个实时的数据传输中间件,用做简单的一个语音电话,我们这边的优势在于音视频的编解码,目前您的源码是指定了格式为String,正在尝试修改成通用的byte[] ,这样既可以传普通文本消息,也可以传送实时音视频数据,亦或是文件等。
签名: 该会员没有填写今日想说内容.
引用:LeoLee 发表于 2017-06-10 14:29
谢谢回复,我不是要做语音留言,是需要做一个实时的数据传输中间件,用做简单的一个语音电话,我们这边的 ...

低层的方法其实就是以byte数组的形式传输的,你可以从底层改造一下,别转成string再回转为byte,这样转就会让效率变低,没有必要。你可以考虑在底层传输的时候为byte数组加一个头标识位,比如当是0的时候就是现在原有的指令内容,当为1时就是你新增的定制byte数组传输内容,这样就合理高效多了,而且这样改也不影响你增加指令之前的算法逻辑,你只需要在发送和接收这连的代码最底层来封装就可以。
我感觉实时传输都走的是流了,不是data,而且服务端只是打开两个客户端的连接通道,以后的流传输都不走服务端转发了。难点是怎么两个客户端直接连接,看他们说要什么net穿墙,我也不懂
引用:狂奔的蜗牛 发表于 2017-06-12 17:07
我感觉实时传输都走的是流了,不是data,而且服务端只是打开两个客户端的连接通道,以后的流传输都不走服务 ...

实用的实时音视频系统都是优先考虑p2p,在p2p不通的情况下才考虑服务器转发。P2P的技术资料你可以看看这个系列文章:http://www.52im.net/thread-50-1-1.html
引用:JackJiang 发表于 2017-06-10 16:02
低层的方法其实就是以byte数组的形式传输的,你可以从底层改造一下,别转成string再回转为byte,这样转就 ...

感觉还是很难改,目前源码里面相当于还是传的string,用的Gson来转换,我是想修改成二进制数据,换其它的protobuf等感觉改动又太大了,有简单一点的办法么
签名: 该会员没有填写今日想说内容.
引用:JackJiang 发表于 2017-06-12 17:22
实用的实时音视频系统都是优先考虑p2p,在p2p不通的情况下才考虑服务器转发。P2P的技术资料你可以看看这 ...

一个集群的对讲,只能用服务器来转发,服务器会把语音数据发送给所有的人,我想做的就是这样一个服务器,修改成传输二进制碰到困难了
签名: 该会员没有填写今日想说内容.
引用:LeoLee 发表于 2017-06-12 17:53
感觉还是很难改,目前源码里面相当于还是传的string,用的Gson来转换,我是想修改成二进制数据,换其它的 ...

你还是没有仔细看源码,最底层就是byte数组啊,卡住最底层的方法扩展一下
引用:JackJiang 发表于 2017-06-12 17:55
你还是没有仔细看源码,最底层就是byte数组啊,卡住最底层的方法扩展一下

能否详细说一下,我只看到ProtocalFactory部分是用Gson来相互转换的,难道还有更底层的部分?
签名: 该会员没有填写今日想说内容.
引用:LeoLee 发表于 2017-06-12 17:56
能否详细说一下,我只看到ProtocalFactory部分是用Gson来相互转换的,难道还有更底层的部分?

去看看发送数据的代码:LocalUDPDataSender
引用:JackJiang 发表于 2017-06-12 18:02
去看看发送数据的代码:LocalUDPDataSender

这个部分有看到过,底层发送最终是Protocal.toBytes方法,接收部分是CharsetHelper.getString后的json字符串转换 new Gson().fromJson(xxx) ,音频数据是不可打印字符,在转换的过程中Gson就抛异常了
签名: 该会员没有填写今日想说内容.
引用:LeoLee 发表于 2017-06-12 18:18
这个部分有看到过,底层发送最终是Protocal.toBytes方法,接收部分是CharsetHelper.getString后的json字 ...

最终的解决办法是通过java的序列化和反序列化来做的,谢谢作者回复。
签名: 该会员没有填写今日想说内容.
引用:LeoLee 发表于 2017-06-12 18:45
最终的解决办法是通过java的序列化和反序列化来做的,谢谢作者回复。

我现在也是想用序列化来实现,但是在服务端接受数据解析这块出现了问题,不知道能不能交流下
引用:turays 发表于 2017-07-08 12:38
我现在也是想用序列化来实现,但是在服务端接受数据解析这块出现了问题,不知道能不能交流下

从数据收发的根方法进行修改。我会考虑在以后的MobileIMSDK版本里直接开放出收发byte数组的方法。
引用:turays 发表于 2017-07-08 12:38
我现在也是想用序列化来实现,但是在服务端接受数据解析这块出现了问题,不知道能不能交流下

从数据收发的根方法进行修改。我会考虑在以后的MobileIMSDK版本里直接开放出收发byte数组的方法。
引用:LeoLee 发表于 2017-06-12 18:45
最终的解决办法是通过java的序列化和反序列化来做的,谢谢作者回复。

您好,我也想实现byte[]数据的传输,请问是怎么样通过序列化实现的,您能详细说明一下吗?
     请您指教,非常感谢!
引用:LeoLee 发表于 2017-06-12 18:45
最终的解决办法是通过java的序列化和反序列化来做的,谢谢作者回复。

    您是不是先将消息封装为Protocal对象(根据您上面贴出的代码对Protocal类的修改),再直接通过Java对象序列化将Protocal对象序列化为byte[]。  而跳过源码中将Protocal对象转换为json格式字符串,再转换为byte[]。
   谢谢您!
   
引用:JackJiang 发表于 2017-07-08 16:20
从数据收发的根方法进行修改。我会考虑在以后的MobileIMSDK版本里直接开放出收发byte数组的方法。

jack,您好。              我想实现语音对讲,于是我测试了将发送的String类文本消息转换为bytep[]类型后,再将Protocal对象进行序列化为byte[],这样文本消息是完全可以正常收发的,相当于实现了byte[]消息的传输。(因为语音数据是byte[]类型的)
     但我进行下面操作时,出现了一些问题,如下讲述。
     客户端:
           通过将获取的语音数据buffer(类型为byte[],大小为640bit。是通过录音对象获取的,录音区的大小为640bit , 进而从录音对象中获取录音数据放在该byte[]中),再将byte[]封装到Protocal对象中。
          接着通过Java序列化,将Protocal对象序列化为byte[]类型数据执行发送,该byte[]大小为870bit。
          语音是一直在循环获取,所以使得每个数据报发送的时间间隔为0.04s(偶尔出现有0.02s,0.03s,0.06s三种发送的时间间隔)
     客户端每次发送可以成功。

     服务端:
          接收到该数据时,每个包也可以成功接收,并且将接收到的从message中获取byte[](为870bit),再反序列化为Protocal对象,接着从Protocal对象中获取语音数据byte[](为640bit),
          下一步将该语音数据封装到Protocal对象中,让后再将该Protocal对象反序列化为byte[],最后使用
WriteFuture future = session.write(buf); 进行发送时发送不成功。(网上说mina框架UDP不能发送超过256,超过就分批发送)
          不知道我这种实现语音对讲的思路可不可行,恳请您给我一些指导,谢谢您!!!


引用:632743365 发表于 2017-10-12 22:52
jack,您好。              我想实现语音对讲,于是我测试了将发送的String类文本消息转换为bytep[]类型后 ...

你参考一下我在这个帖子里的因复:
[已回复] MobileIMSDK发送消息的最大字节数是多少?超了会出现什么情况?
打赏楼主 ×
使用微信打赏! 使用支付宝打赏!

返回顶部