1. 程式人生 > 實用技巧 >騰訊雲直播-開啟互動直播

騰訊雲直播-開啟互動直播

專案背景:基於騰訊雲直播開發專案,直播交友平臺1+6模式

ps : 記錄自己的日常

一、申請騰訊視訊許可權(官方連結)

首先在流管理新增一個域名 型別為播放域名域名地址為 推流域名的域名字首+你的域名生成的而已域名或者三級域名

然後點選你儲存的播放域名檢視詳情

然後去自己的購買的網站域名中心進行解析域名解析的域名為你儲存的域名地址

型別為CNAME,填寫的是在騰訊播放域名的詳情裡的CNAME

為了資訊資料安全我在流管理的播放流加入了HTTS的證書

二、在雲直播的直播sdk列表中找到License,申請測試license新增ios/安卓的包名和隨機的appname

然後拿著key 、lincenseURL交給ios和安卓開發人員

三、開通即時通訊IM 拿著 appskID 和祕鑰 處理業務(註冊)

package com.skyonez.core.util; import java.io.IOException; import org.apache.http.Consts;import org.apache.http.HttpResponse;import org.apache.http.client.ClientProtocolException;import org.apache.http.client.HttpClient;import org.apache.http.client.methods.HttpPost;import org.apache.http.entity.StringEntity;import org.apache.http.impl.client.HttpClientBuilder;import org.apache.http.util.EntityUtils; import com.skyonez.core.constant.Parameter;import com.skyonez.core.entity.User;import com.tencentyun.TLSSigAPIv2; import net.sf.json.JSONArray;import net.sf.json.JSONObject; public class TencentIMUtils {     public static final long SDK_APP_ID =  你的sdkappid;  public static final String KEY = "你的祕鑰";    /**  * 賬號註冊  *   * @param user 使用者物件  * @return 響應    */ public static JSONObject create(User user) {        // 請求地址     String url = "https://console.tim.qq.com/v4/im_open_login_svc/account_import";      // 封裝請求引數       JSONObject param = new JSONObject();        param.put("Identifier", String.valueOf(user.getId()));      param.put("Nick", user.getUsername());      param.put("FaceUrl", Parameter.OSS_BUCKET + "/" + user.getHeadPortrait());      param.put("Type", 0);       return post(url, param);    }   /**  * 新增好友  *   * @param user   * @return   */ public static JSONObject addFriend(Integer id, Integer toId) {      // 請求地址     String url = "https://console.tim.qq.com/v4/sns/friend_add";        // 封裝請求引數       JSONObject param = new JSONObject();        param.put("From_Account", String.valueOf(id));      JSONArray array = new JSONArray();      JSONObject friend = new JSONObject();       friend.put("To_Account", String.valueOf(toId));     friend.put("AddSource", "AddSource_Type_Android");      array.add(friend);      param.put("AddFriendItem", array);      param.put("AddType", "Add_Type_Single");        param.put("ForceAddFlags", 1);      return post(url, param);    }   /**  * 刪除好友  *   * @param user   * @return   */ public static JSONObject deleteFriend(Integer id, Integer toId) {       // 請求地址     String url = "https://console.tim.qq.com/v4/sns/friend_delete";     // 封裝請求引數       JSONObject param = new JSONObject();        param.put("From_Account", String.valueOf(id));      JSONArray array = new JSONArray();      array.add(String.valueOf(toId));        param.put("To_Account", array);     param.put("DeleteType", "Delete_Type_Both");        return post(url, param);    }   /**  * 通過使用者id獲取sig   *   * @param id 使用者id    * @return sig   */ public static String genSig(Integer id) {       TLSSigAPIv2 api = new TLSSigAPIv2(SDK_APP_ID, KEY);     return api.genSig(String.valueOf(id), 180 * 86400).replaceAll("(\\r\\n|\\n|\\n\\r)", "");   }   /**  * 通用請求  *   * @param url   請求地址     * @param param 引數   * @return 響應    */ private static JSONObject post(String url, JSONObject param) {      // 驗證獲取簽名       TLSSigAPIv2 api = new TLSSigAPIv2(SDK_APP_ID, KEY);     // 獲取簽名     String usersig = api.genSig("admin", 1800).replaceAll("(\\r\\n|\\n|\\n\\r)", "");       // 獲取DefaultHttpClient請求        HttpClient client = HttpClientBuilder.create().build();     HttpPost httpPost = new HttpPost(url + "?sdkappid=" + SDK_APP_ID + "&identifier=admin&usersig=" + usersig               + "&random=" + StringUtils.randomUUID() + "&contenttype=json");     // 設定請求的header      httpPost.addHeader("Content-Type", "application/json;charset=utf-8");       // 設定請求的引數      StringEntity params = (new StringEntity(param.toString(), Consts.UTF_8));       // 將引數傳入httpBody中       httpPost.setEntity(params);     // 執行請求     HttpResponse response;      try {           response = client.execute(httpPost);            return JSONObject.fromObject(EntityUtils.toString(response.getEntity(), "utf-8"));      } catch (ClientProtocolException e) {           e.printStackTrace();        } catch (IOException e) {           e.printStackTrace();        }       return null;    }   /**  * 拉黑好友  *   * @param user   * @return   */ public static JSONObject addBlack(Integer id, Integer toId) {       // 請求地址     String url = "https://console.tim.qq.com/v4/sns/black_list_add";        // 封裝請求引數       JSONObject param = new JSONObject();        param.put("From_Account", String.valueOf(id));      JSONArray array = new JSONArray();      array.add( String.valueOf(toId) );      param.put("To_Account", array);             return post(url, param);    }   /**  * 取消拉黑好友    *   * @param user   * @return   */ public static JSONObject deleteBlack(Integer id, Integer toId) {        // 請求地址     String url = "https://console.tim.qq.com/v4/sns/black_list_delete";     // 封裝請求引數       JSONObject param = new JSONObject();        param.put("From_Account", String.valueOf(id));      JSONArray array = new JSONArray();      array.add( String.valueOf(toId) );      param.put("To_Account", array);     return post(url, param);    } }

四、生成推拉流地址

package com.skyonez.core.util; import org.slf4j.Logger;import org.slf4j.LoggerFactory; import java.io.UnsupportedEncodingException;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException; /** * 騰訊推流、拉流工具 *  * @author [email protected] */public class TecentCloudUtils {      // 這就是個日誌,不需要的刪掉就行了    private static final Logger logger = LoggerFactory.getLogger(TecentCloudUtils.class);     // 用於 生成推流防盜鏈的key    public static final String key = "推拉流放到key" ;      public static final String bizid = "你的推流地址上字首*****.livepush.myqcloud.com 的*****";     public static final String APPID = "點選你的頭像檢視你的資訊裡的APPid";     // 用於主動查詢和被動通知的key:API鑑定key    public static final String API_KEY = "api鑑權key";     // API回撥地址    public static final String API_ADDRESS = "http://fcgi.video.qcloud.com/common_access";     /**     * 推流地址     */    public static final String PUSH_URL = "rtmp://" + bizid + ".livepush.myqcloud.com/live/";     /**     * PC拉流地址     *///    public static final String PULL_RTMP_URL = "rtmp://" + bizid + ".名/live/"+ bizid + "_";    public static final String PULL_RTMP_URL = "rtmp://" + bizid + ".域名/live/";//    public static final String PULL_RTMP_URL = "rtmp://" + bizid + ".域名/live/";    /**     * app拉流地址     */    //  https://59744.liveplay.myqcloud.com/live/1003634281.flv    public static final String PULL_URL = "https://"+ bizid +".play.unclexin.com/live/";//    public static final String PULL_URL = "https://"+ bizid +".liveplay.myqcloud.com/live/";       /**     * 這是推流防盜鏈的生成 KEY+ streamId + txTime     *      * @param key     *            防盜鏈使用的key     * @param streamId     *            通常為直播碼.示例:bizid+房間id     * @param txTime     *            到期時間     * @return     * @author [email protected]     */    public static String getSafeUrl(String key, String streamId, long txTime) {        String input = new StringBuilder().                append(key).                append(streamId).                append(Long.toHexString(txTime).toUpperCase()).toString();         String txSecret = null;        try {            MessageDigest messageDigest = MessageDigest.getInstance("MD5");            txSecret  = byteArrayToHexString(                    messageDigest.digest(input.getBytes("UTF-8")));        } catch (NoSuchAlgorithmException e) {            e.printStackTrace();        } catch (UnsupportedEncodingException e) {            e.printStackTrace();        }         return txSecret == null ? "" :                new StringBuilder().                        append("txSecret=").                        append(txSecret).                        append("&").                        append("txTime=").                        append(Long.toHexString(txTime).toUpperCase()).                        toString();    }    private static final char[] DIGITS_LOWER =            {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};      private static String byteArrayToHexString(byte[] data) {        char[] out = new char[data.length << 1];         for (int i = 0, j = 0; i < data.length; i++) {            out[j++] = DIGITS_LOWER[(0xF0 & data[i]) >>> 4];            out[j++] = DIGITS_LOWER[0x0F & data[i]];        }        return new String(out);    }     /**     * 推流地址生成     */    public static String getPushUrl(String roomId,Long txTime) {         String safeUrl = getSafeUrl(key, roomId, txTime);         String realPushUrl = PUSH_URL + roomId + "?"+ safeUrl;         return realPushUrl;    }     /**     * APP拉流地址獲得     */    public static String getPullUrl(String owenrId,Long txTime) {        String safeUrl = getSafeUrl(key, owenrId, txTime);//        String appPullUrl = PULL_URL + owenrId + ".flv"+ "?"+ safeUrl;        String appPullUrl = PULL_URL + owenrId + ".flv"+ "?"+ safeUrl+"&bizid"+bizid ;//        String appPullUrl = PULL_URL + owenrId + ".flv";        return appPullUrl;    }     /**     * PC拉流地址獲得     */    public static String getPullRtmpUrl(String owenrId,Long txTime) {        String safeUrl = getSafeUrl(key, owenrId, txTime);//        String pullRtmpUrl = PULL_RTMP_URL + owenrId;//       String pullRtmpUrl = PULL_RTMP_URL + owenrId+ "?"+ safeUrl ;       String pullRtmpUrl = PULL_RTMP_URL + owenrId+ "?"+ safeUrl+"&bizid"+bizid ;        return pullRtmpUrl;    }    /**     * APP拉流地址獲得     */    public static String getHlsPullUrl(String owenrId,Long txTime) {        String safeUrl = getSafeUrl(key, owenrId, txTime);//        String appPullUrl = PULL_URL + owenrId + ".flv"+ "?"+ safeUrl;        String appPullUrl = PULL_URL + owenrId + ".m3u8"+ "?"+ safeUrl+"&bizid"+bizid ;//        String appPullUrl = PULL_URL + owenrId + ".flv";        return appPullUrl;    }     ////    /**//     * 獲取關閉直播的url關閉直播 需要傳送請求給騰訊伺服器,然後返回結果//     *//     * @param id//     *            需要關閉的房間ID//     * @return 關閉直播的url//     * @author [email protected]//     * @date 2017年7月22日 下午2:54:14//     *///    public static String getCloseLiveUrl(String id) {//        // 此請求的有效時間//        Long current = System.currentTimeMillis() / 1000 + 10;//        // 生成sign簽名//        String sign = MD5Encode.stringToMD5(new StringBuffer().append(API_KEY).append(current).toString());//        // 生成需要關閉的直播碼//        String code = bizid + "_" + id;//        // 生成關閉的引數列表//        String params = new StringBuffer().append("&interface=Live_Channel_SetStatus").append("&Param.s.channel_id=").append(code).append("&Param.n.status=0").append("&t=").append(current).append("&sign=").append(sign).toString();////        // 拼接關閉URL//        String url = API_ADDRESS + "?appid=" + APPID + params;//        return url;//    }//      public static void main(String[] args) {//        https://59744.liveplay.myqcloud.com/live/1003634281.flv//       https://59744.liveplay.myqcloud.com/live/1003634281.fl        // [騰訊雲](https://l.gushuji.site/tencent)獲取推流地址、拉流地址        Long now = System.currentTimeMillis() + 60L * 60L * 24L * 30L * 1000L;// 要轉成long型別,不然為負數        // 當前毫秒數+需要加上的時間毫秒數 = 過期時間毫秒數        Long txTime = now / 1000;// 推流碼過期時間秒數        String pushUrl = TecentCloudUtils.getPushUrl("1003634281",txTime);        String pullUrl = TecentCloudUtils.getPullUrl("1003634281",txTime);        String pullRtmpUrl = TecentCloudUtils.getPullRtmpUrl("1003634281",txTime);        System.out.println(pushUrl);        System.out.println(pullUrl);        System.out.println(pullRtmpUrl);   }        /**     * 這是推流防盜鏈的生成 KEY+ streamId + txTime     *      * @param key     *            防盜鏈使用的key     * @param streamId     *            通常為直播碼.示例:bizid+房間id     * @param txTime     *            到期時間     * @return     * @author [email protected]     */    public static String md5( long txTime) {        String input = new StringBuilder().                append(key).                append(Long.toHexString(txTime).toUpperCase()).toString();         String txSecret = null;        try {            MessageDigest messageDigest = MessageDigest.getInstance("MD5");            txSecret  = byteArrayToHexString(                    messageDigest.digest(input.getBytes("UTF-8")));        } catch (NoSuchAlgorithmException e) {            e.printStackTrace();        } catch (UnsupportedEncodingException e) {            e.printStackTrace();        }         return txSecret == null ? "" :txSecret.toString() ;    }        }

五、騰訊介面封裝

package com.skyonez.core.util; import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONArray;import com.alibaba.fastjson.JSONObject;import com.skyonez.core.entity.Live;import com.skyonez.core.pojo.Account;import com.skyonez.core.pojo.Crowd;import com.tencentyun.TLSSigAPIv2;import org.apache.http.Consts;import org.apache.http.HttpResponse;import org.apache.http.client.ClientProtocolException;import org.apache.http.client.HttpClient;import org.apache.http.client.methods.HttpPost;import org.apache.http.entity.StringEntity;import org.apache.http.impl.client.HttpClientBuilder;import org.apache.http.util.EntityUtils; import java.io.IOException;import java.util.*; /** * @description: 騰訊im 介面 * @author: liangyong * @time: 2019/8/24 0024 下午 15:30 */ public class TencentApi {     /**  * 單個帳號匯入介面  *   * @param Identifier 使用者id    * @param Nick       使用者名稱     * @param FaceUrl    頭像  * @param Type       預設 0 :普通使用者 1:為機器人   */ public Account insert(String Identifier, String Nick, String FaceUrl, Integer Type) {       Account account = new Account();        // 驗證獲取簽名       TLSSigAPIv2 api = new TLSSigAPIv2(AccessToken.SDK_APP_ID, AccessToken.KEY);     // 得到簽名     String sing = api.genSig("admin", 180 * 86400);     String result = sing.replaceAll("(\\r\\n|\\n|\\n\\r)", "");     // 獲取DefaultHttpClient請求        HttpClient client = HttpClientBuilder.create().build();     String url = AccessToken.ACCOUNT_IMPORT + "?sdkappid=" + AccessToken.SDK_APP_ID + "&identifier=admin&usersig="              + result + "&random=" + RandomUtil.getSixNumber() + "&contenttype=json";        HttpPost httpPost = new HttpPost(url);      // 設定請求的header      httpPost.addHeader("Content-Type", "application/json;charset=utf-8");       // 封裝請求引數       JSONObject postData = new JSONObject();     // 聊天室id        postData.put("Identifier", Identifier);     postData.put("Nick", Nick);     postData.put("Type", Type);     System.out.println(new StringEntity(postData.toString(), Consts.UTF_8));        // 設定請求的引數      StringEntity params = (new StringEntity(postData.toString(), Consts.UTF_8));        // 將引數傳入httpBody中       httpPost.setEntity(params);     // 執行請求     HttpResponse response;      try {           response = client.execute(httpPost);            JSONObject existJsonObject = JSON.parseObject(EntityUtils.toString(response.getEntity(), "utf-8"));         account = existJsonObject.toJavaObject(Account.class);          return account;     } catch (ClientProtocolException e) {           e.printStackTrace();            return account;     } catch (IOException e) {           e.printStackTrace();            return account;     }   }   /**  * 帳號刪除介面    *   * @param ids 使用者ids 集合   * @return   */ public Account drop(List<String> ids) {     Account account = new Account();        // 驗證獲取簽名       TLSSigAPIv2 api = new TLSSigAPIv2(AccessToken.SDK_APP_ID, AccessToken.KEY);     // 得到簽名     String sing = api.genSig("admin", 180 * 86400);     String result = sing.replaceAll("(\\r\\n|\\n|\\n\\r)", "");     // 獲取DefaultHttpClient請求        HttpClient client = HttpClientBuilder.create().build();     java.lang.String url = AccessToken.ACCOUNT_DELETE + "?sdkappid=" + AccessToken.SDK_APP_ID               + "&identifier=admin&usersig=" + result + "&random=" + RandomUtil.getSixNumber() + "&contenttype=json";     HttpPost httpPost = new HttpPost(url);      // 設定請求的header      httpPost.addHeader("Content-Type", "application/json;charset=utf-8");       // 封裝請求引數       JSONObject postData = new JSONObject();     List<Map<String, Object>> list = new ArrayList<>(2);        Map<java.lang.String, String> map = new HashMap<>();        for (int i = 0; i < ids.size(); i++) {          map.put("UserID", ids.get(i));      }       // 聊天室id        postData.put("DeleteItem", list);       // 列印引數     System.out.println(new StringEntity(postData.toString(), Consts.UTF_8));        // 設定請求的引數      StringEntity params = (new StringEntity(postData.toString(), Consts.UTF_8));        // 將引數傳入httpBody中       httpPost.setEntity(params);     // 執行請求     HttpResponse response;      try {           response = client.execute(httpPost);            JSONObject existJsonObject = JSON.parseObject(EntityUtils.toString(response.getEntity(), "utf-8"));         account = existJsonObject.toJavaObject(Account.class);          return account;     } catch (ClientProtocolException e) {           e.printStackTrace();            return account;     } catch (IOException e) {           e.printStackTrace();            return account;     }   }   /**  * 帳號刪除介面    *   * @param message 訊息     * @return   */ public Account drop(Message message) {      Account account = new Account();        // 驗證獲取簽名       TLSSigAPIv2 api = new TLSSigAPIv2(AccessToken.SDK_APP_ID, AccessToken.KEY);     // 得到簽名     String sing = api.genSig("admin", 180 * 86400);     String result = sing.replaceAll("(\\r\\n|\\n|\\n\\r)", "");     // 獲取DefaultHttpClient請求        HttpClient client = HttpClientBuilder.create().build();     String url = AccessToken.ACCOUNT_DELETE + "?sdkappid=" + AccessToken.SDK_APP_ID + "&identifier=admin&usersig="              + result + "&random=" + RandomUtil.getSixNumber() + "&contenttype=json";        HttpPost httpPost = new HttpPost(url);      // 設定請求的header      httpPost.addHeader("Content-Type", "application/json;charset=utf-8");       // 封裝請求引數       JSONObject postData = JSONObject.parseObject(message.toString());       // 列印引數     System.out.println(new StringEntity(postData.toString(), Consts.UTF_8));        // 設定請求的引數      StringEntity params = (new StringEntity(postData.toString(), Consts.UTF_8));        // 將引數傳入httpBody中       httpPost.setEntity(params);     // 執行請求     HttpResponse response;      try {           response = client.execute(httpPost);            JSONObject existJsonObject = JSON.parseObject(EntityUtils.toString(response.getEntity(), "utf-8"));         account = existJsonObject.toJavaObject(Account.class);          return account;     } catch (ClientProtocolException e) {           e.printStackTrace();            return account;     } catch (IOException e) {           e.printStackTrace();            return account;     }   }   /**  * 帳號刪除介面    *   * @param message 訊息     * @return   */ public Account sendMessage(Message message) {       Account account = new Account();        // 驗證獲取簽名       TLSSigAPIv2 api = new TLSSigAPIv2(AccessToken.SDK_APP_ID, AccessToken.KEY);     // 得到簽名     String sing = api.genSig("admin", 180 * 86400);     String result = sing.replaceAll("(\\r\\n|\\n|\\n\\r)", "");     // 獲取DefaultHttpClient請求        HttpClient client = HttpClientBuilder.create().build();     String url = AccessToken.OPENIM_SENDMSG + "?sdkappid=" + AccessToken.SDK_APP_ID + "&identifier=admin&usersig="              + result + "&random=" + RandomUtil.getSixNumber() + "&contenttype=json";        HttpPost httpPost = new HttpPost(url);      // 設定請求的header      httpPost.addHeader("Content-Type", "application/json;charset=utf-8");       // 封裝請求引數       JSONObject postData = JSONObject.parseObject(message.toString());       // 列印引數     System.out.println(new StringEntity(postData.toString(), Consts.UTF_8));        // 設定請求的引數      StringEntity params = (new StringEntity(postData.toString(), Consts.UTF_8));        // 將引數傳入httpBody中       httpPost.setEntity(params);     // 執行請求     HttpResponse response;      try {           response = client.execute(httpPost);            JSONObject existJsonObject = JSON.parseObject(EntityUtils.toString(response.getEntity(), "utf-8"));         account = existJsonObject.toJavaObject(Account.class);          return account;     } catch (ClientProtocolException e) {           e.printStackTrace();            return account;     } catch (IOException e) {           e.printStackTrace();            return account;     }   }   /**  * 帳號刪除介面    *   * @param ToAccount 使用者ids    * @return   */ public Account queryState(JSONObject ToAccount) {       Account account = new Account();        // 驗證獲取簽名       TLSSigAPIv2 api = new TLSSigAPIv2(AccessToken.SDK_APP_ID, AccessToken.KEY);     // 得到簽名     String sing = api.genSig("admin", 180 * 86400);     String result = sing.replaceAll("(\\r\\n|\\n|\\n\\r)", "");     // 獲取DefaultHttpClient請求        HttpClient client = HttpClientBuilder.create().build();     String url = AccessToken.OPENIM_QUERYSTATE + "?sdkappid=" + AccessToken.SDK_APP_ID              + "&identifier=admin&usersig=" + result + "&random=" + RandomUtil.getSixNumber() + "&contenttype=json";     HttpPost httpPost = new HttpPost(url);      // 設定請求的header      httpPost.addHeader("Content-Type", "application/json;charset=utf-8");       // 封裝請求引數       JSONObject postData = JSONObject.parseObject(ToAccount.toString());     // 列印引數     System.out.println(new StringEntity(postData.toString(), Consts.UTF_8));        // 設定請求的引數      StringEntity params = (new StringEntity(postData.toString(), Consts.UTF_8));        // 將引數傳入httpBody中       httpPost.setEntity(params);     // 執行請求     HttpResponse response;      try {           response = client.execute(httpPost);            JSONObject existJsonObject = JSON.parseObject(EntityUtils.toString(response.getEntity(), "utf-8"));         account = existJsonObject.toJavaObject(Account.class);          return account;     } catch (ClientProtocolException e) {           e.printStackTrace();            return account;     } catch (IOException e) {           e.printStackTrace();            return account;     }   }   /**  * 設定使用者資訊    *   * @param FromAccount    * @param list   * @return   */ public Account portrait_set(String FromAccount, List<Map<String, Object>> list) {       Account account = new Account();        // 驗證獲取簽名       TLSSigAPIv2 api = new TLSSigAPIv2(AccessToken.SDK_APP_ID, AccessToken.KEY);     // 得到簽名     String sing = api.genSig("admin", 180 * 86400);     String result = sing.replaceAll("(\\r\\n|\\n|\\n\\r)", "");     // 獲取DefaultHttpClient請求        HttpClient client = HttpClientBuilder.create().build();     String url = AccessToken.PORTRAIT_SET + "?sdkappid=" + AccessToken.SDK_APP_ID + "&identifier=admin&usersig="                + result + "&random=" + RandomUtil.getSixNumber() + "&contenttype=json";        HttpPost httpPost = new HttpPost(url);      // 設定請求的header      httpPost.addHeader("Content-Type", "application/json;charset=utf-8");       // 封裝請求引數       JSONObject postData = new JSONObject();     postData.put("From_Account", FromAccount);      postData.put("ProfileItem", list);      // 列印引數     System.out.println(new StringEntity(postData.toString(), Consts.UTF_8));        // 設定請求的引數      StringEntity params = (new StringEntity(postData.toString(), Consts.UTF_8));        // 將引數傳入httpBody中       httpPost.setEntity(params);     // 執行請求     HttpResponse response;      try {           response = client.execute(httpPost);            JSONObject existJsonObject = JSON.parseObject(EntityUtils.toString(response.getEntity(), "utf-8"));         account = existJsonObject.toJavaObject(Account.class);          return account;     } catch (ClientProtocolException e) {           e.printStackTrace();            return account;     } catch (IOException e) {           e.printStackTrace();            return account;     }   }   /**  * 獲取    *   * @param FromAccount    * @param list   * @return existJsonObject   */ public JSONObject portrait_get(String FromAccount, List<Map<String, Object>> list) {        // 驗證獲取簽名       TLSSigAPIv2 api = new TLSSigAPIv2(AccessToken.SDK_APP_ID, AccessToken.KEY);     // 得到簽名     String sing = api.genSig("admin", 180 * 86400);     String result = sing.replaceAll("(\\r\\n|\\n|\\n\\r)", "");     // 獲取DefaultHttpClient請求        HttpClient client = HttpClientBuilder.create().build();     String url = AccessToken.PORTRAIT_GET + "?sdkappid=" + AccessToken.SDK_APP_ID + "&identifier=admin&usersig="                + result + "&random=" + RandomUtil.getSixNumber() + "&contenttype=json";        HttpPost httpPost = new HttpPost(url);      // 設定請求的header      httpPost.addHeader("Content-Type", "application/json;charset=utf-8");       // 封裝請求引數       JSONObject postData = new JSONObject();     postData.put("From_Account", FromAccount);      postData.put("ProfileItem", list);      // 列印引數     System.out.println(new StringEntity(postData.toString(), Consts.UTF_8));        // 設定請求的引數      StringEntity params = (new StringEntity(postData.toString(), Consts.UTF_8));        // 將引數傳入httpBody中       httpPost.setEntity(params);     // 執行請求     HttpResponse response;      try {           response = client.execute(httpPost);            JSONObject existJsonObject = JSON.parseObject(EntityUtils.toString(response.getEntity(), "utf-8"));             return existJsonObject;     } catch (ClientProtocolException e) {           e.printStackTrace();        } catch (IOException e) {           e.printStackTrace();        }       return null;    }   /**  * 建立群組  *   * @param crowd 群組實體類    * @return   */ public Account createGroup(Crowd crowd, String liveNumber) {        Account account = new Account();        // 驗證獲取簽名       TLSSigAPIv2 api = new TLSSigAPIv2(AccessToken.SDK_APP_ID, AccessToken.KEY);     // 得到簽名     String sing = api.genSig("admin", 180 * 86400);     String result = sing.replaceAll("(\\r\\n|\\n|\\n\\r)", "");     // 獲取DefaultHttpClient請求        HttpClient client = HttpClientBuilder.create().build();     String url = AccessToken.CREATE_GROUP + "?sdkappid=" + AccessToken.SDK_APP_ID + "&identifier=admin&usersig="                + result + "&random=" + RandomUtil.getSixNumber() + "&contenttype=json";        HttpPost httpPost = new HttpPost(url);      // 設定請求的header      httpPost.addHeader("Content-Type", "application/json;charset=utf-8");       // 封裝請求引數       JSONObject postData = new JSONObject();     // 群主的 UserId(選填)       postData.put("Owner_Account", crowd.getOwnerAccount());     // 群組型別:Private/Public/ChatRoom/AVChatRoom/BChatRoom(必填)        postData.put("Type", crowd.getType());      // 群名稱(必填)      postData.put("Name", crowd.getName());      // 群組自定義id      postData.put("GroupId", "XDS" + liveNumber);        // 群簡介(選填)      postData.put("Introduction", crowd.getIntroduction());      // 群公告(選填)      postData.put("Notification", crowd.getNotification());//        // 群頭像 URL(選填)//        postData.put("FaceUrl",list);//        // 最大群成員數量(選填)//        postData.put("MaxMemberCount",list);//        // 申請加群處理方式(選填)申請加群處理方式。包含 FreeAccess(自由加入),NeedPermission(需要驗證),DisableApply(禁止加群),不填預設為 NeedPermission(需要驗證)     postData.put("ApplyJoinOption", "FreeAccess");      // 列印引數     System.out.println(new StringEntity(postData.toString(), Consts.UTF_8));        // 設定請求的引數      StringEntity params = (new StringEntity(postData.toString(), Consts.UTF_8));        // 將引數傳入httpBody中       httpPost.setEntity(params);     // 執行請求     HttpResponse response;      try {           response = client.execute(httpPost);            JSONObject existJsonObject = JSON.parseObject(EntityUtils.toString(response.getEntity(), "utf-8"));         account = existJsonObject.toJavaObject(Account.class);          return account;     } catch (ClientProtocolException e) {           e.printStackTrace();        } catch (IOException e) {           e.printStackTrace();        }       return null;    }   /**  * 解散    *   * @param crowd 群組實體類    * @return   */ public Account DESTORY_GROUP(String liveNumber) {       Account account = new Account();        // 驗證獲取簽名       TLSSigAPIv2 api = new TLSSigAPIv2(AccessToken.SDK_APP_ID, AccessToken.KEY);     // 得到簽名     String sing = api.genSig("admin", 180 * 86400);     String result = sing.replaceAll("(\\r\\n|\\n|\\n\\r)", "");     // 獲取DefaultHttpClient請求        HttpClient client = HttpClientBuilder.create().build();     String url = AccessToken.DESTORY_GROUP + "?sdkappid=" + AccessToken.SDK_APP_ID + "&identifier=admin&usersig="               + result + "&random=" + RandomUtil.getSixNumber() + "&contenttype=json";        HttpPost httpPost = new HttpPost(url);      // 設定請求的header      httpPost.addHeader("Content-Type", "application/json;charset=utf-8");       // 封裝請求引數       JSONObject postData = new JSONObject();     // 群組自定義id      postData.put("GroupId", "XDS" + liveNumber);        // 列印引數     System.out.println(new StringEntity(postData.toString(), Consts.UTF_8));        // 設定請求的引數      StringEntity params = (new StringEntity(postData.toString(), Consts.UTF_8));        // 將引數傳入httpBody中       httpPost.setEntity(params);     // 執行請求     HttpResponse response;      try {           response = client.execute(httpPost);            JSONObject existJsonObject = JSON.parseObject(EntityUtils.toString(response.getEntity(), "utf-8"));         account = existJsonObject.toJavaObject(Account.class);          return account;     } catch (ClientProtocolException e) {           e.printStackTrace();        } catch (IOException e) {           e.printStackTrace();        }       return null;    }   public Account createGroup(Message message) {       Account account = new Account();        // 驗證獲取簽名       TLSSigAPIv2 api = new TLSSigAPIv2(AccessToken.SDK_APP_ID, AccessToken.KEY);     // 得到簽名     String sing = api.genSig("admin", 180 * 86400);     String result = sing.replaceAll("(\\r\\n|\\n|\\n\\r)", "");     // 獲取DefaultHttpClient請求        HttpClient client = HttpClientBuilder.create().build();     String url = AccessToken.SEND_GROUP_MSG + "?sdkappid=" + AccessToken.SDK_APP_ID + "&identifier=admin&usersig="              + result + "&random=" + RandomUtil.getSixNumber() + "&contenttype=json";        HttpPost httpPost = new HttpPost(url);      // 設定請求的header      httpPost.addHeader("Content-Type", "application/json;charset=utf-8");       // 封裝請求引數       JSONObject postData = new JSONObject();     JSONObject jsonObject2 = new JSONObject();      jsonObject2.put("Text", "123456789");       JSONObject jsonObject = new JSONObject();       jsonObject.put("MsgType", "TIMTextElem");       jsonObject.put("MsgContent", jsonObject2);      JSONArray jsonArray = new JSONArray();      jsonArray.add(jsonObject);      postData.put("GroupId", "");        // 群組型別:Private/Public/ChatRoom/AVChatRoom/BChatRoom(必填)        postData.put("From_Account", "10031");      // 群名稱(必填)      postData.put("Random", "123456879");        postData.put("MsgBody", jsonArray);     // 列印引數     System.out.println(new StringEntity(postData.toString(), Consts.UTF_8));        // 設定請求的引數      StringEntity params = (new StringEntity(postData.toString(), Consts.UTF_8));        // 將引數傳入httpBody中       httpPost.setEntity(params);     // 執行請求     HttpResponse response;      try {           response = client.execute(httpPost);            JSONObject existJsonObject = JSON.parseObject(EntityUtils.toString(response.getEntity(), "utf-8"));         account = existJsonObject.toJavaObject(Account.class);          System.out.println(account.toString());         return account;     } catch (ClientProtocolException e) {           e.printStackTrace();        } catch (IOException e) {           e.printStackTrace();        }       return null;    }   /**  * 混流    *   * @return   */ public JSONObject common(JSONObject jsonObject) {       Long now = System.currentTimeMillis() + 60L * 60L * 24L * 30L * 1000L;// 要轉成long型別,不然為負數        // 當前毫秒數+需要加上的時間毫秒數 = 過期時間毫秒數       Long txTime = now / 1000;// 推流碼過期時間秒數       // 正式       String key = AccessToken.API_KEY + txTime;      String result = MD5Utils.MD5(key);      // 獲取DefaultHttpClient請求        HttpClient client = HttpClientBuilder.create().build();     String url = AccessToken.COMMON_ACCESS + "?appid=" + AccessToken.APP_ID + "&interface=Mix_StreamV2&t=" + txTime             + "&sign=" + result;        HttpPost httpPost = new HttpPost(url);      // 設定請求的header      httpPost.addHeader("Content-Type", "application/json;charset=utf-8");       // 封裝請求引數       JSONObject postData = new JSONObject();     postData.put("timestamp", txTime);      // 群組型別:Private/Public/ChatRoom/AVChatRoom/BChatRoom(必填)        postData.put("eventId", txTime);        // 群名稱(必填)      postData.put("interface", jsonObject);      // 列印引數//        System.out.println(new StringEntity(postData.toString(), Consts.UTF_8));       // 設定請求的引數      StringEntity params = (new StringEntity(postData.toString(), Consts.UTF_8));        // 將引數傳入httpBody中       httpPost.setEntity(params);     // 執行請求     HttpResponse response;      try {           response = client.execute(httpPost);//            System.out.println(EntityUtils.toString(response.getEntity(), "utf-8"));          JSONObject existJsonObject = JSON.parseObject(EntityUtils.toString(response.getEntity(), "utf-8"));         return existJsonObject;         } catch (ClientProtocolException e) {           e.printStackTrace();        } catch (IOException e) {           e.printStackTrace();        }       return null;    }   /**  *   * @Title: dropStream    * @Description: 移除混流    * @param liveNumber     * @return JSONObject    * @author liangyong     * @date 2019年10月16日下午3:55:35    */ public JSONObject dropStream(String liveNumber) {       JSONObject jsonObject = new JSONObject();       JSONObject para = new JSONObject();     para.put("app_id", AccessToken.APP_ID);     para.put("interface", "mix_streamv2.cancel_mix_stream");        para.put("mix_stream_session_id", liveNumber);      para.put("output_stream_id", liveNumber);       jsonObject.put("interfaceName", "Mix_StreamV2");        jsonObject.put("para", para);       common(jsonObject);     return jsonObject;  }   /**  * 畫布    *   * @param idsList    * @param live   * @return   */ public JSONObject anchorStart(List<Object> idsList, Live live, Integer max) {       // para 引數      JSONObject para = new JSONObject();     // 固定值mix_streamv2.start_mix_stream_advanced        para.put("interface", "mix_streamv2.start_mix_stream_advanced");        para.put("app_id", AccessToken.APP_ID);     para.put("mix_stream_template_id", 0);      // list     JSONArray list = new JSONArray();       for (int i = 0; i < idsList.size(); i++) {          // input_stream_list //         Map<String, Object> map = new HashMap<>();          JSONObject input_stream_list = new JSONObject();            if (i == 0) {               para.put("mix_stream_session_id", live.getLiveNumber());                para.put("output_stream_id", live.getLiveNumber());             para.put("output_stream_type", 1);              // 畫布               // layout_params                JSONObject layoutParams = new JSONObject();             // 1)背景流(即大主播畫面或畫布)的 image_layer 填1。                // 2)純音訊混流,該引數也需填。              layoutParams.put("image_layer", 1);             // 目前支援:                // 不填預設為0。              // 0表示輸入源為音視訊。              // 2表示輸入源為圖片。               // 3表示輸入源為畫布。               // 4表示輸入源為音訊。               // 5表示輸入源為純視訊。//                layoutParams.put("input_type", 2);              layoutParams.put("input_type", 3);              // 不填預設為輸入流的寬度。             // 使用百分比時,期望輸出為(百分比 * 背景寬)              layoutParams.put("image_width", 540);               // 不填預設為輸入流的高度。             // 使用百分比時,期望輸出為(百分比 * 背景高)              layoutParams.put("image_height", 540);              // 使用畫布(input_type = 3)時填寫,常用的顏色有:              // 紅色:0xcc0033。             // 黃色:0xcc9900。             // 綠色:0xcccc33。             // 藍色:0x99CCFF。             // 黑色:0x000000。             // 白色:0xFFFFFF。             // 灰色:0x999999。             // 自己設定:23232f              layoutParams.put("color", "23232f");//              layoutParams.put("picture_id", 118417);             // 引數1              input_stream_list.put("input_stream_id", "canvas1");                // 引數二              input_stream_list.put("layout_params", layoutParams);               list.add(input_stream_list);            }           // 畫布圖層1            // layout_params            JSONObject layoutParams1 = new JSONObject();            JSONObject crop_params = new JSONObject();          // 1)背景流(即大主播畫面或畫布)的 image_layer 填1。            // 2)純音訊混流,該引數也需填。          layoutParams1.put("image_layer", i + 2);            // 判斷主播共多少個來做畫布的佈局          // 1 v 1            if (max == 1) {                 if (i == 0) {                   // 不填預設為輸入流的寬度。                 // 使用百分比時,期望輸出為(百分比 * 背景寬)                  layoutParams1.put("image_width", 540 / 2.0 - 0.1);                  // 不填預設為輸入流的高度。                 // 使用百分比時,期望輸出為(百分比 * 背景高)//                    map = lists.get(i);//                    map.get("width");//                    map.get("width");                   layoutParams1.put("image_height", (540 / 2.0) * (250.0 / 188) - 0.1);                   // x 軸                  layoutParams1.put("location_x", 0);                 // y 軸                  layoutParams1.put("location_y", 0);                 crop_params.put("crop_width", 540);                 crop_params.put("crop_height", 540);                    crop_params.put("crop_x", 0);                   crop_params.put("crop_y", 0);               } else if (i == 1) {                    // 不填預設為輸入流的寬度。                 // 使用百分比時,期望輸出為(百分比 * 背景寬)                  layoutParams1.put("image_width", 540 / 2.0 - 0.1);                  // 不填預設為輸入流的高度。                 // 使用百分比時,期望輸出為(百分比 * 背景高)                  layoutParams1.put("image_height", (540 / 2.0) * (250.0 / 188.0) - 0.1);                 // // x 軸                   layoutParams1.put("location_x", 0.5);                   // y 軸                  layoutParams1.put("location_y", 0);                 crop_params.put("crop_width", 280);                 crop_params.put("crop_height", 280 * (250.0 / 188));                    crop_params.put("crop_x", 1);                   crop_params.put("crop_y", 100);             }               // 三人間          } else if (max == 2) {              if (i == 0) {                   // 不填預設為輸入流的寬度。                 // 使用百分比時,期望輸出為(百分比 * 背景寬)                  layoutParams1.put("image_width", 540 / 2.0 - 0.1);                  // 不填預設為輸入流的高度。                 // 使用百分比時,期望輸出為(百分比 * 背景高)//                    map = lists.get(i);//                    map.get("width");//                    map.get("width");                   layoutParams1.put("image_height", 540 / 2.0 - 0.1);                 // x 軸                  layoutParams1.put("location_x", 0.25);                  // y 軸                  layoutParams1.put("location_y", 0);                 crop_params.put("crop_width", 540);                 crop_params.put("crop_height", 540);                    crop_params.put("crop_x", 0);                   crop_params.put("crop_y", 0);               } else if (i == 1) {                    // 不填預設為輸入流的寬度。                 // 使用百分比時,期望輸出為(百分比 * 背景寬)                  layoutParams1.put("image_width", 540 / 2.0 - 0.1);                  // 不填預設為輸入流的高度。                 // 使用百分比時,期望輸出為(百分比 * 背景高)                  layoutParams1.put("image_height", 540 / 2.0 - 0.1);                 // // x 軸                   layoutParams1.put("location_x", 0);                 // y 軸                  layoutParams1.put("location_y", 0.5);                   crop_params.put("crop_width", 280);                 crop_params.put("crop_height", 280);                    crop_params.put("crop_x", 1);                   crop_params.put("crop_y", 100);             } else if (i == 2) {                    // 不填預設為輸入流的寬度。                 // 使用百分比時,期望輸出為(百分比 * 背景寬)                  layoutParams1.put("image_width", 540 / 2.0 - 0.1);                  // 不填預設為輸入流的高度。                 // 使用百分比時,期望輸出為(百分比 * 背景高)                  layoutParams1.put("image_height", 540 / 2.0 - 0.1);                 // x 軸                  layoutParams1.put("location_x", 0.5);                   // y 軸                  layoutParams1.put("location_y", 0.5);                   crop_params.put("crop_width", 280);                 crop_params.put("crop_height", 280);                    crop_params.put("crop_x", 1);                   crop_params.put("crop_y", 100);             }               // 四人間          } else if (max == 3) {              if (i == 0) {                   // 不填預設為輸入流的寬度。                 // 使用百分比時,期望輸出為(百分比 * 背景寬)                  layoutParams1.put("image_width", 540 / 2.0 - 0.1);                  // 不填預設為輸入流的高度。                 // 使用百分比時,期望輸出為(百分比 * 背景高)//                        map = lists.get(i);//                        map.get("width");//                        map.get("width");                   layoutParams1.put("image_height", 540 / 2.0 - 0.1);                 // x 軸                  layoutParams1.put("location_x", 0);                 // y 軸                  layoutParams1.put("location_y", 0);                 crop_params.put("crop_width", 540);                 crop_params.put("crop_height", 540);                    crop_params.put("crop_x", 0);                   crop_params.put("crop_y", 0);               } else if (i == 1) {                    // 不填預設為輸入流的寬度。                 // 使用百分比時,期望輸出為(百分比 * 背景寬)                  layoutParams1.put("image_width", 540 / 2.0 - 0.1);                  // 不填預設為輸入流的高度。                 // 使用百分比時,期望輸出為(百分比 * 背景高)                  layoutParams1.put("image_height", 540 / 2.0 - 0.1);                 // // x 軸                   layoutParams1.put("location_x", 0.5);                   // y 軸                  layoutParams1.put("location_y", 0);                 crop_params.put("crop_width", 280);                 crop_params.put("crop_height", 280);                    crop_params.put("crop_x", 1);                   crop_params.put("crop_y", 100);             } else if (i == 2) {                    // 不填預設為輸入流的寬度。                 // 使用百分比時,期望輸出為(百分比 * 背景寬)                  layoutParams1.put("image_width", 540 / 2.0 - 0.1);                  // 不填預設為輸入流的高度。                 // 使用百分比時,期望輸出為(百分比 * 背景高)                  layoutParams1.put("image_height", 540 / 2.0 - 0.1);                 // x 軸                  layoutParams1.put("location_x", 0);                 // y 軸                  layoutParams1.put("location_y", 0.5);                   crop_params.put("crop_width", 280);                 crop_params.put("crop_height", 280);                    crop_params.put("crop_x", 1);                   crop_params.put("crop_y", 100);             } else if (i == 3) {                    // 不填預設為輸入流的寬度。                 // 使用百分比時,期望輸出為(百分比 * 背景寬)                  layoutParams1.put("image_width", 540 / 2.0 - 0.1);                  // 不填預設為輸入流的高度。                 // 使用百分比時,期望輸出為(百分比 * 背景高)                  layoutParams1.put("image_height", 540 / 2.0 - 0.1);                 // x 軸                  layoutParams1.put("location_x", 0.5);                   // y 軸                  layoutParams1.put("location_y", 0.5);                   crop_params.put("crop_width", 280);                 crop_params.put("crop_height", 280);                    crop_params.put("crop_x", 1);                   crop_params.put("crop_y", 100);             }               // 五人間          } else if (max == 4) {              if (i == 0) {                   // 不填預設為輸入流的寬度。                 // 使用百分比時,期望輸出為(百分比 * 背景寬)                  layoutParams1.put("image_width", 540 / 3.0 - 0.1);                  // 不填預設為輸入流的高度。                 // 使用百分比時,期望輸出為(百分比 * 背景高)//                        map = lists.get(i);//                        map.get("width");//                        map.get("width");                   layoutParams1.put("image_height", 540 / 3.0 - 0.1);                 // x 軸                  layoutParams1.put("location_x", 1 / 3.0 / 2.0);                 // y 軸                  layoutParams1.put("location_y", 0);                 crop_params.put("crop_width", 540);                 crop_params.put("crop_height", 540);                    crop_params.put("crop_x", 0);                   crop_params.put("crop_y", 0);               } else if (i == 1) {                    // 不填預設為輸入流的寬度。                 // 使用百分比時,期望輸出為(百分比 * 背景寬)                  layoutParams1.put("image_width", 540 / 3.0 - 0.1);                  // 不填預設為輸入流的高度。                 // 使用百分比時,期望輸出為(百分比 * 背景高)                  layoutParams1.put("image_height", 540 / 3.0 - 0.1);                 // // x 軸                   layoutParams1.put("location_x", 1 / 3.0 / 2.0 + 1 / 3.0);                   // y 軸                  layoutParams1.put("location_y", 0);                 crop_params.put("crop_width", 280);                 crop_params.put("crop_height", 280);                    crop_params.put("crop_x", 1);                   crop_params.put("crop_y", 100);             } else if (i == 2) {                    // 不填預設為輸入流的寬度。                 // 使用百分比時,期望輸出為(百分比 * 背景寬)                  layoutParams1.put("image_width", 540 / 3.0 - 0.1);                  // 不填預設為輸入流的高度。                 // 使用百分比時,期望輸出為(百分比 * 背景高)                  layoutParams1.put("image_height", 540 / 3.0 - 0.1);                 // x 軸                  layoutParams1.put("location_x", 0);                 // y 軸                  layoutParams1.put("location_y", 1 / 3.0);                   crop_params.put("crop_width", 280);                 crop_params.put("crop_height", 280);                    crop_params.put("crop_x", 1);                   crop_params.put("crop_y", 100);             } else if (i == 3) {                    // 不填預設為輸入流的寬度。                 // 使用百分比時,期望輸出為(百分比 * 背景寬)                  layoutParams1.put("image_width", 540 / 3.0 - 0.1);                  // 不填預設為輸入流的高度。                 // 使用百分比時,期望輸出為(百分比 * 背景高)                  layoutParams1.put("image_height", 540 / 3.0 - 0.1);                 // x 軸                  layoutParams1.put("location_x", 1 / 3.0);                   // y 軸                  layoutParams1.put("location_y", 1 / 3.0);                   crop_params.put("crop_width", 280);                 crop_params.put("crop_height", 280);                    crop_params.put("crop_x", 1);                   crop_params.put("crop_y", 100);             } else if (i == 4) {                    // 不填預設為輸入流的寬度。                 // 使用百分比時,期望輸出為(百分比 * 背景寬)                  layoutParams1.put("image_width", 540 / 3.0 - 0.1);                  // 不填預設為輸入流的高度。                 // 使用百分比時,期望輸出為(百分比 * 背景高)                  layoutParams1.put("image_height", 540 / 3.0 - 0.1);                 // x 軸                  layoutParams1.put("location_x", 1 / 3.0 * 2.0);                 // y 軸                  layoutParams1.put("location_y", 1 / 3.0);                   crop_params.put("crop_width", 280);                 crop_params.put("crop_height", 280);                    crop_params.put("crop_x", 1);                   crop_params.put("crop_y", 100);             }               // 六人間          } else if (max == 5) {              if (i == 0) {                   // 不填預設為輸入流的寬度。                 // 使用百分比時,期望輸出為(百分比 * 背景寬)                  layoutParams1.put("image_width", 540 / 3.0 - 0.1);                  // 不填預設為輸入流的高度。                 // 使用百分比時,期望輸出為(百分比 * 背景高)//                        map = lists.get(i);//                        map.get("width");//                        map.get("width");                   layoutParams1.put("image_height", 540 / 3.0 - 0.1);                 // x 軸                  layoutParams1.put("location_x", 0);                 // y 軸                  layoutParams1.put("location_y", 0);                 crop_params.put("crop_width", 540);                 crop_params.put("crop_height", 540);                    crop_params.put("crop_x", 0);                   crop_params.put("crop_y", 0);               } else if (i == 1) {                    // 不填預設為輸入流的寬度。                 // 使用百分比時,期望輸出為(百分比 * 背景寬)                  layoutParams1.put("image_width", 540 / 3.0 - 0.1);                  // 不填預設為輸入流的高度。                 // 使用百分比時,期望輸出為(百分比 * 背景高)                  layoutParams1.put("image_height", 540 / 3.0 - 0.1);                 // // x 軸                   layoutParams1.put("location_x", 1 / 3.0);                   // y 軸                  layoutParams1.put("location_y", 0);                 crop_params.put("crop_width", 280);                 crop_params.put("crop_height", 280);                    crop_params.put("crop_x", 1);                   crop_params.put("crop_y", 100);             } else if (i == 2) {                    // 不填預設為輸入流的寬度。                 // 使用百分比時,期望輸出為(百分比 * 背景寬)                  layoutParams1.put("image_width", 540 / 3.0 - 0.1);                  // 不填預設為輸入流的高度。                 // 使用百分比時,期望輸出為(百分比 * 背景高)                  layoutParams1.put("image_height", 540 / 3.0 - 0.1);                 // x 軸                  layoutParams1.put("location_x", 1 / 3.0 * 2);                   // y 軸                  layoutParams1.put("location_y", 0);                 crop_params.put("crop_width", 280);                 crop_params.put("crop_height", 280);                    crop_params.put("crop_x", 1);                   crop_params.put("crop_y", 100);             } else if (i == 3) {                    // 不填預設為輸入流的寬度。                 // 使用百分比時,期望輸出為(百分比 * 背景寬)                  layoutParams1.put("image_width", 540 / 3.0 - 0.1);                  // 不填預設為輸入流的高度。                 // 使用百分比時,期望輸出為(百分比 * 背景高)                  layoutParams1.put("image_height", 540 / 3.0 - 0.1);                 // x 軸                  layoutParams1.put("location_x", 0);                 // y 軸                  layoutParams1.put("location_y", 1 / 3.0);                   crop_params.put("crop_width", 280);                 crop_params.put("crop_height", 280);                    crop_params.put("crop_x", 1);                   crop_params.put("crop_y", 100);             } else if (i == 4) {                    // 不填預設為輸入流的寬度。                 // 使用百分比時,期望輸出為(百分比 * 背景寬)                  layoutParams1.put("image_width", 540 / 3.0 - 0.1);                  // 不填預設為輸入流的高度。                 // 使用百分比時,期望輸出為(百分比 * 背景高)                  layoutParams1.put("image_height", 540 / 3.0 - 0.1);                 // x 軸                  layoutParams1.put("location_x", 1 / 3.0);                   // y 軸                  layoutParams1.put("location_y", 1 / 3.0);                   crop_params.put("crop_width", 280);                 crop_params.put("crop_height", 280);                    crop_params.put("crop_x", 1);                   crop_params.put("crop_y", 100);             } else if (i == 5) {                    // 不填預設為輸入流的寬度。                 // 使用百分比時,期望輸出為(百分比 * 背景寬)                  layoutParams1.put("image_width", 540 / 3.0 - 0.1);                  // 不填預設為輸入流的高度。                 // 使用百分比時,期望輸出為(百分比 * 背景高)                  layoutParams1.put("image_height", 540 / 3.0 - 0.1);                 // x 軸                  layoutParams1.put("location_x", 1 / 3.0 * 2.0);                 // y 軸                  layoutParams1.put("location_y", 1 / 3.0);                   crop_params.put("crop_width", 280);                 crop_params.put("crop_height", 280);                    crop_params.put("crop_x", 1);                   crop_params.put("crop_y", 100);             }               // 七人間          } else if (max == 6) {              if (i == 0) {                   // 不填預設為輸入流的寬度。                 // 使用百分比時,期望輸出為(百分比 * 背景寬)                  layoutParams1.put("image_width", 540 / 3.0 - 0.1);                  // 不填預設為輸入流的高度。                 // 使用百分比時,期望輸出為(百分比 * 背景高)                  layoutParams1.put("image_height", 540 / 3.0 - 0.1);                 // x 軸                  layoutParams1.put("location_x", 0);                 // y 軸                  layoutParams1.put("location_y", 0);                 crop_params.put("crop_width", 540);                 crop_params.put("crop_height", 540);                    crop_params.put("crop_x", 0);                   crop_params.put("crop_y", 0);               } else if (i == 1) {                    // 不填預設為輸入流的寬度。                 // 使用百分比時,期望輸出為(百分比 * 背景寬)                  layoutParams1.put("image_width", 540 / 3.0 - 0.1);                  // 不填預設為輸入流的高度。                 // 使用百分比時,期望輸出為(百分比 * 背景高)                  layoutParams1.put("image_height", 540 / 3.0 - 0.1);                 // // x 軸                   layoutParams1.put("location_x", 0);                 // y 軸                  layoutParams1.put("location_y", 1 / 3.0);                   crop_params.put("crop_width", 280);                 crop_params.put("crop_height", 280);                    crop_params.put("crop_x", 1);                   crop_params.put("crop_y", 100);             } else if (i == 2) {                    // 不填預設為輸入流的寬度。                 // 使用百分比時,期望輸出為(百分比 * 背景寬)                  layoutParams1.put("image_width", 540 / 3.0 - 0.1);                  // 不填預設為輸入流的高度。                 // 使用百分比時,期望輸出為(百分比 * 背景高)                  layoutParams1.put("image_height", 540 / 3.0 - 0.1);                 // x 軸                  layoutParams1.put("location_x", 1 / 3.0);                   // y 軸                  layoutParams1.put("location_y", 1 / 3.0);                   crop_params.put("crop_width", 280);                 crop_params.put("crop_height", 280);                    crop_params.put("crop_x", 1);                   crop_params.put("crop_y", 100);             } else if (i == 3) {                    // 不填預設為輸入流的寬度。                 // 使用百分比時,期望輸出為(百分比 * 背景寬)                  layoutParams1.put("image_width", 540 / 3.0 - 0.1);                  // 不填預設為輸入流的高度。                 // 使用百分比時,期望輸出為(百分比 * 背景高)                  layoutParams1.put("image_height", 540 / 3.0 - 0.1);                 // x 軸                  layoutParams1.put("location_x", 1 / 3.0 * 2.0);                 // y 軸                  layoutParams1.put("location_y", 1 / 3.0);                   crop_params.put("crop_width", 280);                 crop_params.put("crop_height", 280);                    crop_params.put("crop_x", 1);                   crop_params.put("crop_y", 100);             } else if (i == 4) {                    // 不填預設為輸入流的寬度。                 // 使用百分比時,期望輸出為(百分比 * 背景寬)                  layoutParams1.put("image_width", 540 / 3.0 - 0.1);                  // 不填預設為輸入流的高度。                 // 使用百分比時,期望輸出為(百分比 * 背景高)                  layoutParams1.put("image_height", 540 / 3.0 - 0.1);                 // x 軸                  layoutParams1.put("location_x", 0);                 // y 軸                  layoutParams1.put("location_y", 1 / 3.0 * 2);                   crop_params.put("crop_width", 280);                 crop_params.put("crop_height", 280);                    crop_params.put("crop_x", 1);                   crop_params.put("crop_y", 100);             } else if (i == 5) {                    // 不填預設為輸入流的寬度。                 // 使用百分比時,期望輸出為(百分比 * 背景寬)                  layoutParams1.put("image_width", 540 / 3.0 - 0.1);                  // 不填預設為輸入流的高度。                 // 使用百分比時,期望輸出為(百分比 * 背景高)                  layoutParams1.put("image_height", 540 / 3.0 - 0.1);                 // x 軸                  layoutParams1.put("location_x", 1 / 3.0);                   // y 軸                  layoutParams1.put("location_y", 1 / 3.0 * 2.0);                 crop_params.put("crop_width", 280);                 crop_params.put("crop_height", 280);                    crop_params.put("crop_x", 1);                   crop_params.put("crop_y", 100);             } else if (i == 6) {                    // 不填預設為輸入流的寬度。                 // 使用百分比時,期望輸出為(百分比 * 背景寬)                  layoutParams1.put("image_width", 540 / 3.0 - 0.1);                  // 不填預設為輸入流的高度。                 // 使用百分比時,期望輸出為(百分比 * 背景高)                  layoutParams1.put("image_height", 540 / 3.0 - 0.1);                 // x 軸                  layoutParams1.put("location_x", 1 / 3.0 * 2.0);                 // y 軸                  layoutParams1.put("location_y", 1 / 3.0 * 2.0);                 crop_params.put("crop_width", 280);                 crop_params.put("crop_height", 280);                    crop_params.put("crop_x", 1);                   crop_params.put("crop_y", 100);             }           }           // input_stream_list            JSONObject input_stream_list1 = new JSONObject();//            // 引數1           input_stream_list1.put("input_stream_id", idsList.get(i));          // 引數二          input_stream_list1.put("layout_params", layoutParams1);         input_stream_list1.put("crop_params", crop_params);         list.add(input_stream_list1);       }       // 封裝畫布佈局       para.put("input_stream_list", list);        JSONObject jsonObject = new JSONObject();       // 固定值Mix_StreamV2      jsonObject.put("interfaceName", "Mix_StreamV2");        jsonObject.put("para", para);       TencentApi api = new TencentApi();      JSONObject result = api.common(jsonObject);         return result;  }   public Boolean sendGroupMsg(JSONObject message) {       // 驗證獲取簽名       TLSSigAPIv2 api = new TLSSigAPIv2(AccessToken.SDK_APP_ID, AccessToken.KEY);     // 得到簽名     String sing = api.genSig("admin", 180 * 86400);     String result = sing.replaceAll("(\\r\\n|\\n|\\n\\r)", "");     // 獲取DefaultHttpClient請求        HttpClient client = HttpClientBuilder.create().build();     String url = AccessToken.SEND_GROUP_SYSTEM_NOTIFICATION + "?sdkappid=" + AccessToken.SDK_APP_ID             + "&identifier=admin&usersig=" + result + "&random=" + getSixNumber() + "&contenttype=json";        HttpPost httpPost = new HttpPost(url);      // 設定請求的header      httpPost.addHeader("Content-Type", "application/json;charset=utf-8");       // 列印引數     // 設定請求的引數      StringEntity params = (new StringEntity(message.toString(), Consts.UTF_8));     // 將引數傳入httpBody中       httpPost.setEntity(params);     // 執行請求     HttpResponse response;      try {           response = client.execute(httpPost);            JSONObject existJsonObject = JSON.parseObject(EntityUtils.toString(response.getEntity(), "utf-8"));         Integer errorCode = (Integer) existJsonObject.get("ErrorCode");         if (errorCode == 0) {               return true;            } else {                return false;           }       } catch (ClientProtocolException e) {           e.printStackTrace();        } catch (IOException e) {           e.printStackTrace();        }       return null;    }    }

備註:

1.根據自己的業務進行修改,當用戶註冊時進行IM繫結註冊,讓自己的會員跟騰訊的IM體系進行關聯

2. 根據自己的業務開啟直播時,在什麼流程下建立直播間群聊,群聊一定要是AVChatRoom,而且這個單獨購買服務,否則有建立上線。

3.為了降低延遲最後採用rtmp 超低延遲解決方案。需要購買實時音視訊套餐包!

新手無怪,有問題評論區留言即可,會盡快回復!