开始混流接口json格式

下载pdf
更新时间:2019-12-19 11:14

请注意:该功能需要联系 ZEGO 技术支持开通。

1 接口调用请求说明

http请求方式: POST/JSON,需使用https
正式环境地址
https://webapi.zego.im/cgi/start-mix?access_token=ACCESS_TOKEN
测试环境地址
https://testwebapi.zego.im/cgi/start-mix?access_token=ACCESS_TOKEN

2 参数说明

参数名 是否必须 数据类型 说明
signature string 签名摘要,生成规则md5(appid+timestamp+callbacksecret)
timestamp int64 时间戳(单位秒)
id_name string 用户标识 (不同的混流任务id_name要不同)
biztype string 业务类型 live or rtv 默认live
stream_id string 流名
appid uint64 业务侧所使用的appid
MixInput MixInput[] 混流输入流的信息(json结构体格式),
MixOutput MixOutput[] 混流输出流的信息(json结构体格式),
live_channel string 直播频道,即房间id
output_bg_image string 混流背景图,如需设置,请联系对应的技术支持
output_bg_color int64 混流背景色,RGB色,需传10进制的值
with_sound_level int 混流音浪,1: 开启,0:不开启;默认值是0
userdata string 用户数据,自定义的数据客户端是通过收到媒体次要信息的接口 onRecvMediaSideInfo 回调
seq int 混流请求的序号,保证混流请求被执行的顺序,自增唯一
watermark WaterMarkConfig 水印结构(json结构体格式),如需设置,请联系对应的技术支持
task_id string 混流任务id,多路混流输出必须填写(客户自定义,务必保证唯一)
audio_channel_cnt int32 音频通道数 默认0:单声道,1:单声道,2:双声道
testenv int 测试标识
version int 版本号:1
bypass uint32 是否启用单流透传开关(默认不启用) 1: 启用, 0:不启用
extra_params ExParams[] 额外参数(json结构体格式),具体联系技术支持,比如video_encode/sei_mode,可参见数据示例

MixInput成员如下:

参数名 是否必须 数据类型 说明
url string 输入流地址
stream_id string 输入流名,URL和流ID两者取其一即可,如填写了流id,则url为空
sound_level_id int 启用音浪的时候用于标记唯一用户
content_control int 内容控制。0:取音视频,1:取音频(未实现),2:取视频
rect RectInfo 流的位置信息(json结构体格式)
RectInfo成员如下:
参数名 是否必须 数据类型 说明
layer int 图层层次
top int 上边框,纯音频混流的时候,推荐填写0
left int 左边框,纯音频混流的时候,推荐填写0
bottom int 下边框,纯音频混流的时候,推荐填写1
right int 右边框,纯音频混流的时候,推荐填写1

MixOutput成员如下:

参数名 是否必须 数据类型 说明
stream_id string 输出流名
mixurl string 输出流地址,URL和流ID两者取其一即可,如填写了流id,则url为空
bitrate int 视频码率,纯音频混流的时候,推荐填写1
fps int 视频帧率,纯音频混流的时候,推荐填写1
height int 画布高–视频输出分辨率高,纯音频混流的时候,推荐填写1
width int 画布宽–视频输出分辨率宽,纯音频混流的时候,推荐填写1
audio_enc_id int 音频编码 0:HE_AAC,1:AAC_LC,2:MP3
audio_bitrate int 混流输出音频码率,默认48K
audio_channel_cnt int 音频通道数 0:单声道,1:单声道,2:双声道
encode_mode int 混流输出码率控制模式,0 表示 CBR 恒定码率,1 表示 CRF 恒定质量,默认值为 0
encode_qua int 视频质量参数:[0, 51],不指定时默认23。0最好,51最差

WaterMarkConfig成员如下:

参数名 是否必须 数据类型 说明
image string 水印图片
rect RectInfo 水印布局(json结构体格式)
WaterMarkConfig-rect成员如下:
参数名 是否必须 数据类型 说明
top int 上边框
left int 左边框
bottom int 下边框
right int 右边框

ExParams成员如下:

参数名 是否必须 数据类型 说明
key string key值
value string value值

3 数据示例

{
    "signature": "",// md5(appid+timestamp+secret);必填
    "timestamp":1562052086857,//timestamp必填,对单次请求做校验;必填
    "id_name": '', // 用户标识;必填
    "live_channel": '', // 房间标识;可缺省
    "appid": 400840168,//appid;必填
    "output_bg_image":'', //混流背景图,如没有就为空;混流背景图,支持预设图片,如 (preset-id://xxx.jpg/png);此值由zego提供,开发者先将背景图提供给zego,zego设置后再反馈背景图片的设置参数;可缺省
    "with_sound_level": 0, // 混流音浪,1: 开启,0:不开启;默认值是0;可缺省
    "output_bg_color": '', // 混流背景色,如没有就为空;混流背景颜色,前三个字节为 RGB,即 0xRRGGBBxx;例如:选取RGB为 #FFFFFF00(白色)把#后面的16进制转成10进制,所以转换后传4294967040这个值,数值类型是整型;可缺省
    "userdata": "", // 用户数据,userData自定义的数据客户端是通过收到媒体次要信息的接口 onRecvMediaSideInfo 回调,如没有就为空;可缺省
    "seq": 1, // 混流请求的序号,保证混流请求被执行的顺序,自增唯一;可缺省
    "task_id":"mult_output_task_id",// 混流任务id;可缺省;但多路混流输出必须填写(客户自定义,务必保证唯一)
    "version":1 // 默认是1
    "MixInput":[//输入流列表;必填
        {
            "url":"stream1_url", //输入流1拉流URL,如没有就为空;必填
            "stream_id":"stream1",//流ID,URL和流ID两者取其一即可,如填写了流id,则url为空;必填
            "sound_level_id": 0, // 设置音浪ID,用于标识用户,soundLevelID必须 >= 0 且 <= 4294967295L(即2^32-1);可缺省
            "content_control": 0, // 内容控制;0:取音视频,2:取视频,默认值是0;可缺省
            "rect": { //流的位置信息;必填
                "layer":0,//可缺省
                "top":0,//必填
                "left":0,//必填
                "bottom":640,//必填
                "right":480//必填
                //  原点在左上角,top/bottom/left/right 定义如下:
                //
                //  (left, top)-----------------------
                //  |                                |
                //  |                                |
                //  |                                |
                //  |                                |
                //  -------------------(right, bottom)
            }
        },
        {
            "url":"stream2_url",//输入流2拉流URL,如没有就为空
            "stream_id":"stream2",//流ID,URL和流ID两者取其一即可,如填写了流id,则url为空
            "rect":{ //流的位置信息
                "top":480,
                "left":320,
                "bottom":640,
                "right":480
            }
        }
    ],
    "MixOutput":[//输出流列表;必填
        {
            //流ID,URL和流ID两者取其一即可,如填写了流id,则url为空;必填   
            "stream_id":  "mix_stream1", 

            // 输出流推流URL;如果没有则为空;必填   
            "mixurl":"mixurl1",

            // 混流输出视频码率;必填;
            // 视频码率值范围<= 10M,此参数单位是 bps,1M = 1 * 1000 * 1000 bps       
            "bitrate":400000, 

            // 混流输出视频帧率;必填;值范围:[1,30],根据网络情况设定值,帧率越高画面越流畅
            "fps":15, 

            // 混流输出视频分辨率高;必填;不确定用什么分辨率时可采用16:9的规格设置
            //此值必须≥输入流列表中bottom的最大值
            "height":640

            // 混流输出视频分辨率宽;必填;不确定用什么分辨率时可采用16:9的规格设置
            //此值必须≥输入流列表中right的最大值
            "width":480,

            // 混流输出音频编码格式,默认值为 0;可缺省
            // 可选值为 0:默认编码;1:可选编码
            "audio_enc_id":  0,

            // 混流输出音频码率,码率范围值是[10000, 192000];可缺省
            // 若audio_enc_id采用默认音频编码0,采用 1/2声道时,建议码率值是 48k/64k,可根据需要在此基础上调整;
            // 若audio_enc_id采用可选音频编码1,采用 1/2声道时,建议码率值是 80k/128k,可根据需要在此基础上调整
            "audio_bitrate": 64000, 

            // 混流声道数, 1-单声道,2-双声道,默认为单声道;可缺省
            "audio_channel_cnt": 1, 

            // 混流输出码率控制模式,0 表示 CBR 恒定码率,1 表示 CRF 恒定质量,默认值为 0;可缺省
            // CRF 恒定质量 表示保证视频的清晰度在固定水平上,因此若采用此控制模式,码率会根据网速的变化波动,比如游戏类直播时,为了让观众看到比较流畅的操作类画面会使用恒定质量模式,提升视频质量
            "encode_mode": 0, 

            // 混流输出质量,输出码率控制模式参数设置为 CRF恒定质量时此设置值有效,有效值范围 [0,51],默认值是 23;可缺省
            // 若想视频质量好点,在23的基础上降低质量值测试调整;若想文件大小小一点,在23的基础上升高质量值测试调整
            // 以 x 值下的文件大小为例, x + 6 下的文件大小是 x 值下文件大小的一半,x - 6 下的文件大小是 x 值下 文件大小的两倍
            "encode_qua": 23, 
        },
    //如果有混流输出N路流的需求,可继续填写第N路流的输出信息
        {
             "stream_id":  "mix_stream2", //流ID
             "mixurl":"mixurl2", // 输出流推流URL
             "bitrate":400000, // 混流输出视频码率
             "fps":15, // 混流输出视频帧率,值范围:[1,30]
             "height":640,// 混流输出视频分辨率高
             "width":480,// 混流输出视频分辨率宽
      }
    ],
    "watermark":{//水印位置;可缺省
        "image":"iamge-id",//(preset-id://xxx.jpg/png)请联系技术支持设置
        "rect":{
            "top":0,
            "bottom":10,
            "left":0,
            "right":10
        }
    },
    "extra_params":[
        {
            "key":"video_encode", // 视频编码格式
            "value":"h265" //h265即选用h265编码格式,默认h264格式
        },
        {
            "key":"sei_mode", //sei发送模式
            "value":"1"  //1代表通过单帧发送,默认通过视频帧发送
        }
    ]
}

当需要纯音频混流的时候,推荐使用如下配置:
MixOutput.fps = 1
MixOutput.bitrate = 1
MixOutput.height = 1
MixOutput.width = 1
MixInput.rect.top = 0
MixInput.rect.left = 0
MixInput.rect.bottom = 1
MixInput.rect.right = 1

4 返回说明

{
        code : 0,
        message : 'success',
        data:{
            "id_name": '', // 用户标识
            "seq": '', // 序列号
            "live_channel": '', // 房间标识
             "play": [
                {
                    "hdl_url": "http://flv.dndemo.zego.im/zego/mix_stream.flv",
                    "hls_url": "http://hls.dndemo.zego.im/zego/mix_stream/index.m3u8",
                    "rtmp_url": "rtmp://rtmp.dndemo.zego.im/zego/mix_stream",
                    "stream_alias": "mix_stream"
                }
            ],
        }
}

5 示例代码

备注:

1> 若是测试环境,输入流的流 ID 和 输出流的流 ID 需要加上 zegotest-客户appid- 前缀,不加可能会导致混流失败和拉不到混流。

2> 混流协议id_name字段(用户标识),用于保证用户级混流请求的串行处理。如后台混流共用同一个id_name,可能会导致混流请求失败。

5.1 Java示例代码

package com.zego;

import java.io.*;
import java.net.*;
import java.util.*;
import java.security.*;
import com.alibaba.fastjson.*;

public class StartMixStream {

    // 发送post请求
    public static String sendPost(String url, String param) {
        String result = "";
        try {
            URL realUrl = new URL(url);
            URLConnection conn = realUrl.openConnection();
            conn.setDoOutput(true);
            conn.setDoInput(true);
            try (
                PrintWriter out = new PrintWriter(conn.getOutputStream())
            ){
                out.print(param);
                out.flush();
            }
            try (
                BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"))
            ){
                String line;
                while ((line = in.readLine()) != null) {
                    result += "\n" + line;
                }
            }
        } catch (Exception e) {
            System.out.println(e);
            e.printStackTrace();
        }
        return result;
    }

    // 生成md5串
    public static String getMD5str(Long appid, String timestamp, String serverSecret) {
        String plaintext = appid + timestamp + serverSecret;
        String md5str = "";
        StringBuffer hexStr = new StringBuffer();
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] plaintextByte = plaintext.getBytes("UTF-8");
            byte[] md5_byte = md.digest(plaintextByte);
            int num;
            for (int i = 0; i < md5_byte.length; i++) {
                num = md5_byte[i];
                if(num < 0) {
                    num += 256;
                }
                if(num < 16){
                    hexStr.append("0");
                }
                hexStr.append(Integer.toHexString(num));
            }

        } catch (Exception e) {
            System.out.println("erro md5 creat!!!!");
            e.printStackTrace();
        }
        md5str = hexStr.toString();
        return md5str;
    }

    //构造mixinput的数据(数组)
    public static LinkedHashMap[] getMixInputData_array(String inputStreamId1, String inputStreamId2){

        LinkedHashMap<String,Object> mixInput_stream1_rect_map = new LinkedHashMap<>();
        mixInput_stream1_rect_map.put("layer",0);
        mixInput_stream1_rect_map.put("top",0);
        mixInput_stream1_rect_map.put("left",0);
        mixInput_stream1_rect_map.put("bottom",640);
        mixInput_stream1_rect_map.put("right",480);

        LinkedHashMap<String,Object> mixInput_stream1_map = new LinkedHashMap<>();
        mixInput_stream1_map.put("url","");
        mixInput_stream1_map.put("stream_id",inputStreamId1);
        mixInput_stream1_map.put("rect",mixInput_stream1_rect_map);

        LinkedHashMap<String,Object> mixInput_stream2_rect_map = new LinkedHashMap<>();
        mixInput_stream2_rect_map.put("layer",1);
        mixInput_stream2_rect_map.put("top",480);
        mixInput_stream2_rect_map.put("left",320);
        mixInput_stream2_rect_map.put("bottom",640);
        mixInput_stream2_rect_map.put("right",480);

        LinkedHashMap<String,Object> mixInput_stream2_map = new LinkedHashMap<>();
        mixInput_stream2_map.put("url","");
        mixInput_stream2_map.put("stream_id",inputStreamId2);
        mixInput_stream2_map.put("rect",mixInput_stream2_rect_map);

        LinkedHashMap[] mixInput_array = {mixInput_stream1_map,mixInput_stream2_map};
        return mixInput_array;
    }

    //构造mixoutput的数据(数组)
    public static LinkedHashMap[] getMixOutputData_array(String outputStreamId, String cdnURL){
        LinkedHashMap<String,Object> mixOutput_map = new LinkedHashMap<>();
        mixOutput_map.put("stream_id", outputStreamId);
        mixOutput_map.put("mixurl", cdnURL + outputStreamId);
        mixOutput_map.put("bitrate", 400000);
        mixOutput_map.put("fps", 15);
        mixOutput_map.put("height", 640);
        mixOutput_map.put("width", 480);
        LinkedHashMap[] mixOutput_array = {mixOutput_map};
        return mixOutput_array;
    }

    public static void main(String args[]) throws Exception{

        // zego分配的appid
        Long appid = 123456789L;
        // 从zego获取的serverSecret
        String serverSecret = "00000000000000000000000000000000";
        // 发起混流的id_name
        String id_name = "xxx";
        // 混流的roomid
        String live_channel = "xxxx";
        // 输入流的流id
        String inputStreamId1 = "is1"; // 注意如果为测试环境,流id为 "zegotest-" + appid + "-is1"
        String inputStreamId2 = "is2"; // 注意如果为测试环境,流id为 "zegotest-" + appid + "-is2"
        // 输出的混流流id
        String outputStreamId = "os"; //注意如果为测试环境,流id为 "zegotest-" + appid + "-os"
        // cdn的推流地址
        String cdnURL = "rtmp://127.0.0.1/xxx/"; 
        // md5加密所需的时间戳
        String timestamp = Long.toString(System.currentTimeMillis()/1000);
        // 请求混流的url,注意正式环境与测试环境的区别, url中包含的access_token参考 "获取Access Token"
        String startMixStream_url = "https://testwebapi.zego.im/cgi/start-mix?access_token=";

        //获取md5字符串
        String md5str = getMD5str(appid, timestamp, serverSecret);

        // 构造生成mixInput_str的字符串和mixOutput_str的字符串, 需要做urlencode
        LinkedHashMap[] mixInput_array = getMixInputData_array(inputStreamId1, inputStreamId2);
        LinkedHashMap[] mixOutput_array = getMixOutputData_array(outputStreamId, cdnURL);

        LinkedHashMap<String,Object> postJsonData = new LinkedHashMap<>();
        postJsonData.put("signature", md5str);
        postJsonData.put("id_name", id_name);
        postJsonData.put("live_channel", live_channel);
        postJsonData.put("appid", appid);
        postJsonData.put("MixInput", mixInput_array);
        postJsonData.put("MixOutput", mixOutput_array);

        String post_json_str = JSONObject.toJSONString(postJsonData);
        System.out.println(post_json_str);

        // 发送请求开始混流, access_token 参考 "获取Access Token" 部分
        String ret = StartMixStream.sendPost(startMixStream_url + access_token, post_json_str);
        System.out.println(ret);

    }
}

5.2 php示例代码

<?php
$token = 'xxxxxxxx';

//// 注意如果为测试环境,MixInput的stream_id为 "zegotest-" + appid + "xxxxx",MixOutput的stream_id为"zegotest-" + appid + "xxxxx".

$json = '{"appid":123456789,"id_name":"xxx","signature":"xxxx","live_channel":"xxxxx","audio_channel_cnt":0,"output_bg_color":0,"output_bg_image":"","output_audio_bitrate":0,"with_sound_level":0,"UserData":"","seq":0,"version":1,"MixInput":[{"url":"","stream_id":"xxxxxxxx","sound_level_id":0,"content_control":0,"rect":{"layer":0,"top":0,"left":0,"bottom":1,"right":1}}],"MixOutput":[{"stream_id":"xxxxx","mixurl":"xxxxxxxx","bitrate":1,"fps":1,"height":1,"width":1,"audio_channel_cnt":0,"audio_enc_id":0,"audio_bitrate":0,"encode_mode":null,"encode_qua":null,"output_bg_color":0,"output_bg_image":""}],"task_id":"","watermark":null,"bypass":null}';
$ch = curl_init();
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_URL, 'https://testwebapi.zego.im/cgi/start-mix?access_token=' . $token);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Content-Type: application/json; charset=utf-8',
        'Content-Length: ' . strlen($json)
    )
);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

$result = array($httpCode, $response);

print_r($result);

?>

5.3 curl请求示例

 curl -X POST http://106.15.219.49/cgi/start-mix?access_token=VlhXbXp1eWxhZFd6azZzTitTS3M0aWNGa3d3ZFRveU5FbjlRWTF4VXl6bU5EQkpQZ2l2d1ZobTdPdHo5dUd0WQ  -d '{"appId": 3828875002,"id_name":"test_mix","task_id":"task1","timestamp":1562052086857,"signature":"d4507c4cc277dfb9893057dd9031caae","MixInput":[{"url":"avertp://39.108.212.3/miniapp/mix-input-test-1000yanglei","rect":{"layer":1,"top":320,"left":180,"bottom":640,"right":360}}],"mixOutput":[{"mixurl":"avertp://39.108.212.3/miniapp/mix-output-test-1000yanglei","bitrate":400000,"fps":15,"height":1024,"width":840}],"output_bg_image":"preset-id://liveme-bg"}'