logo
Voice Call
Server API
Stream Mixing and Transcoding APIs
On this page

Quick Start


Introduction

ZEGO cloud communication products (real-time audio and video, real-time voice, etc.) provide multiple server-side API interfaces that support developers in sending requests to ZEGO servers to implement a series of backend services such as room signaling, media services, and audio/video stream mixing. Developers can call server-side APIs using GET or POST methods by initiating HTTPS network requests to interact with ZEGO servers.

This article uses "How to call a server-side API interface" as an example to help developers quickly understand the usage of various server-side API interfaces.

Prerequisites

Before calling server-side API interfaces, make sure that:

  • You have created a project in the ZEGOCLOUD Console and applied for a valid AppId and ServerSecret. For details, please refer to "Project Information" in Console - Project Management.
  • You have prepared a development environment for debugging server-side API interfaces
  • You have prepared your own client and set up relevant business scenarios. For example, before calling the server-side API interface Start Mix, developers need to initiate audio/video publishing and playing in the Room through their own client.

GET Request Example Code

ZEGO provides sample code in multiple programming languages for developers to reference. Taking the Describe User Number interface as an example to send a GET request to the ZEGO server:

package main

import (
	"crypto/md5"
	"crypto/rand"
	"encoding/hex"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"time"
)

//Please modify AppId to your AppId, AppId is uint32
//Example: 1234567890
var appId uint32 = 1234567890

//Please modify serverSecret to your serverSecret, serverSecret is string
//Example: "abcde1234aaaaaaaabbbbbbb"
var serverSecret =

func main() {
	queryParams := url.Values{}
	roomId := "room1"
	queryParams.Add("RoomId[]", roomId)

	timestamp := time.Now().Unix()
    // Generate 16-digit hexadecimal random string (16 bits)
	nonce := make([]byte, 8)
	rand.Read(nonce)
	hexNonce := hex.EncodeToString(nonce)
    // Generate signature
	signature := generateSignature(appId, serverSecret, hexNonce, timestamp)
	authParams := url.Values{}
	authParams.Set("AppId", fmt.Sprintf("%d", appId))
    // The random number in public parameters must be consistent with the random number used to generate the signature
	authParams.Set("SignatureNonce", hexNonce)
	authParams.Set("SignatureVersion", "2.0")
    // The timestamp in public parameters must be consistent with the timestamp used to generate the signature
	authParams.Set("Timestamp", fmt.Sprintf("%d", timestamp))
	authParams.Set("Signature", signature)
	// rtc-api.zego.im indicates that the product used is the cloud communication product, including real-time audio and video (Express Video), real-time audio (Express Audio), and low-latency live (L3)
    // The following example calls the "DescribeUserNum" API to get the number of users in the Room with RoomId room1
	addr := fmt.Sprintf("https://rtc-api.zego.im?Action=DescribeUserNum&%s&%s", authParams.Encode(), queryParams.Encode())
	rsp, err := http.Get(addr)
	if err != nil {
		fmt.Printf("http.Get err:%+v", err)
		return
	}
	defer rsp.Body.Close()
	body, err := ioutil.ReadAll(rsp.Body)
	if err != nil {
		fmt.Printf("ioutil.ReadAll err:%+v", err)
		return
	}
	fmt.Printf("body:%+v", string(body))
}

// Generate signature
// Signature=md5(AppId + SignatureNonce + ServerSecret + Timestamp)
func generateSignature(appId uint32, serverSecret, signatureNonce string, timeStamp int64) string {
	data := fmt.Sprintf("%d%s%s%d", appId, signatureNonce, serverSecret, timeStamp)

	h := md5.New()
	h.Write([]byte(data))
	return hex.EncodeToString(h.Sum(nil))
}
# -*- coding: UTF-8 -*-
import hashlib
import secrets
import time


from urllib.parse import urlencode

import requests

# Generate signature
# Signature=md5(AppId + SignatureNonce + ServerSecret + Timestamp)
def GenerateSignature(appId, signatureNonce, serverSecret, timestamp):
    str1 = str(appId) + signatureNonce + serverSecret + str(timestamp)
    hash = hashlib.md5()
    hash.update(str1.encode("utf8"))
    signature = hash.hexdigest()
    return signature


if __name__ == '__main__':
    # Please modify appId to your AppId, AppId is a number
    # Example: 1234567890
    appId = 1234567890
    # Please modify serverSecret to your serverSecret, serverSecret is string
    # Example: "abcde1234aaaaaaaabbbbbbb"
    serverSecret =
    # Generate random number
    signatureNonce = secrets.token_hex(8)

    timestamp = int(time.time())
    # Generate signature
    sig = GenerateSignature(appId, signatureNonce, serverSecret, timestamp)

    # The following example calls the "DescribeUserNum" API to get the number of users in the Room with RoomId room1
    par = {
        "Action": "DescribeUserNum",
        "AppId": appId,
        "Signature": sig,
        "SignatureNonce": signatureNonce, # The timestamp in public parameters must be consistent with the timestamp used to generate the signature
        "SignatureVersion": "2.0",
        "Timestamp": timestamp, # The timestamp in public parameters must be consistent with the timestamp used to generate the signature
        "RoomId[]": "room1"
    }
    url = 'https://rtc-api.zego.im/'
    req = requests.get(url, params=par)
    print("Url: ", req.url)
    print("StatusCode: ", req.status_code)
    print("Respone: ", req.text)
Get Room User Count (Java)
package org.example;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Map;

public class DescribeUserNum {

    public static void main(String[] args) {
        // Get the number of users in the Room
        describeUserNum();
    }

    /**
     * Test getting the number of users in the Room
     */
    public static void describeUserNum() {
        // Please fill in the Room ID you want to count
        String roomId = "room1";
        // Please fill in the APP ID you obtained from the console,
        // Example: 1234567890L, APP_ID is of Long type
        Long APP_ID = 1234567890L;
        // Please fill in the SERVER SECRET you obtained from the console,
        // Example: "abcde1234aaaaaaaabbbbbbb"
        String SERVER_SECRET = ;
        // Generate 16-digit hexadecimal random string (16 bits)
        byte[] bytes = new byte[8];
        SecureRandom sr = new SecureRandom();
        sr.nextBytes(bytes);
        String signatureNonce = bytesToHex(bytes);
        // Set timestamp
        long timestamp = System.currentTimeMillis() / 1000L;

        // Generate signature Signature=md5(AppId + SignatureNonce + ServerSecret + Timestamp)
        String signatue = generateSignature(APP_ID, signatureNonce, SERVER_SECRET, timestamp);

        // Assemble request URL
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("Action", "DescribeUserNum");
        params.put("RoomId[]", roomId);
        params.put("AppId", APP_ID);
        // The random number in public parameters must be consistent with the random number used to generate the signature
        params.put("SignatureNonce", signatureNonce);
        // The timestamp in public parameters must be consistent with the timestamp used to generate the signature
        params.put("Timestamp", timestamp);
        params.put("Signature", signatue);
        params.put("SignatureVersion", "2.0");
        String url = buildAPIUrl("https://rtc-api.zego.im/", params);

        String result = sendGet(url);
        System.out.println(result);
    }

    /**
     * Generate signature
     * @param appId Application AppId
     * @param signatureNonce Signature random code
     * @param serverSecret Server-side API key
     * @param timestamp Signature timestamp
     * @return Generated signature string
     */
    public static String generateSignature(long appId, String signatureNonce, String serverSecret, long timestamp){
        String str = String.valueOf(appId) + signatureNonce + serverSecret + String.valueOf(timestamp);
        String signature = "";
        try{
            //Create an object that provides the message digest algorithm, initialized as an md5 algorithm object
            MessageDigest md = MessageDigest.getInstance("MD5");
            //Calculate to get byte array
            byte[] bytes = md.digest(str.getBytes("utf-8"));
            //Convert each byte of the array to hexadecimal and concatenate into md5 string
            signature = bytesToHex(bytes);
        }catch (Exception e) {
            e.printStackTrace();
        }
        return signature;
    }

    /**
     * Convert byte array to hexadecimal
     * @param bytes The byte array to be converted
     * @return Converted Hex string
     */
    public static String bytesToHex(byte[] bytes) {
        StringBuffer md5str = new StringBuffer();
        //Convert each byte of the array to hexadecimal and concatenate into md5 string
        int digital;
        for (int i = 0; i < bytes.length; i++) {
            digital = bytes[i];
            if (digital < 0) {
                digital += 256;
            }
            if (digital < 16) {
                md5str.append("0");
            }
            md5str.append(Integer.toHexString(digital));
        }
        return md5str.toString();
    }

    /**
     * Send HTTP-GET request
     * @param httpurl Request path
     * @return Response content
     */
    public static String sendGet(String httpurl) {
        HttpURLConnection connection = null;
        InputStream is = null;
        BufferedReader br = null;
        String result = null;// Return result string
        try {
            // Create remote URL connection object
            URL url = new URL(httpurl);
            // Open a connection through the remote URL connection object and cast it to HttpURLConnection class
            connection = (HttpURLConnection) url.openConnection();
            // Set connection method: get
            connection.setRequestMethod("GET");
            // Set connection timeout to host server: 15000 milliseconds
            connection.setConnectTimeout(15000);
            // Set timeout for reading remote return data: 60000 milliseconds
            connection.setReadTimeout(60000);
            // Send request
            connection.connect();
            // Get input stream through connection connection
            if (connection.getResponseCode() == 200) {
                is = connection.getInputStream();
                // Encapsulate input stream is and specify character set
                br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                // Store data
                StringBuffer sbf = new StringBuffer();
                String temp = null;
                while ((temp = br.readLine()) != null) {
                    sbf.append(temp);
                    sbf.append("\r\n");
                }
                result = sbf.toString();
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // Close resources
            if (null != br) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != is) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            connection.disconnect();// Close remote connection
        }
        return result;
    }
    /**
     * Assemble API address string
     * @param url API address
     * @param params Request parameters
     * @return Assembled API address string
     */
    public static String buildAPIUrl(String url, Map<String, Object> params) {
        if(params.isEmpty()) {
            return url;
        }
        StringBuffer buffer = new StringBuffer(url).append("?");
        for(String key : params.keySet()) {
            buffer.append(key).append("=").append(params.get(key)).append("&");
        }
        String apiurl = buffer.toString();
        if(apiurl.endsWith("&")) {
            return apiurl.substring(0, apiurl.length()-1);
        } else {
            return apiurl;
        }
    }

}
<?php
/**
 * Simplest example code to get the number of users in room room1
 */

//Please modify appId to your AppId
//Example: 1234567890
$appId = 1234567890;
//Please modify serverSecret to your serverSecret, serverSecret is a string
//Example: "1234567890bbc111111da999ef05f0ee"
$serverSecret = ;

//Generate signature
//Signature=md5(AppId + SignatureNonce + ServerSecret + Timestamp)
function GenerateSignature($appId, $signatureNonce, $serverSecret, $timeStamp){
    $str = $appId . $signatureNonce . $serverSecret . $timeStamp;
    //Use the standard MD5 algorithm in PHP, which returns a 32-character hexadecimal number by default
    return md5($str);
}

//Get random string and convert to hexadecimal value
$signatureNonce = bin2hex(random_bytes(8));

//Get millisecond-level timestamp
list($msec, $sec) = explode(' ', microtime());
$msecTime = (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
//Round $msecTime to get the second-level timestamp
$timeStamp = round($msecTime/1000);
// Generate signature
// The Timestamp used when generating the signature must be consistent with the Timestamp in the url parameter, and the SignatureNonce used when generating the signature must also be consistent with the SignatureNonce in the url parameter
$sig = GenerateSignature($appId, $signatureNonce, $serverSecret, $timeStamp);

//The following example calls the "DescribeUserNum" API to get the number of users in the Room with RoomID room1
$url = "https://rtc-api.zego.im/?Action=DescribeUserNum&RoomId[]=room1&AppId=$appId&SignatureNonce=$signatureNonce&Timestamp=$timeStamp&Signature=$sig&SignatureVersion=2.0&IsTest=false";

//Use curl library
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//Set request connection timeout, unit: seconds
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
$response = curl_exec($ch);
curl_close($ch);
//Requested url
echo "Url: " . $url ."\r\n";
//Returned result
echo "response:" . $response;
const crypto = require('crypto');
const request = require('request');

//Please modify appId to your AppId, AppId is number
var appId = 1234567890;
//Please modify serverSecret to your serverSecret, serverSecret is string
//Example: "1234567890bbc111111da999ef05f0ee"
var serverSecret = ;

//Generate signature
//Signature=md5(AppId + SignatureNonce + ServerSecret + Timestamp)
function GenerateUASignature(appId, signatureNonce, serverSecret, timeStamp){
    const hash = crypto.createHash('md5'); //Specify using MD5 algorithm in hash algorithm
    var str = appId + signatureNonce + serverSecret + timeStamp;
    hash.update(str);
    //hash.digest('hex') indicates the output format is hexadecimal
    return hash.digest('hex');
}

var signatureNonce = crypto.randomBytes(8).toString('hex');
var timeStamp = Math.round(Date.now()/1000);
// Generate signature
// The Timestamp used when generating the signature must be consistent with the Timestamp in the url parameter, and the SignatureNonce used when generating the signature must also be consistent with the SignatureNonce in the url parameter
var sig = GenerateUASignature(appId, signatureNonce, serverSecret, timeStamp)
// rtc-api.zego.im indicates that the product used is the cloud communication product, including real-time audio and video (Express Video), real-time audio (Express Audio), and low-latency live (L3)
//The following example can get the number of users in the Room with RoomID room1
var url = `https://rtc-api.zego.im/?Action=DescribeUserNum&RoomId[]=room1&AppId=${appId}&SignatureNonce=${signatureNonce}&Timestamp=${timeStamp}&Signature=${sig}&SignatureVersion=2.0&IsTest=false`;

request(url, function(error, response, body){
    console.log('Url: ',url)
    console.log('StatusCode: ',response.statusCode)
    console.log('Error: ', error)
    if(!error && response.statusCode){
        console.log(body)
    }
})

POST Request Example Code

ZEGO provides sample code in multiple programming languages for developers to reference. We take Start Mix as an example to send a POST request to the ZEGO server.

package main

import (
	"bytes"
	"crypto/md5"
	"crypto/rand"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
	"time"
)
// rtc-api.zego.im indicates that the product used is the cloud communication product, including real-time audio and video (Express Video), real-time audio (Express Audio), and low-latency live (L3)
const DOMAIN = "https://rtc-api.zego.im"

var (
	//Please modify AppId to your AppId, AppId is uint32
	//Example: 1234567890
	AppId uint32 = 1234567890
	//Please modify serverSecret to your serverSecret, serverSecret is string
	Secret = ""
)

type MixStartRequest struct {
	Appid     uint64       `json:"Appid"`
	UserId    string       `json:"UserId"`
	Sequence  int64        `json:"Sequence"`
	MixInput  []*MixInput  `json:"MixInput"`
	MixOutput []*MixOutput `json:"MixOutput"`
	MixTaskId string       `json:"TaskId"`
}

type RectInfo struct {
	Top    int32 `json:"Top"`
	Left   int32 `json:"Left"`
	Bottom int32 `json:"Bottom"`
	Right  int32 `json:"Right"`
}

type MixInput struct {
	StreamId  string    `json:"StreamId"`
	RectInfo  *RectInfo `json:"RectInfo"`
}

type MixOutput struct {
	StreamId     string `json:"StreamId"`
	VideoBitrate int32  `json:"VideoBitrate"`
	Fps          int32  `json:"Fps"`
	Height       int32  `json:"Height"`
	Width        int32  `json:"Width"`
}

func main() {
	nonce := make([]byte, 8)
	rand.Read(nonce)
	hexNonce := hex.EncodeToString(nonce)
	ts := time.Now()
	signature := GenerateSignature(AppId, hexNonce, Secret, ts.Unix())
	value := url.Values{}
	value.Add("AppId", strconv.FormatUint(AppId, 10))
	value.Add("SignatureNonce", hexNonce)
	value.Add("Timestamp", strconv.FormatInt(ts.Unix(), 10))
	value.Add("Signature", signature)
	value.Add("Action", "StartMix")
	value.Add("SignatureVersion", "2.0")
	urlData, err := url.Parse(DOMAIN)
	if err != nil {
		fmt.Println(err)
		return
	}
	urlData.RawQuery = value.Encode()
	dataJson, _ := json.Marshal(GenerateStartMixData())
	req, err := http.NewRequest("POST", urlData.String(), bytes.NewBuffer(dataJson))
	if err != nil {
		fmt.Println(err)
		return
	}
	req.Header.Set("Content-Type", "application/json")
	req.Close = true
	client := &http.Client{}
	r, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return
	}
	if r.StatusCode != 200 {
		fmt.Printf("status code is:%v", r.StatusCode)
	}
	defer r.Body.Close()
	resp, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return
	}
	fmt.Println(string(resp))
	return
}

//The following example mixes the audio and video stream with streamId "stream1" with the audio and video stream with streamId "stream2" to output the audio and video stream with streamId "stream3"
func GenerateStartMixData() *MixStartRequest {
	inputs := make([]*MixInput, 0)
	input1 := MixInput{
		StreamId: "stream1",
		RectInfo: &RectInfo{
			Top:    70,
			Left:   100,
			Bottom: 160,
			Right:  260,
		},
	}
	inputs = append(inputs, &input1)
	input2 := MixInput{
		StreamId: "stream2",
		RectInfo: &RectInfo{
			Top:    200,
			Left:   100,
			Bottom: 290,
			Right:  260,
		},
	}
	inputs = append(inputs, &input2)
	output := MixOutput{
		StreamId:     "stream3",
		VideoBitrate: 12000,
		Fps:          15,
		Height:       360,
		Width:        360,
	}
	outputs := append([]*MixOutput{}, &output)
	req := &MixStartRequest{
		Appid:     AppId,
		UserId:    "123",
		Sequence:  123,
		MixInput:  inputs,
		MixOutput: outputs,
		MixTaskId: "123",
	}
	return req
}

//Signature=md5(AppId + SignatureNonce + ServerSecret + Timestamp)
func GenerateSignature(appid uint64, nonce string, appSecret string, timestamp int64) (signature string) {
	data := fmt.Sprintf("%d%s%s%d", appid, nonce, appSecret, timestamp)
	h := md5.New() //Specify using MD5 algorithm in hash algorithm
	h.Write([]byte(data))
	//hex.EncodeToString(h.Sum(nil)) outputs hexadecimal string
	return hex.EncodeToString(h.Sum(nil))
}
# -*- coding: UTF-8 -*-
import hashlib
import secrets
import time

# Generate signature
# Signature=md5(AppId + SignatureNonce + ServerSecret + Timestamp)
from urllib.parse import urlencode

import requests


def GenerateSignature(appId, signatureNonce, serverSecret, timestamp):
    str1 = str(appId) + signatureNonce + serverSecret + str(timestamp)
    hash = hashlib.md5()
    hash.update(str1.encode("utf8"))
    signature = hash.hexdigest()
    return signature


if __name__ == '__main__':
    # Please modify appId to your AppId, AppId is a number
    # Example: 1234567890
    appId = 1234567890
    # Please modify serverSecret to your serverSecret, serverSecret is string
    serverSecret = ""

    signatureNonce = secrets.token_hex(8)
    timestamp = int(time.time())
    sig = GenerateSignature(appId, signatureNonce, serverSecret, timestamp)

    # The following example mixes the audio and video stream with streamId "stream1" with the audio and video stream with streamId "stream2" to output the audio and video stream with streamId "stream3"
    par = {
        "Action": "StartMix",
        "AppId": appId,
        "Signature": sig,
        "SignatureNonce": signatureNonce,
        "SignatureVersion": "2.0",
        "Timestamp": timestamp,
        "IsTest": "False"
    }
    body = {
        'TaskId': '123',
        'Sequence': 123,
        'UserId': '123',
        'MixInput': [
            {
                'StreamId': 'stream1',
                'RectInfo': {
                    "Top": 70,
                    "Bottom": 160,
                    "Left": 100,
                    "Right": 260,
                },

            },
            {
                'StreamId': 'stream2',
                'RectInfo': {
                    "Top": 200,
                    "Bottom": 290,
                    "Left": 100,
                    "Right": 260,
                },
            }
        ],
        'MixOutput': [{
            'StreamId': 'stream3',
            'Width': 360,
            'Height': 360,
            'VideoBitrate': 12000,
            'Fps': 15
        }]
    }
    url = 'https://rtc-api.zego.im/'
    req = requests.post(url, params=par, json=body)
    print("Url: ", req.url)
    print("StatusCode", req.status_code)
    print("Respone:", req.text)
Start Mix (Java)
package org.example;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Map;

/**
 * Please first import com.alibaba.fastjson to facilitate building request body parameters
 */
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

public class StartMix {

    //
    public static void main(String[] args) {
        // Start stream mixing
        startMixStream();
    }

    /**
     * Start stream mixing
     */
    public static void startMixStream() {
        // Please fill in the APP ID you obtained from the console,
        // Example: 1234567890L
        Long APP_ID = 1234567890L;
        // Please fill in the SERVER SECRET you obtained from the console,
        // Example: "abcde1234aaaaaaaabbbbbbb"
        String SERVER_SECRET = ;
        // Generate 16-digit hexadecimal random string (16 bits)
        byte[] bytes = new byte[8];
        SecureRandom sr = new SecureRandom();
        sr.nextBytes(bytes);
        String signatureNonce = bytesToHex(bytes);
        // Set timestamp
        long timestamp = System.currentTimeMillis() / 1000L;

        // Generate signature Signature=md5(AppId + SignatureNonce + ServerSecret + Timestamp)
        String signatue = generateSignature(APP_ID, signatureNonce, SERVER_SECRET, timestamp);

        // Assemble request URL
        //The following example mixes the audio and video stream with streamId "stream1" with the audio and video stream with streamId "stream2" to output the audio and video stream with streamId "stream3"
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("Action", "StartMix");
        params.put("AppId", APP_ID);
        params.put("SignatureNonce", signatureNonce);
        params.put("Timestamp", timestamp);
        params.put("Signature", signatue);
        params.put("SignatureVersion", "2.0");
        // rtc-api.zego.im 表示使用的产品是云通讯产品,包括了实时音视频(Express Video)、实时音频(Express Audio)、低延迟直播(L3)
        String url = buildAPIUrl("https://rtc-api.zego.im/", params);

        JSONObject body = new JSONObject()
                .fluentPut("TaskId", "123")
                .fluentPut("Sequence", 123)
                .fluentPut("UserId", "123");

        JSONArray mixInputList = new JSONArray();
        mixInputList.add(new JSONObject()
                .fluentPut("StreamId", "stream1")
                .fluentPut("RectInfo", new JSONObject()
                        .fluentPut("Top", 70)
                        .fluentPut("Bottom", 160)
                        .fluentPut("Left", 100)
                        .fluentPut("Right", 260)));
        mixInputList.add(new JSONObject()
                .fluentPut("StreamId", "stream2")
                .fluentPut("RectInfo", new JSONObject()
                        .fluentPut("Top", 200)
                        .fluentPut("Bottom", 290)
                        .fluentPut("Left", 100)
                        .fluentPut("Right", 260)));
        body.put("MixInput", mixInputList);

        JSONArray mixOutputList = new JSONArray();
        mixOutputList.add(new JSONObject()
                .fluentPut("StreamId", "stream3")
                .fluentPut("Width", 360)
                .fluentPut("Height", 360)
                .fluentPut("VideoBitrate", 12000)
                .fluentPut("Fps", 15));
        body.put("MixOutput", mixOutputList);

        String result = sendPost(url, body.toString());
        System.out.println(result);
    }

    /**
     * Generate signature
     * @param appId Application AppId
     * @param signatureNonce Signature random code
     * @param serverSecret Server-side API key
     * @param timestamp Signature timestamp
     * @return Generated signature string
     */
    public static String generateSignature(long appId, String signatureNonce, String serverSecret, long timestamp){
        String str = String.valueOf(appId) + signatureNonce + serverSecret + String.valueOf(timestamp);
        String signature = "";
        try{
            //Create an object that provides the message digest algorithm, initialized as an md5 algorithm object
            MessageDigest md = MessageDigest.getInstance("MD5");
            //Calculate to get byte array
            byte[] bytes = md.digest(str.getBytes("utf-8"));
            //Convert each byte of the array to hexadecimal and concatenate into md5 string
            signature = bytesToHex(bytes);
        }catch (Exception e) {
            e.printStackTrace();
        }
        return signature;
    }

    /**
     * Convert byte array to hexadecimal
     * @param bytes The byte array to be converted
     * @return Converted Hex string
     */
    public static String bytesToHex(byte[] bytes) {
        StringBuffer md5str = new StringBuffer();
        //Convert each byte of the array to hexadecimal and concatenate into md5 string
        int digital;
        for (int i = 0; i < bytes.length; i++) {
            digital = bytes[i];
            if (digital < 0) {
                digital += 256;
            }
            if (digital < 16) {
                md5str.append("0");
            }
            md5str.append(Integer.toHexString(digital));
        }
        return md5str.toString();
    }

    /**
     * Send HTTP-GET request
     * @param httpurl Request path
     * @return Response content
     */
    public static String sendGet(String httpurl) {
        HttpURLConnection connection = null;
        InputStream is = null;
        BufferedReader br = null;
        String result = null;// Return result string
        try {
            // Create remote URL connection object
            URL url = new URL(httpurl);
            // Open a connection through the remote URL connection object and cast it to HttpURLConnection class
            connection = (HttpURLConnection) url.openConnection();
            // Set connection method: get
            connection.setRequestMethod("GET");
            // Set connection timeout to host server: 15000 milliseconds
            connection.setConnectTimeout(15000);
            // Set timeout for reading remote return data: 60000 milliseconds
            connection.setReadTimeout(60000);
            // Send request
            connection.connect();
            // Get input stream through connection connection
            if (connection.getResponseCode() == 200) {
                is = connection.getInputStream();
                // Encapsulate input stream is and specify character set
                br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                // Store data
                StringBuffer sbf = new StringBuffer();
                String temp = null;
                while ((temp = br.readLine()) != null) {
                    sbf.append(temp);
                    sbf.append("\r\n");
                }
                result = sbf.toString();
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // Close resources
            if (null != br) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != is) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            connection.disconnect();// Close remote connection
        }
        return result;
    }

    /**
     * Send HTTP-POST request
     * @param param Message body parameter
     * @return Response content
     */
    public static String sendPost(String httpUrl, String param) {
        HttpURLConnection connection = null;
        InputStream is = null;
        OutputStream os = null;
        BufferedReader br = null;
        String result = null;
        try {
            URL url = new URL(httpUrl);
            // Open connection through remote URL connection object
            connection = (HttpURLConnection) url.openConnection();
            // Set connection request method
            connection.setRequestMethod("POST");
            // Set connection timeout to host server: 15000 milliseconds
            connection.setConnectTimeout(15000);
            // Set timeout for reading host server return data: 60000 milliseconds
            connection.setReadTimeout(60000);
            // Default value: false, must be set to true when transmitting/writing data to remote server
            connection.setDoOutput(true);
            // Default value: true, set to true when reading data from remote service, this parameter is optional
            connection.setDoInput(true);
            // Set the format of incoming parameters: request parameters should be in the form of name1=value1&name2=value2
            connection.setRequestProperty("Content-Type", "application/json");
            // Establish connection
            connection.connect();
            // Get an output stream object through the connection object
            OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream(),"UTF-8");
            writer.write(param);
            writer.flush();
            // Get an input stream through the connection object to read remotely
            if (connection.getResponseCode() == 200) {
                is = connection.getInputStream();
                // Wrap the input stream object: charset is set according to the requirements of the project team
                br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                StringBuffer sbf = new StringBuffer();
                String temp = null;
                // Loop to read data line by line
                while ((temp = br.readLine()) != null) {
                    sbf.append(temp);
                    sbf.append("\r");
                }
                result = sbf.toString();
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // Close resources
            if (null != br) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != os) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != is) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            // Disconnect from remote URL
            connection.disconnect();
        }
        return result;
    }

    /**
     * Assemble API address string
     * @param url API address
     * @param params Request parameters
     * @return Assembled API address string
     */
    public static String buildAPIUrl(String url, Map<String, Object> params) {
        if(params.isEmpty()) {
            return url;
        }
        StringBuffer buffer = new StringBuffer(url).append("?");
        for(String key : params.keySet()) {
            buffer.append(key).append("=").append(params.get(key)).append("&");
        }
        String apiurl = buffer.toString();
        if(apiurl.endsWith("&")) {
            return apiurl.substring(0, apiurl.length()-1);
        } else {
            return apiurl;
        }
    }

}
<?php

/**
 * Simplest example code to initiate stream mixing
 */

//Please modify appId to your AppId
//Example: 1234567890
$appId = 1234567890;
//Please modify serverSecret to your serverSecret, serverSecret is string
$serverSecret = "";

//Generate signature
//Signature=md5(AppId + SignatureNonce + ServerSecret + Timestamp)
function GenerateSignature($appId, $signatureNonce, $serverSecret, $timeStamp){
    $str = $appId . $signatureNonce . $serverSecret . $timeStamp;
    //Use the standard MD5 algorithm in PHP, which returns a 32-character hexadecimal number by default
    return md5($str);
}

//Get random string and convert to hexadecimal value
$signatureNonce = bin2hex(random_bytes(8));

//Get millisecond-level timestamp
list($msec, $sec) = explode(' ', microtime());
$msecTime = (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
//Round $msecTime to get the second-level timestamp
$timeStamp = round($msecTime/1000);
$sig = GenerateSignature($appId, $signatureNonce, $serverSecret, $timeStamp);

//The following example mixes the audio and video stream with streamId "stream1" with the audio and video stream with streamId "stream2" to output the audio and video stream with streamId "stream3"
$url = "https://rtc-api.zego.im/?Action=StartMix&AppId=$appId&SignatureNonce=$signatureNonce&Timestamp=$timeStamp&Signature=$sig&SignatureVersion=2.0&IsTest=false";

$body = [
    "TaskId"   => "123",
    "Sequence" => 123,
    "UserId"   => "123",
    "MixInput" => [
        [
            "StreamId" => "stream1",
            "RectInfo" => [
            "Top"    => 70,
                "Bottom" => 160,
                "Left"   => 100,
                "Right"  => 260,
            ],
        ],
        [
            "StreamId" => "stream2",
            "RectInfo" => [
            "Top"    => 200,
                "Bottom" => 290,
                "Left"   => 100,
                "Right"  => 260,
            ],
        ]
    ],
    "MixOutput" => [
        [
            "StreamId" => "stream3",
            "Width"    => 360,
            "Height"   => 360,
            "VideoBitrate" => 12000,
            "Fps"      => 15
        ]
    ]
];

$post_string = json_encode($body);

$ch = curl_init();

curl_setopt ($ch, CURLOPT_URL, $url);
curl_setopt ($ch, CURLOPT_POST, 1);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
//Set request connection timeout, unit: seconds
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_string);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Content-Type: application/json; charset=utf-8',
    )
);
$response = curl_exec($ch);
curl_close($ch);

echo "Url:" . $url;
echo "\r\n";
echo "request body:" . $post_string;
echo "\r\n";
echo "response:" . $response;
const crypto = require('crypto');
const request = require('request');

//Please modify appId to your AppId, AppId is number
var appId = ;
//Please modify serverSecret to your serverSecret, serverSecret is string
var serverSecret = "";

//Signature=md5(AppId + SignatureNonce + ServerSecret + Timestamp)
function GenerateSignature(appId, signatureNonce, serverSecret, timeStamp) {
    const hash = crypto.createHash('md5'); //Specify using MD5 algorithm in hash algorithm
    var str = appId + signatureNonce + serverSecret + timeStamp;
    hash.update(str);
    //hash.digest('hex') indicates the output format is hexadecimal
    return hash.digest('hex');
}

var signatureNonce = crypto.randomBytes(8).toString('hex');
var timeStamp = Math.round(Date.now() / 1000);
var sig = GenerateSignature(appId, signatureNonce, serverSecret, timeStamp)

//The following example mixes the audio and video stream with streamID "stream1" with the audio and video stream with streamID "stream2" to output the audio and video stream with streamID "stream3"
var url = `https://rtc-api.zego.im/?Action=StartMix&AppId=${appId}&SignatureNonce=${signatureNonce}&Timestamp=${timeStamp}&Signature=${sig}&SignatureVersion=2.0&IsTest=false`
var body = {
    'TaskId': '123',
    'Sequence': 123,
    'UserId': '123',
    'MixInput': [
    {
        'StreamId': 'stream1',
        'RectInfo': {
            "Top": 70,
            "Bottom": 160,
            "Left": 100,
            "Right": 260,
        },
    },
    {
        'StreamId': 'stream2',
        'RectInfo': {
            "Top": 200,
            "Bottom": 290,
            "Left": 100,
            "Right": 260,
        },
    }
    ],
    'MixOutput': [{
        'StreamId': 'stream3',
        'Width': 360,
        'Height': 360,
        'VideoBitrate': 12000,
        'Fps': 15
    }]
}

request({
    url: url,
    method: 'POST',
    json: true,
    headers: {
        'content-type': 'application/json'
    },
    body: body
}, function (error, response, body) {
    console.log(error)
    console.log(response.statusCode)
    if (!error && response.statusCode === 200) {
        console.log(body.Data)
    }
})

Usage Flow

Developers can quickly initiate requests to ZEGO servers through the following process:

  1. The developer's server first confirms the URL address of the request;
  2. Obtain signature information according to the signature generation rules;
  3. The developer's server configures common request parameters;
  4. Configure API-related business parameters;
  5. The developer's server accesses the ZEGO server through the URL address, carrying request information (including business parameters, signature information, etc.);
  6. ZEGO server returns response information.

We take the API interface Describe User List as an example to send a GET request to the ZEGO server and introduce the usage flow in detail.

Confirm URL Address

ZEGO server distinguishes different requests based on different URL addresses (for specific formats, please refer to "Request Method Overview" in Calling Method). Therefore, when the developer's server accesses the ZEGO server, please first obtain the request URL address from the corresponding interface documentation.

The following is the URL address for Describe User List:

https://rtc-api.zego.im/?Action=DescribeUserList

Where:

  • https: Specifies the request communication protocol.
  • rtc-api.zego.im: Specifies the access address of the ZEGO server, where rtc represents that the product used is the cloud communication product (including real-time audio and video, real-time voice, etc.), see Calling Method - Request Structure - Access Address for details.
  • Action=DescribeUserList: Specifies that the API interface to be called is DescribeUserList.

Generate Signature Information

To ensure the secure calling of APIs, ZEGO server will authenticate each API access request. When calling APIs, developers need to include signature Signature information in the request.

Developers can refer to the sample code in various languages in Calling Method - Signature Mechanism, use the AppId and ServerSecret obtained in Prerequisites of this article to generate their own signature information.

Configure Common Request Parameters

Before calling each ZEGO server-side API, developers need to configure the common request parameters of the API first.

Common request parameters refer to the request parameters that need to be used by each interface, including AppId, Signature (referring to the 2 generated signature information), SignatureNonce (random string), Timestamp (timestamp), etc. Please modify according to the actual situation. For the specific introduction of common parameters, please refer to Calling Method - Common Parameters.

https://rtc-api.zego.im/?Action=DescribeUserList&AppId=1234567890&SignatureNonce=15215528852396&Timestamp=1234567890&Signature=Pc5WB8gokVn0xfeu%2FZV%2BiNM1dgI%3D&SignatureVersion=2.0&IsTest=false

Developers can enter the URL address on the Server API Verification page to verify whether the signature information, common parameters, and URL format are legal.

After configuring the common parameters, configure the business parameters related to the API to set the required target operation.

For the specific introduction of business parameters, please refer to Request Parameters.

Developer's Server Initiates Request

After the above configuration is completed, the developer's server can send a request to the ZEGO server through the URL address.

The request example is as follows:

//This request is to get the list of users in the Room with RoomId `room_demo`
https://rtc-api.zego.im/?Action=DescribeUserList
&RoomId=room_demo
&Mode=0
&Limit=2
&Marker=1635940599950-user2
&<Common Request Parameters>

ZEGO Server Responds to Request

After receiving the developer's request information, ZEGO server returns the response information.

{
    "Code": 0,
    "Message": "success",
    "RequestId": "TestRequestId1635940600561291000",
    "Data": {
        "Marker": "1635940599950-user2",
        "UserList": [
            {
                "UserId": "user1",
                "UserName": "user1"
            },
            {
                "UserId": "user2",
                "UserName": "user2"
            }
        ]
    }
}

In the returned information field, if Code is "0", it means the access is successful and you can view the member list in the Room; if it is not "0", please refer to Global Return Codes for handling.

At this point, the developer's server and ZEGO server have completed an information interaction.

Previous

API Overview

Next

Calling APIs