腾讯云视频接入初探

今日来公司的项目要求接入视频,如是根据需求对网易云视频,anychat,腾讯云视频进行了技术调研,因为基于响应时间,降噪等诸多效果的测试,考虑,最终选择了腾讯云视频。因为腾讯云视频刚刚推出不久,demo,文档写的不是太集中,故在集成时出现多个坑。现对集成步骤做一下简单归纳:

1.集成播放列表:

直播播放列表需要开通查询统计信息(Beta)

该接口的相关文档地址:https://www.qcloud.com/document/product/267/6110。
这个接口需要提交工单才会开通,默认是不开通的。
开通后会产生appid和推流鉴权key (这个东西会在生成sign时使用,sign生成的规则是推流鉴权key直接拼接过期时间)

 String playUrl ="http://statcgi.video.qcloud.com/common_access?"+
            "cmd=1251175924&interface=Get_LiveStat"+
                    "&Param.n.page_no=1"+"&Param.n.page_size=20"+
                    "&t="+time+"&sign="+signValue;

cmd后面需要根据你自己的需要更换成自己的appid,我的核心代码如下:
sign是推流鉴权key直接拼接过期时间进行md5生成:

md5工具类:

public class MD5Utils {
      static String MD5(String sourceStr) {
            String result = "";
            try {
                MessageDigest md = MessageDigest.getInstance("MD5");
                md.update(sourceStr.getBytes());
                byte b[] = md.digest();
                int i;
                StringBuffer buf = new StringBuffer("");
                for (int offset = 0; offset < b.length; offset++) {
                    i = b[offset];
                    if (i < 0)
                        i += 256;
                    if (i < 16)
                        buf.append("0");
                    buf.append(Integer.toHexString(i));
                }
                result = buf.toString();
                System.out.println("MD5(" + sourceStr + ",32) = " + result);
                System.out.println("MD5(" + sourceStr + ",16) = " + buf.toString().substring(8, 24));
            } catch (NoSuchAlgorithmException e) {
                System.out.println(e);
            }
            return result;
        }

}

过期时间戳转化工具类:

public class TimeUtils {
//日期转化为时间戳
     public static String dateToStamp(String s) throws Exception{
            String res;
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date date = simpleDateFormat.parse(s);
            long ts = (date.getTime()+300000)/1000;
            res = String.valueOf(ts);
            return res;
        }
     public static String stampToDate(String s){
            String res;
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            long lt = new Long(s);
            Date date = new Date(lt);
            res = simpleDateFormat.format(date);
            return res;
        }
}

查询时间列表的核心逻辑:

    public static void main(String[] args) throws Exception {
        OkHttpClient client = new OkHttpClient();
       SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
          String time="";
        try {
            //获取当前日期的时间戳
            time = TimeUtils.dateToStamp(sdf.format(new Date()));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
           System.out.println(time);
             //推流鉴权key
            String key="7407d5829e270dd92661ffcf06169bcf";
            String signValue=MD5Utils.MD5(key+time);
            String playUrl ="http://statcgi.video.qcloud.com/common_access?"+
            "cmd=1251175924&interface=Get_LiveStat"+
                    "&Param.n.page_no=1"+"&Param.n.page_size=20"+
                    "&t="+time+"&sign="+signValue;
            System.out.println(playUrl);
        Request request = new Request.Builder().url(playUrl).build();
        Response response = client.newCall(request).execute();
        
        if (response.isSuccessful()) {
            System.out.println(response.body().string());
            
        } else {
            throw new IOException("Unexpected code " + response);
        }

获取成功会如下显示:

{"errmsg":"has no stream is living","message":"has no stream is living","output":null,"ret":0,"retcode":0}

如果有推流的话是:

{"errmsg":"","message":"","output":{"stream_count":1,"stream_info":[{"bandwidth":0.0,"client_ip":"125.46.216.125","flr":1.0,"fps":0,"online":0,"server_ip":"123.138.162.79","speed":0,"stream_name":"8818_b262bb2709","time":"2017-04-13 11:04:13"}],"total_bandwidth":0.0,"total_online":0},"ret":0,"retcode":0}

返回的是json这个由你自己的业务需求定

2.登录用户体系:

腾讯提供了两种账户体系,一种是托管的,一种是独立的,托管的是需要注册登录腾讯tls体系,账户管理交由腾讯,独立的就是不对现有用户体系有影响,而是在需要调用腾讯的时候,去到腾讯上验证一下,就像融云的token一样。

2.1托管体系注册

android:


accountHelper.TLSStrAccReg("xtfgq", "12345678", new TLSStrAccRegListener() {
            @Override
            public void OnStrAccRegSuccess(TLSUserInfo tlsUserInfo) {
//                tlsUserInfo.

                Log.e("vv","111");
            }

            @Override
            public void OnStrAccRegFail(TLSErrInfo tlsErrInfo) {
                Log.e("vv","222");
            }

            @Override
            public void OnStrAccRegTimeout(TLSErrInfo tlsErrInfo) {
                Log.e("vv","333");
            }
        });

需要在oncreate中完成初始化,这里面的appid与前面的不同,(特别注意),这个是开通腾讯云云通信里面的那个千万不要搞错。

 accountHelper=TLSAccountHelper.getInstance().init(SettingActivity.this,1251175924,12001,"1.0.1");

托管登录:

  loginHelper = TLSLoginHelper.getInstance()
                .init(getApplicationContext(), 11270, 12001, "1.0.1");
        loginHelper.TLSPwdLogin("用户帐号", "用户密码".getBytes(), new TLSPwdLoginListener(){
            @Override
            public void OnPwdLoginSuccess(TLSUserInfo tlsUserInfo) {
  final TIMUser user = new TIMUser();
                user.setIdentifier("用户帐号");
                user.setAccountType("12001");
                user.setAppIdAt3rd(String.valueOf(Constants.sdkAppId));
                TIMManager.getInstance().login(
                        Constants.sdkAppId,                   //sdkAppId,由腾讯分配
                        user,
                        loginHelper.getUserSig("用户帐号"),                    //用户帐号签名,由私钥加密获得,具体请参考文档
                        new TIMCallBack() {//回调接口

                            @Override
                            public void onSuccess() {//登录成功
                                Log.e("vvv","succuss");
                            //根据逻辑跳到不同界面
                            }

                            @Override
                            public void onError(int code, String desc) {//登录失败

                                //错误码code和错误描述desc,可用于定位请求失败原因
                                //错误码code含义请参见错误码表
                                Log.e("eer","eeror");

                            }
                        });

            }

            @Override
            public void OnPwdLoginReaskImgcodeSuccess(byte[] bytes) {

            }

            @Override
            public void OnPwdLoginNeedImgcode(byte[] bytes, TLSErrInfo tlsErrInfo) {

            }

            @Override
            public void OnPwdLoginFail(TLSErrInfo tlsErrInfo) {

            }

            @Override
            public void OnPwdLoginTimeout(TLSErrInfo tlsErrInfo) {

            }
        });

2.2 独立模式,即usersinger需从自己的服务器获得,可参考usersinger生成文档:https://www.qcloud.com/document/product/269/1510。

客户端不需要像刚才那样先登陆tls,然后在成功回调里调用 TIMManager.getInstance().login,而是直接从自己的服务取得usersinger,
代码如下:

 final TIMUser user = new TIMUser();
                        user.setIdentifier(userid);
                        user.setAccountType("12001");
                        user.setAppIdAt3rd(String.valueOf(Constants.sdkAppId));
                        TIMManager.getInstance().login(
                                Constants.sdkAppId,                   //sdkAppId,由腾讯分配
                                user,
                               sig,                    //用户帐号签名,由私钥加密获得,具体请参考文档
                                new TIMCallBack() {//回调接口

                                    @Override
                                    public void onSuccess() {//登录成功
                                        Log.e("vvv","succuss");
                                    
                                    

                                    }

                                    @Override
                                    public void onError(int code, String desc) {//登录失败

                                        //错误码code和错误描述desc,可用于定位请求失败原因
                                        //错误码code含义请参见错误码表
                                        Log.e("eer","eeror");

                                    }
                                });

最后,不管哪中模式,都需要调用修改昵称的腾讯接口,否则会出现发弹幕上用户名变成数字方面的问题。

 public void setMyNickName(String nickName){
        TIMFriendshipManager.getInstance().setNickName(nickName, new TIMCallBack() {
            @Override
            public void onError(int i, String s) {

            }

            @Override
            public void onSuccess() {

            }
        });
    }

3.加入聊天室:

 private void joinIMChatRoom(final String chatRoomId) {

        mGroupConversation = TIMManager.getInstance().getConversation(TIMConversationType.Group, chatRoomId);

        TIMGroupManager.getInstance().applyJoinGroup(chatRoomId, Constants.APPLY_CHATROOM + chatRoomId, new TIMCallBack() {
            @Override
            public void onError(int i, String s) {
                //已经在是成员了
                if (i == Constants.IS_ALREADY_MEMBER) {

                    initTIMListener(chatRoomId);

                }
            }

            @Override
            public void onSuccess() {

                initTIMListener(chatRoomId);
            }
        });

    }

消息监听:

  public void initTIMListener(String chatRoomId) {
        mGroupConversation = TIMManager.getInstance().getConversation(TIMConversationType.Group, chatRoomId);
        TIMManager.getInstance().addMessageListener(msgListener);

    }
 /**
     * 群消息回调
     */
    private TIMMessageListener msgListener = new TIMMessageListener() {
        @Override
        public boolean onNewMessages(List list) {
            //SxbLog.d(TAG, "onNewMessages readMessage " + list.size());
            //解析TIM推送消息
            parseIMMessage(list);
            return false;
        }
    };
 /**
     * 解析消息回调
     *
     * @param list 消息列表
     */
    private void parseIMMessage(List list) {
        List tlist = list;

        if (tlist.size() > 0) {
            if (mGroupConversation != null)
                mGroupConversation.setReadMessage(tlist.get(0));
        }


        for (int i = tlist.size() - 1; i >= 0; i--) {
            TIMMessage currMsg = tlist.get(i);
            for (int j = 0; j < currMsg.getElementCount(); j++) {
                if (currMsg.getElement(j) == null)
                    continue;
                TIMElem elem = currMsg.getElement(j);
                TIMElemType type = elem.getType();

                //系统消息
                if (type == TIMElemType.GroupSystem) {
                    if (TIMGroupSystemElemType.TIM_GROUP_SYSTEM_DELETE_GROUP_TYPE == ((TIMGroupSystemElem) elem).getSubtype()) {

                    }


                }

                //最后处理文本消息
                if (type == TIMElemType.Text) {
                    if (currMsg.isSelf()) {
                        handleTextMessage(elem, name);
                    } else {
                        TIMUserProfile sendUser = currMsg.getSenderProfile();
                       String nick="";
                        if(sendUser!=null){
                            nick=sendUser.getNickName();
                        }else{
                            nick=currMsg.getSender();
                        }
                        handleTextMessage(elem,nick);
                    }
                }
            }
        }
    }

发送消息:

 mGroupConversation = TIMManager.getInstance().getConversation(TIMConversationType.Group, groupId);

        mGroupConversation.sendMessage(msg, new TIMValueCallBack() {//发送消息回调
            @Override
            public void onError(int code, String desc) {//发送消息失败
                //错误码code和错误描述desc,可用于定位请求失败原因
                //错误码code含义请参见错误码表
                if (code == 85) { //消息体太长
                    if (null != getActivity()) {
                        Toast.makeText(getActivity(), "输入内容太长", Toast.LENGTH_SHORT).show();
                    }
                } else if (code == 6011) {//群主不存在
                    if (null != getActivity()) {
                        Toast.makeText(getActivity(), "群主不存在", Toast.LENGTH_SHORT).show();
                    }
                }

            }

            @Override
            public void onSuccess(TIMMessage timMessage) {//发送消息成功
                mBoolRefreshLock=false;
                for (int j = 0; j < timMessage.getElementCount(); j++) {
                    TIMElem elem = (TIMElem) timMessage.getElement(0);
                    if (timMessage.isSelf()) {
                        handleTextMessage(elem, name);
                    } else {
                        TIMUserProfile sendUser = timMessage.getSenderProfile();
                        String name;
                        if (sendUser != null) {
                            name = sendUser.getNickName();
                        }
                        else {
                            name = timMessage.getSender();
                        }
                        //String sendId = timMessage.getSender();

                        handleTextMessage(elem,name);
                    }
                }
            }
        });
    }

处理消息文本:

  /**
     * 处理文本消息解析
     *
     * @param elem
     * @param name
     */
    private void handleTextMessage(TIMElem elem, String name) {
        TIMTextElem textElem = (TIMTextElem) elem;
        if (textElem.getText() != null) {
            refreshTextListView(name, textElem.getText(), Constants.TEXT_TYPE);
        }

    }
 /**
     * 消息刷新显示
     *
     * @param name    发送者
     * @param context 内容
     * @param type    类型 (上线线消息和 聊天消息)
     */
    public void refreshTextListView(String name, String context, int type) {
        ChatEntity entity = new ChatEntity();
        entity.setSenderName(name);
        entity.setContext(context);
        entity.setType(type);
        notifyRefreshListView(entity);
        mListViewMsgItems.setVisibility(View.VISIBLE);
        if (mListViewMsgItems.getCount() > 1) {
            if (true)
                mListViewMsgItems.setSelection(0);
            else
                mListViewMsgItems.setSelection(mListViewMsgItems.getCount() - 1);
        }
    }

最后实现效果如图:


腾讯云视频接入初探_第1张图片
2.png

你可能感兴趣的:(腾讯云视频接入初探)