Through the stream-mixing service, multiple published media streams can compose a single stream , which allows audiences to play just one stream to improve quality and reduce performance cost.
Starts or updates a stream mixing task.
For more information about the stream mixing feature, see Stream mixing.
For callbacks related to stream mixing, see Callback on stream mixing started and Callback on stream mixing ended.
Before using this interface for the first time, you need to contact ZEGO technical support to activate it.
Before you begin, make sure you complete the following:
ZEGOCLOUD provides example code in multiple programming languages. The following example code is for "mixing two audio and video streams (stream1, stream2) and outputting the mixed stream to a single stream (stream3)".
package main
import (
"bytes"
"crypto/md5"
"crypto/rand"
"encoding/hex"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strconv"
"time"
)
const DOMAIN = "https://rtc-api.zego.im"
var (
AppId uint32 =
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
}
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
}
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()
h.Write([]byte(data))
return hex.EncodeToString(h.Sum(nil))
}
# -*- coding: UTF-8 -*-
import hashlib
import secrets
import time
# 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__':
appId =
serverSecret = ""
signatureNonce = secrets.token_hex(8)
timestamp = int(time.time())
sig = GenerateSignature(appId, signatureNonce, serverSecret, timestamp)
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)
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;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
public class StartMix {
//
public static void main(String[] args) {
startMixStream();
}
public static void startMixStream() {
Long APP_ID =
String SERVER_SECRET = ;
byte[] bytes = new byte[8];
SecureRandom sr = new SecureRandom();
sr.nextBytes(bytes);
String signatureNonce = bytesToHex(bytes);
long timestamp = System.currentTimeMillis() / 1000L;
String signatue = generateSignature(APP_ID, signatureNonce, SERVER_SECRET, timestamp);
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");
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);
}
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{
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] bytes = md.digest(str.getBytes("utf-8"));
signature = bytesToHex(bytes);
}catch (Exception e) {
e.printStackTrace();
}
return signature;
}
public static String bytesToHex(byte[] bytes) {
StringBuffer md5str = new StringBuffer();
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();
}
public static String sendGet(String httpurl) {
HttpURLConnection connection = null;
InputStream is = null;
BufferedReader br = null;
String result = null;
try {
URL url = new URL(httpurl);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(15000);
connection.setReadTimeout(60000);
connection.connect();
if (connection.getResponseCode() == 200) {
is = connection.getInputStream();
br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
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 {
if (null != br) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != is) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
connection.disconnect();
}
return result;
}
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);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setConnectTimeout(15000);
connection.setReadTimeout(60000);
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestProperty("Content-Type", "application/json");
connection.connect();
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream(),"UTF-8");
writer.write(param);
writer.flush();
if (connection.getResponseCode() == 200) {
is = connection.getInputStream();
br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
StringBuffer sbf = new StringBuffer();
String temp = null;
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 {
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();
}
}
connection.disconnect();
}
return result;
}
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
$appId =
$serverSecret =
//Signature=md5(AppId + SignatureNonce + ServerSecret + Timestamp)
function GenerateSignature($appId, $signatureNonce, $serverSecret, $timeStamp){
$str = $appId . $signatureNonce . $serverSecret . $timeStamp;
return md5($str);
}
$signatureNonce = bin2hex(random_bytes(8));
list($msec, $sec) = explode(' ', microtime());
$msecTime = (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
$timeStamp = round($msecTime/1000);
$sig = GenerateSignature($appId, $signatureNonce, $serverSecret, $timeStamp);
$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);
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');
var appId = ;
var serverSecret = ;
//Signature=md5(AppId + SignatureNonce + ServerSecret + Timestamp)
function GenerateSignature(appId, signatureNonce, serverSecret, timeStamp) {
const hash = crypto.createHash('md5');
var str = appId + signatureNonce + serverSecret + timeStamp;
hash.update(str);
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)
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)
}
})
Listed below are the parameters specific to this request and part of the public request parameters. For the complete list of public request parameters, see Server APIs public request parameters.
Only some parameters in this API support dynamic updates after the stream mixing starts. For details, refer to the description in the following table.
For all the request parameters below, parameters with the type "String" only support numbers, English characters, and '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '=', '-', '`', ';', '’', ',', '.', '<', '>', '/', ''。
Name | Type | Required | Description |
---|---|---|---|
TaskId |
String |
Yes |
Task ID, the unique identifier of a stream mixing task, which can be used to update a stream mixing task or determine whether a stream mixing task is newly added. |
UserId |
String |
Yes |
User ID. The user ID of the operations on the same stream mixing task must be consistent. The user ID can be used as an identifier of the task owner, which means only the user with this user ID can update or stop the task. To use this feature, contact ZEGO technical support to enable it first. |
MixInput |
Array of Object |
Yes |
Input streams. By default, a stream mixing task can have up to 9 input streams. If you need to have more input streams, contact ZEGO Technical Support for assistance. |
└ StreamId |
String |
Yes |
Stream ID of the input stream. If an input stream has a stream ID, it comes from the ZEGO RTC service. |
└ StreamUrl |
String |
Yes |
URL of the input stream, which must be an RTMP or HTTP-FLV URL. You can use either StreamID or StreamUrl to specify an input stream. If StreamUrl is specified, StreamId doesn't take effect. |
└ RectInfo |
Object |
Yes |
Position information of the input stream. |
└ Layer |
Int |
No |
Picture layer level. 0 represents the lowest level. The higher the value, the higher the level. This parameter supports dynamic updates after the stream mixing starts. |
└ Top |
Int |
No |
Position of this input stream's top border. Pixel distance from the top border of the output stream's canvas. This parameter supports dynamic updates after the stream mixing starts. |
└ Left |
Int |
No |
Position of this input stream's left border. Pixel distance from the left border of the output stream's canvas. This parameter supports dynamic updates after the stream mixing starts. |
└ Bottom |
Int |
No |
Position of this input stream's bottom border. Pixel distance from the bottom border of the output stream's canvas. This parameter supports dynamic updates after the stream mixing starts. |
└ Right |
Int |
No |
Position of this input stream's right border. Pixel distance from the right border of the output stream's canvas. This parameter supports dynamic updates after the stream mixing starts. |
└ CornerRadius |
Int |
No |
Video corner radius. This parameter supports dynamic updates after the stream mixing starts.The effect is shown below: |
└ Image |
Object |
No |
Set an image for this input stream to overlay the video content; when using an image, the video content will not be displayed. The configured image will reuse the position information set by RectInfo. |
└ Url |
String |
No |
Image path, supports JPG and PNG formats. Supports the following 2 usage modes:
If this parameter is empty, video content will be displayed.This parameter supports dynamic updates after the stream mixing starts. |
└ DisplayMode |
Int |
No |
Image display mode.
|
└ ContentControl |
Int |
No |
Content control.
|
└ SoundLevelId |
Int |
Yes |
ID of the input stream's sound level data. |
MixOutput |
Array of Object |
Yes |
Output streams. A stream mixing task can have up to 3 mixing outputs. |
└ StreamId |
String |
Yes |
Stream ID of the output stream. By default, the mixed streams are sent to ZEGO's RTC servers or ZEGO's low-latency live streaming servers. You can also contact ZEGO Technical Support to configure the system to send the outputs to the CDNs supported by ZEGO, which will be applied to all mixing outputs in the entire scope of your AppID. If you want to specify the CDN destination for individual output streams, you must specify the streamURL accordingly instead. |
└ StreamUrl |
String |
Yes |
The destination URL of the output stream, which must be an RTMP URL. Users can receive and play the mixed stream directly from this URL. You can use either StreamId or StreamUrl to specify an output stream. If StreamUrl is specified, StreamId doesn't take effect. |
└ VideoBitrate |
Int |
Yes |
Video bitrate (bps) of the output stream. When mixing audio-only streams, set this value to 1. You can update this value in real time while the stream mixing task is running. This parameter supports dynamic updates after the stream mixing starts. |
└ VideoEncId |
Int |
No |
Output video encoding.
This parameter does not support dynamic updates after the stream mixing starts. Supports different output streams to use different video encoding formats, with a maximum limit of two. When using multiple video encoding formats, please contact ZEGO technical support to enable the "mutil_encode" backend parameter first. |
└ Fps |
Int |
Yes |
Video frame rate. |
└ Width |
Int |
Yes |
Video frame Width of the output stream. This value must be in the range [0, 3000] and must be a multiple of 2. When mixing audio-only streams, set this value to 1. You can update this value in real time while the stream mixing task is running. This parameter supports dynamic updates after the stream mixing starts. |
└ Height |
Int |
Yes |
Video frame height of the output stream. This value must be in the range [0, 3000] and must be a multiple of 2. When mixing audio-only streams, set this value to 1. You can update this value in real time while the stream mixing task is running. This parameter supports dynamic updates after the stream mixing starts. |
└ AudioCodec |
Int |
No |
Audio coding format and sampling rate of the output stream. To modify the sampling rate, please contact ZEGO Technical Support.
|
└ AudioBitrate |
Int |
NO |
Audio bitrate of the output stream. The default value is 48000 bps. |
└ SoundChannel |
Int |
No |
The number of audio channels of the output stream, which takes precedence over the global parameter.
|
Sequence |
Int |
Yes |
The sequence number of the stream mixing request, which is used to ensure the sequence of task operations. Requests must be sent with ascending sequence numbers. |
RoomId |
String |
No |
Room ID. |
UserData |
String |
No |
User data. On the client side, this custom-defined data is received through the callback onPlayerRecvSEI. The data length must be in the range of [1, 1000] bytes, and the recommended length is 850 bytes or less. You can update the user data in real time while the stream mixing task is running. This parameter supports dynamic updates after the stream mixing starts. |
SoundLevel |
Int |
No |
The sound level of the mixed stream. You can update this sound level value in real time while the stream mixing task is running.
|
ByPass |
Int |
No |
Switch of the single-stream passthrough feature. This switch controls whether to recode the stream according to the output settings when there is only one input stream. To use this feature, contact ZEGO technical support to enable it first.
|
SoundChannel |
String |
No |
Output audio channel count, this configuration will take effect when the channel count is not specified for the output stream.
|
BackgroundImage |
String |
No |
Background image of the mixed stream. You can use images in JPG and PNG formats as the background images and set up the background image using either one of these methods:
|
BackGroundColorHex |
String |
No |
The background color of the mix stream corresponds to the RGBA color value of 0xRRGGBBAA. Currently, setting the transparency of the background color is not supported. You can set AA in 0xRRGGBBAA to 00. For example, for the RGB color #87CEFA, the corresponding parameter value would be 0x87CEFA00. This parameter supports dynamic updates after the stream mixing starts. |
WaterMark |
Object |
No |
Watermark configuration. |
└ Image |
String |
No |
Watermark image. You can use images in JPG and PNG formats as watermark images and set up the watermark image the same way as you do for BackgroundImage. This parameter supports dynamic updates after the stream mixing starts. |
└ RectInfo |
Object |
No |
Position information of the watermark. This parameter supports dynamic updates after the stream mixing starts. |
└ Top |
Int |
No |
Position of the watermark's top border. Pixel distance from the top border of the output stream's canvas. |
└ Left |
Int |
No |
Position of the watermark's left border. Pixel distance from the left border of the output stream's canvas. |
└ Bottom |
Int |
No |
Position of the watermark's bottom border. Pixel distance from the bottom border of the output stream's canvas. |
└ Right |
Int |
No |
Position of the watermark's right border. Pixel distance from the right border of the output stream's canvas. |
ExPara |
Array of Object |
No |
Extension parameters, which can be specified according to the actual situation. For regular mixing tasks, you can skip this parameter. |
└ Key |
String |
No |
The Key of the parameter (key-value pair). |
└ Value |
String |
No |
The Key of the parameter (key-value pair). |
AlignmentType |
Int |
No |
Control whether the real-time audio and video streams need to be mixed after precise alignment according to NTP (Network Time Protocol).This parameter is mainly used in KTV scenarios and will introduce a certain mixing delay. It is not recommended to set this parameter for non-KTV or similar scenarios.
|
RecvBufferLevel |
Int |
No |
Used to control the minimum buffering time for pulling streams (unit: milliseconds), with a value range of [0, 4000]. The default minimum buffering time is 0. |
https://rtc-api.zego.im/?Action=StartMix
&AppId=1234567890
&SignatureNonce=15215528852396
&Timestamp=1234567890
&Signature=7a2c0f11145fb760d607a07b54825013
&SignatureVersion=2.0
&IsTest=false
{
"TaskId": "2213699902971205739", // N, string, Task ID, needs to be consistent for the same task
"Sequence": 1, // Y, int, Sequence number of the mix stream request, ensure increasing when modifying mix stream parameters
"UserId": "123", // Y, string, User ID
"RoomId": "321", // N, string, Room ID
"UserData": "DoraTest", // N, string, Custom user data, needs to be base64 encoded, length limit is 4000 bytes, recommended not to exceed 850 bytes; The custom user data will be transmitted as SEI information to the player, and the player can obtain this data through the onPlayerSyncRecvSEI callback; Supports real-time update during mix stream process
"SoundLevel": 1, // N, int, Sound level of the mix stream, 1: enabled, 0: disabled; Default value is 0; Supports real-time update during mix stream process
"BackgroundImage": "http://47.101.46.7:8090/no_camera_icon.png", // N, string, Background image, supports online URL
"BackGroundColorHex": "0x87CEFA00", // N, string, Background color
"ByPass": 1, // N, single stream bypass switch, whether to mix when there is only one input stream (default is not enabled), 1: enabled, 0: disabled
"AlignmentType": 0, // Alignment type: 0 - Not aligned (default), 1 - Specify stream alignment, 2 - Force alignment for all streams
"MixInput": [
{
"RectInfo": {
"Bottom": 640,
"Layer": 1, // N, int, Layer level
"Left": 0,
"Right": 180,
"Top": 0,
"CornerRadius": 10 // N, int, Corner radius
// The origin is at the top-left corner, top/bottom/left/right are defined as follows:
//
// (left, top)-----------------------
// | |
// | |
// | |
// | |
// -------------------(right, bottom)
},
"SoundLevelId": 1,
"StreamId": "stream1",
"Image": {
"Url": "http://47.101.46.7:8090/no_camera_icon.png",
"DisplayMode": 0
},
"ContentControl": 2, // N, int, Content control. 0: audio and video, 2: video only
"RenderMode": 0, // N, int, Mix input fill mode. 0: cropping mode (default), 1: stretching mode
"Volume": 100,
"Label": {
"Text": "Hello",
"Left": 10,
"Top": 10,
"Font": {
"FontType": 1,
"FontSize": 26,
"FontColor": 256,
"Transparency": 50
}
}
},
{
"RectInfo": {
"Bottom": 640,
"Layer": 2,
"Left": 180,
"Right": 360,
"Top": 0
},
"SoundLevelId": 2,
"StreamId": "stream2",
"ContentControl": 2,
"RenderMode": 0
}
],
"WaterMark": {
"Image": "http://47.101.46.7:8090/no_camera_icon.png", // Y, string, Watermark image
"RectInfo": { // Watermark position information; Required
"Top": 0, // Required
"Left": 0, // Required
"Bottom": 200, // Required
"Right": 150 // Required
}
},
"MixOutput": [ // Output stream list; Required
{
"StreamId": "stream3", // Y, input stream address, either StreamId or StreamUrl is required. If both StreamId and StreamUrl are provided, StreamUrl takes effect.
//"StreamUrl": "rtmp://ip/appname/streamid", either StreamId or StreamUrl is required. If both StreamId and StreamUrl are provided, StreamUrl takes effect.
"VideoBitrate": 1200000, // Y, int, video bitrate (unit: bps). Recommended to fill in 0 for pure audio mix stream; Supports real-time update during mix stream process
"Fps": 15, // Y, int, video frame rate
"Width": 360, // Y, int, width, range [0-3000]. The value must be a multiple of 2. Recommended to fill in 0 for pure audio mix stream.
"Height": 640, // Y, int, height, range [0-3000]. The value must be a multiple of 2. Recommended to fill in 0 for pure audio mix stream.
"AudioCodec": 0, // N, int, audio codec. 0: HE-AAC, 1: AAC-LC, 2: MP3; Default is 0.
"AudioBitrate": 48000, // N, int, mixed output audio bitrate. Default is 48000, in bps.
"SoundChannel": 2, // N, int, number of sound channels. 1: mono, 2: stereo.
"VideoEncId": 0 // N, int, video encoding. 0: H264, 2: VP8, 3: H265
}
],
//"ExPara", // N, extended parameters (in json struct format). Please contact technical support for details, such as video_encode/sei_mode. See data example for reference.
"ExPara": [
{
"Key": "video_encode",
"Value": "h264"
},
{
"Key": "sei_mode",
"Value": "1"
},
{
"Key": "mixowner_userid",
"Value": "[\"456\"]"
}
],
"RecvBufferLevel": 0 // N, int, minimum buffering time for pulling streams (unit: milliseconds). Default is 0.
}
Parameter | Type | Description |
---|---|---|
Code |
Number |
Return code. |
Message |
String |
Description of the request execution result. |
RequestId |
String |
Request ID. |
Data |
Array of Object |
Returned data. |
└ UserId |
String |
User ID. |
└ Sequence |
Int |
Serial number. |
└ RoomId |
String |
Room ID. |
└ PlayInfo |
Array of Object |
Playback information of the mixed stream. |
└ StreamId |
String |
Stream ID. |
└ RTMP |
String |
The CDN URL for playback using the RTMP protocol (if the output destination is configured as a CDN URL for RTMP streaming). |
└ HLS |
String |
The CDN URL for playback using the HLS protocol (if the output destination is configured as a CDN URL for HLS streaming). |
└ FLV |
String |
The CDN URL for playback using the HTTP-FLV protocol (if the output destination is configured as a CDN URL for HTTP-FLV streaming). |
{
"Code": 0,
"Data": {
"PlayInfo": [
{
"FLV": "http://domain/appname/test.flv",
"HLS": "http://domain/appname/test/playlist.m3u8",
"RTMP": "rtmp://domain/appname/test",
"Status": 0,
"StreamId": "test",
"UserName": ""
}
],
"RoomId": "321",
"Sequence": 1,
"UserId": "123"
},
"Message": "success",
"RequestId": "8472822294336370476"
}
Listed below are the return codes related to this API. For the complete list of return codes, see Return codes.
Return code | Description |
---|---|
110200001 | Failed. |
110200002 | Input error. |
110200003 | Authentication failed. |
110200004 | Failed to parse the input parameter. |
110200005 | Failed to obtain distributed locks when starting the stream mixing. |
110200006 | Failed to obtain distributed locks when stoping the stream mixing. |
110200007 | Failed to update the stream mixing request. |
110200008 | Failed to transfer protocol when stream mixing started. |
110200009 | Failed to forward the request to start stream mixing. |
110200010 | Callback on stream mixing started failed. |
110200011 | Failed to bypass data when starting stream mixing. |
110200012 | Failed to close the other stream mixing tasks of the task owner. |
110200013 | Failed to bind the ownership between the user and the stream mixing task. |
110200014 | Failed to transfer protocol when stream mixing ended. |
110200015 | Failed to forward the request to stop stream mixing. |
110200016 | Callback on stream mixing ended failed. |
110200017 | Failed to clean the stream mixing status info. |
110200103 | SEQ error. |
110200150 | Input stream of the stream mixing task does not exist. |
110200151 | Stream mixing failed. |
110200152 | Failed to stop stream mixing. |
110200153 | Input stream error. |
110200154 | Output stream error. |
110200155 | Input stream format error. |
110200156 | Output stream format error. |
110200157 | Permission of stream mixing is not enabled. |
110200158 | The number of input streams has exceeded the limit. |
110200159 | Failed to dispatch stream mixing. |
110200160 | The stream mixing is stopped by a non-owner user of the stream mixing task. |
110200170 | Watermark parameter error. |
110200171 | Watermark parameter is empty. |
110200172 | Extended parameter error. |
110200173 | The number of background images has exceeded the limit. |
110200174 | The number of watermarks has exceeded the limit. |
110200175 | Input stream repeated. |
110200176 | Output stream repeated. |
110200177 | The number of focused audio streams has exceeded the limit. |
110200178 | The number of output streams has exceeded the limit. |
110200180 | The token for starting stream mixing is empty. |
110200181 | The token for starting stream mixing is invalid. |
110200182 | The token for stoping stream mixing is empty. |
110200183 | The token for stoping stream mixing is invalid. |
110200184 | Failed to parse parameters when starting stream mixing. |
110200185 | Failed to parse parameters when stoping stream mixing. |
110200190 | Request to start stream mixing overload. |
110200191 | Request to stop stream mixing overload. |
110200192 | Request to search stream mixing tasks overload. |
110200193 | Request to search stream mixing task overload. |
110200194 | Stream mixing request overload. |
110240002 | Token is invalid. |
110240003 | AppId is empty. |
110240004 | AppId is incorrect. |
110200901 | The parameter of the LiveRoom stream mixing command is empty. |
110200902 | The parameter of the LiveRoom stream mixing command does not exist. |
110208000 | Error occurred while forwarding the mixed stream. |
110208001 | Decoding error occurred while forwarding the mixed stream. |
110208002 | The address for forwarding the mixed stream is not configured. |
110208003 | Request to forward the mixed stream overload. |
110208004 | Error occurred while forwarding mixed stream. |
When pushing pure audio mix stream and setting a background image, if the background image cannot be displayed correctly, how to handle it?
In this case, the customer needs to correctly set the width and height of the output layout according to their business needs, and contact ZEGO technical support to configure and enable black frame filling.