H.265
Function Overview
Function Description
H.265 is an efficient video encoding standard designed to deliver higher quality network video over limited bandwidth. Developers can output video bitstreams in H.265 format during encoding or stream mixing.
- ZEGO Express SDK has supported this feature since version 0.19.0.
- If you need to support H.265 video encoding, you need to upgrade all online ZEGO Express SDKs to version 0.19.0 or above; otherwise, decoding H.265 in online versions may result in abnormalities.
The differences between H.265 and H.264 are as follows:
| Difference Item | H.264 | H.265 |
|---|---|---|
| Bitrate at same video quality | - | H.265 saves approximately 30% bitrate compared to H.264 (measured value). |
| Software encoding performance | - | H.265 consumes approximately 3 times the computing power of H.264. |
| Software decoding performance | - | H.265 consumes approximately 1.5 times the computing power of H.264. |
| Hardware ecosystem | Basically all models support hardware encoding and decoding. | Most models support hardware encoding, and the vast majority of models support hardware decoding. |
| Stream mixing output | Supported. | Supported, but the price is more expensive than H.264 stream mixing output. For details, please consult sales. |
| Applicable scenarios | All scenarios. | Recommended for live streaming and audio/video interactive scenarios. |
Application Scenarios
- In talent show live streaming, e-commerce live streaming, interactive live streaming, and game live streaming: By using H.265 encoding, reduce bitrate by 30% (measured value) and distribute to thousands of viewers, greatly reducing CDN distribution costs.
- In video calls, video conferences, and online education: By using H.265 encoding, improve video clarity at the same bitrate, making call effects better in these scenarios.
Concept Explanation
- Video encoding: A method that converts original video format files into another video format through specific compression technology for easy transmission and storage.
- Stream mixing: A technology that mixes multiple audio and video streams into one stream from the cloud. It supports three methods: manual stream mixing, automatic stream mixing, and fully automatic stream mixing. For details, please refer to Stream Mixing.
- Relaying to CDN: The process of pushing audio and video streams from ZEGO Video Call cloud to CDN. For details, please refer to Live Streaming with CDN.
- Co-hosting: A form of interaction between users in a room. By calling the startPublishingStream interface to publish your own stream while also calling the startPlayingStream interface to play the other party's stream. After two users successfully co-host, they can engage in interactive calls.
Service Activation
- When using stream mixing to output H.265 bitstreams, you need to contact ZEGOCLOUD Technical Support to activate the service.
- When using stream mixing to output H.265 bitstreams, pricing will change. Please contact ZEGOCLOUD Business Team for specific cost details.
Prerequisites
Before implementing H.265 encoding/decoding functionality, please ensure:
- You have created a project in the ZEGOCLOUD Console and applied for a valid AppID and AppSign. For details, please refer to Console - Project Information.
- You have integrated ZEGO Express SDK into the project and implemented basic audio and video streaming functionality. For details, please refer to Quick Start - Integration and Quick Start - Implementation.
Implementation Methods
Detect H.265 Encoding/Decoding Capability
Detect H.265 Encoding Capability
Some older or low-end mobile models do not support H.265 video encoding. In this case, developers need to before publishing stream first determine whether the device supports H.265 video encoding capability through the isVideoEncoderSupported interface. If supported, you can set H.265 video encoding type through the setVideoConfig interface before publishing stream; otherwise, it will not take effect.
Detect H.265 Decoding Capability
Some older or low-end mobile models do not support H.265 video decoding. In scenarios where different video bitstreams can be played, such as CDN scenarios, developers need to before playing stream first determine whether the device supports H.265 video decoding capability through the isVideoDecoderSupported interface. If supported, H.265 video bitstreams can be played; otherwise, only other video bitstream formats, such as H.264, can be played.
Co-hosting Stream Mixing Live Streaming
Co-hosting stream mixing live streaming includes the following two implementation methods. Developers can choose to integrate as needed based on actual situations:
- Mix different format bitstreams (recommended): Stream mixing service directly outputs one H.265 mixed stream and one H.264 mixed stream. This scenario only requires one transcoding by the stream mixing service, eliminating the need for CDN transcoding. Compared to stream mixing push CDN transcoding, it offers higher clarity and lower costs, making it recommended.
- Stream mixing push CDN transcoding: Stream mixing service directly outputs one H.265 mixed stream, which needs to use CDN's transcoding capability to transcode one H.265 and one H.264 bitstream.
You need to contact ZEGOCLOUD Technical Support to activate the CDN transcoding feature.
Mix Different Format Bitstreams (Recommended)
In this scenario, after the stream mixing service receives the streams published by the host and co-hosting guests through ZEGOCLOUD Video Call cloud, it directly outputs one H.265 mixed stream and one H.264 mixed stream, and pushes both streams to CDN. Viewers can choose to play H.265 bitstreams or H.264 bitstreams from CDN based on whether their terminal devices support H.265 video decoding.

Host End
- Create a new mixer task object through the constructor ZegoMixerTask, then call instance methods to set input, output, and other parameters respectively.
- Set the mixer task input stream list through the inputList property in the mixer task object ZegoMixerTask (the encoding format of streams in stream mixing input supports H.264 and H.265), default supports up to 9 input streams, please handle stream layout yourself.
- Set the mixer task output stream list through the outputList property in the mixer task object ZegoMixerTask. Assuming in the current scenario, the stream mixing service directly transcodes one H.264 mixed stream and one H.265 mixed stream, that is, the stream mixing output video encoding format is H.264 and H.265.
- Call the startMixerTask interface to initiate a mixer task.
- Developer notifies the app's business server that a new stream has been added.
// Call startMixerTask to start mixing
const task = new ZegoMixerTask("MY_TASK_ID");
// Please set videoConfig yourself
task.videoConfig = {width: 720, height: 1280, fps: 15, bitrate: 1500}
// Please set audioConfig yourself
task.audioConfig = {bitrate: 48, channel: ZegoAudioChannel.Mono, codecID: ZegoAudioCodecID.Normal}
// Note that the encoding format of streams in stream mixing input supports H.264 and H.265. Please handle stream layout and input yourself
task.inputList.push({"streamID": "stream-1", "contentType": ZegoMixerInputContentType.Video, "layout": {"x": 0, "y": 0, "width": task.videoConfig.width, "height": task.videoConfig.height/2}})
task.inputList.push({"streamID": "stream-2", "contentType": ZegoMixerInputContentType.Video, "layout": {"x": 0, "y": task.videoConfig.height / 2, "width": task.videoConfig.width, "height": task.videoConfig.height/2}})
// Stream mixing two outputs
// Note: output target can be streamID or CDN address. The processing methods are different for viewers. This scenario recommends directly passing streamID
// Note: Bitrate in ZegoMixerOutput has higher priority than bitrate in ZegoMixerVideoConfig
let h264StreamID = ""; // Please enter h264StreamID
let h265StreamID = ""; // Please enter h265StreamID
const h264Bitrate = 2244; // Please enter h264 bitrate. This bitrate is the recommended bitrate for current resolution frame rate (720p, 15fps)
const h265Bitrate = 1795; // Please enter h265 bitrate. This bitrate is the recommended bitrate for current resolution frame rate (720p, 15fps)
let outputH264 = new ZegoMixerOutput(h264StreamID);
outputH264.videoConfig = {"width": task.videoConfig.width, "height": task.videoConfig.height, "fps": 15, "bitrate": h264Bitrate};
let outputH265 = new ZegoMixerOutput(h265StreamID);
outputH265.videoConfig = {"width": task.videoConfig.width, "height": task.videoConfig.height, "fps": 15, "bitrate": h265Bitrate};
task.outputList = [outputH264, outputH265];
// Start mixing
ZegoExpressEngine.instance().startMixerTask(task).then((result) => {
if (result.errorCode == 0) {
console.log("Start mixer task success");
} else {
console.log("Start mixer task fail");
}
}];
// Developer notifies the app's business server that a new stream has been addedAudience End
- The audience end receives a stream added notification from the app's business server.
- Call the isVideoDecoderSupported interface to query whether the audience's device supports H.265 decoding format.
- If supported, call the startPlayingStream interface to play H.265 bitstreams from CDN.
- If not supported, call the startPlayingStream interface to play H.264 bitstreams from CDN.
// Receive stream added notification from the app's business server
let h265DecoderSupport = ZegoExpressEngine.instance().isVideoDecoderSupported(ZegoVideoCodecID.H265);
let h264StreamID = ""; // h264StreamID
let h265StreamID = ""; // h265StreamID
let playCanvas = {"reactTag": findNodeHandle(this.refs.zego_play_view), "viewMode": 0, "backgroundColor": 0};
if (h265DecoderSupport) {
// Supports H.265 decoding
ZegoExpressEngine.instance().startPlayingStream(h265StreamID, playCanvas);
}
else {
// Does not support H.265 decoding
ZegoExpressEngine.instance().startPlayingStream(h264StreamID, playCanvas);
}Stream Mixing Push CDN Transcoding
In this scenario, after the stream mixing service receives the streams published by the host and co-hosting guests through ZEGOCLOUD Video Call cloud, it directly outputs one H.265 mixed stream and pushes this mixed stream to CDN. Through CDN's transcoding capability, viewers can choose to play H.265 bitstreams or H.264 bitstreams from CDN based on whether their terminal devices support H.265 video decoding.

Host End
- Create a new mixer task object through the constructor ZegoMixerTask, then call instance methods to set input, output, and other parameters respectively.
- Set the mixer task input stream list through the inputList property in the mixer task object ZegoMixerTask (the encoding format of streams in stream mixing input supports H.264 and H.265), default supports up to 9 input streams, please handle stream layout yourself.
- Set the mixer task output stream list through the outputList property in the mixer task object ZegoMixerTask. Assuming in the current scenario, the stream mixing service directly outputs one H.265 mixed stream, that is, the stream mixing output video encoding format is H.265.
- Call the startMixerTask interface to initiate a mixer task.
- Developer notifies the app's business server that a new stream has been added.
// Call startMixerTask to start mixing
const task = new ZegoMixerTask("MY_TASK_ID");
// Please set videoConfig yourself
task.videoConfig = {width: 720, height: 1280, fps: 15, bitrate: 1500}
// Please set audioConfig yourself
task.audioConfig = {bitrate: 48, channel: ZegoAudioChannel.Mono, codecID: ZegoAudioCodecID.Normal}
// Note that the encoding format of streams in stream mixing input supports H.264 and H.265. Please handle stream layout and input yourself
task.inputList.push({"streamID": "stream-1", "contentType": ZegoMixerInputContentType.Video, "layout": {"x": 0, "y": 0, "width": task.videoConfig.width, "height": task.videoConfig.height/2}})
task.inputList.push({"streamID": "stream-2", "contentType": ZegoMixerInputContentType.Video, "layout": {"x": 0, "y": task.videoConfig.height / 2, "width": task.videoConfig.width, "height": task.videoConfig.height/2}})
// Stream mixing two outputs
// Note: output target can be streamID or CDN address. The processing methods are different for viewers. This scenario passes CDN URL
// Note: Bitrate in ZegoMixerOutput has higher priority than bitrate in ZegoMixerVideoConfig
let publishCdnUrl = ""; // Please enter CDN URL
const h265Bitrate = 1795; // Please enter h265 bitrate. This bitrate is the recommended bitrate for current resolution frame rate (720p, 15fps)
let outputH265 = new ZegoMixerOutput(publishCdnUrl);
outputH265.videoConfig = {"width": task.videoConfig.width, "height": task.videoConfig.height, "fps": 15, "bitrate": h265Bitrate};
task.outputList = [outputH265];
// Start mixing
ZegoExpressEngine.instance().startMixerTask(task).then((result) => {
if (result.errorCode == 0) {
console.log("Start mixer task success");
} else {
console.log("Start mixer task fail");
}
}];
// Developer notifies the app's business server that a new stream has been addedAudience End
- The audience end receives a stream added notification from the app's business server.
- Call the isVideoDecoderSupported interface to query whether the audience's device supports H.265 decoding format.
- If supported, call the startPlayingStream interface to play H.265 bitstreams from CDN.
- If not supported, call the startPlayingStream interface to play H.264 bitstreams from CDN.
// Receive stream added notification from the app's business server
let h265DecoderSupport = ZegoExpressEngine.instance().isVideoDecoderSupported(ZegoVideoCodecID.H265);
String playStreamID = "";
let playCanvas = {"reactTag": findNodeHandle(this.refs.zego_play_view), "viewMode": 0, "backgroundColor": 0};
if (h265DecoderSupport) {
// Supports H.265 decoding
let h265Url = ""; // Please fill in H.265 Url address
// Note: ZegoCDNConfig and ZegoPlayerConfig have other configurable items
let cdnConfig = new ZegoCDNConfig();
// H.265 CDN playing stream address
cdnConfig.url = h265Url;
let playerConfig = new ZegoPlayerConfig();
playerConfig.cdnConfig = cdnConfig;
ZegoExpressEngine.instance().startPlayingStream(playStreamID, playCanvas, playerConfig);
}
else {
// Does not support H.265 decoding
let h264Url = ""; // Please fill in H.264 Url address
// Note: ZegoCDNConfig and ZegoPlayerConfig have other configurable items
let cdnConfig = new ZegoCDNConfig();
// H.264 CDN playing stream address
cdnConfig.url = h264Url;
let playerConfig = new ZegoPlayerConfig();
playerConfig.cdnConfig = cdnConfig;
ZegoExpressEngine.instance().startPlayingStream(playStreamID, playCanvas, playerConfig);
}Single Host Live Streaming
Real-time Network Relay to CDN Live Streaming
This scenario has the following two characteristics:
- The host relays to CDN through ZEGOCLOUD Video Call cloud. Through CDN's transcoding capability, viewers can choose to play H.265 bitstreams or H.264 bitstreams from CDN based on whether their terminal devices support H.265 video decoding.
- When the host publishes H.265 bitstreams, co-hosting guests play streams directly from ZEGOCLOUD Video Call cloud for real-time interaction. This requires that co-hosting guests' terminal devices support H.265 video decoding capability.

Host End
After creating the engine, call the enableHardwareEncoder interface to enable hardware encoding (if configuration is changed after publishing stream, you need to wait for the next publishing stream to take effect). After enabling, GPU will be used for encoding, reducing CPU usage.
Call the isVideoEncoderSupported interface to query whether the host's device supports the specified video encoding type.
Before publishing stream, call the setVideoConfig interface to set video encoding format through codecID (if configuration is changed after publishing stream, you need to wait for the next publishing stream to take effect). If H.265 encoding is set, then:
You can call the enableH265EncodeFallback interface to enable automatic fallback to H.264 encoding when H.265 encoding fails (default enabled). After enabling, when H.265 encoding is not supported or H.265 encoding fails, the SDK will internally attempt to downgrade to H.264 encoding for publishing stream. After disabling, when H.265 encoding is not supported or H.265 encoding fails, publishing stream will fail directly.
Call the addPublishCdnUrl interface to add the URL address for relaying the audio and video stream from ZEGOCLOUD Video Call cloud to CDN.
Call the startPublishingStream interface to start publishing stream. After successful publishing, other users in the same room can get stream addition notifications by listening to the roomStreamUpdate callback.
Developer notifies the app's business server of the encoding format of the publishing stream so that the playing stream end can handle accordingly based on different publishing encoding formats.
// Using H.265 encoding on mobile devices requires enabling hardware encoding
ZegoExpressEngine.instance().enableHardwareEncoder(true);
// Query whether H.265 encoding is supported
let h265EncoderSupport = ZegoExpressEngine.instance().isVideoEncoderSupported(ZegoVideoCodecID.H265);
let videoConfig = new ZegoVideoConfig();
if (h265EncoderSupport) {
// Supports H.265 encoding
videoConfig.codecID = ZegoVideoCodecID.H265;
} else {
// Does not support H.265 encoding
videoConfig.codecID = ZegoVideoCodecID.Default;
}
ZegoExpressEngine.instance().setVideoConfig(videoConfig);
if (h265EncoderSupport) {
// Choose whether to enable H.265 encoding failure automatic fallback capability through enableH265EncodeFallback
ZegoExpressEngine.instance().enableH265EncodeFallback(true);
}
let publishStreamID = ""; // Please enter streamID
let publishCdnUrl = ""; // Please enter CdnUrl
// Add CDN relay address
ZegoExpressEngine.instance().addPublishCdnUrl(publishStreamID, publishCdnUrl).then((result) {
if(result.errorCode == 0) {
// Relay successful
} else {
// Relay failed. Relay request sending may have failed due to network reasons
}
});
ZegoExpressEngine.instance().startPublishingStream(publishStreamID);
// Developer notifies the app's business server of the encoding format of the publishing stream so that the playing stream end can handle accordingly based on different publishing encoding formatsAudience End
- After the host publishes stream, the audience end receives stream added notification through the roomStreamUpdate interface.
- The audience end gets the encoding format of the publishing stream from the app's business server.
- If it is H.264 format, the audience can call the startPlayingStream interface to play the host's stream directly from CDN.
- If it is H.265 format, you need to first call the isVideoDecoderSupported interface to query whether the audience's device supports H.265 decoding format.
- If supported, call the startPlayingStream interface to play H.265 bitstreams from CDN.
- If not supported, call the startPlayingStream interface to play H.264 bitstreams from CDN.
// Receive stream added notification roomStreamUpdate
ZegoExpressEngine.instance().on('roomStreamUpdate', (roomID, updateType, streamList) => {
let videoCodecID = 0; // Get the encoding format of this stream from the app's business server
let playStreamID = ""; // Please enter streamID
let playCanvas = {"reactTag": findNodeHandle(this.refs.zego_play_view), "viewMode": 0, "backgroundColor": 0};
if (videoCodecID == ZegoVideoCodecID.H265) {
// Encoding format is H.265
let h265DecoderSupport = ZegoExpressEngine.instance().isVideoDecoderSupported(ZegoVideoCodecID.H265);
// Do not play stream if decoding is not supported
if (h265DecoderSupport) {
// Supports H.265 decoding
let h265Url = ""; // Please fill in H.265 Url address
// Note: ZegoCDNConfig and ZegoPlayerConfig have other configurable items
let cdnConfig = new ZegoCDNConfig();
// H.265 CDN playing stream address
cdnConfig.url = h265Url;
let playerConfig = new ZegoPlayerConfig();
playerConfig.cdnConfig = cdnConfig;
ZegoExpressEngine.instance().startPlayingStream(playStreamID, playCanvas, playerConfig);
} else {
// Does not support H.265 decoding
let h264Url = ""; // Please fill in H.264 Url address
// Note: ZegoCDNConfig and ZegoPlayerConfig have other configurable items
let cdnConfig = new ZegoCDNConfig();
// H.264 CDN playing stream address
cdnConfig.url = h264Url;
let playerConfig = new ZegoPlayerConfig();
playerConfig.cdnConfig = cdnConfig;
ZegoExpressEngine.instance().startPlayingStream(playStreamID, playCanvas, playerConfig);
}
}
else if (videoCodecID == ZegoVideoCodecID.Default) {
// Encoding format is H.264
ZegoExpressEngine.instance().startPlayingStream(playStreamID, playCanvas);
}
});Co-hosting Guest End
- After the host publishes stream, co-hosting guests receive stream added notifications through the roomStreamUpdate interface.
- Co-hosting guests get the encoding format of the publishing stream from the app's business server.
- If it is H.264 format, co-hosting guests can call the startPlayingStream interface to play the host's stream directly from ZEGOCLOUD Video Call cloud.
- If it is H.265 format, you need to first call the isVideoDecoderSupported interface to query whether their device supports H.265 decoding format.
- If supported, call the startPlayingStream interface to play H.265 bitstreams from ZEGOCLOUD Video Call cloud.
- If not supported, prompt that the terminal device does not support playing this stream.
// Receive stream added notification onRoomStreamUpdate
ZegoExpressEngine.instance().on('roomStreamUpdate', (roomID, updateType, streamList) => {
let videoCodecID = 0; // Get the encoding format of this stream from the app's business server
let playStreamID = ""; // Please enter streamID
let playCanvas = {"reactTag": findNodeHandle(this.refs.zego_play_view), "viewMode": 0, "backgroundColor": 0};
let playerConfig = new ZegoPlayerConfig();
playerConfig.resourceMode = ZegoStreamResourceMode.OnlyRTC; // Only play stream from RTC
if (videoCodecID == ZegoVideoCodecID.H265) {
// Encoding format is H.265
let h265DecoderSupport = ZegoExpressEngine.instance().isVideoDecoderSupported(ZegoVideoCodecID.H265);
// Do not play stream if decoding is not supported
if (h265DecoderSupport) {
// Supports H.265 decoding
ZegoExpressEngine.instance().startPlayingStream(playStreamID, playCanvas, playerConfig);
}
}
else if (videoCodecID == ZegoVideoCodecID.Default) {
// Encoding format is H.264
ZegoExpressEngine.instance().startPlayingStream(playStreamID, playCanvas, playerConfig);
}
});Recording
If H.265 encoding/decoding functionality is used during local server-side recording, cloud recording, or data stream recording, it will affect the generation of recording files as follows:
When recording a publishing stream (H.265 video encoded bitstream), encoding fallback may be triggered due to H.265 encoding failure. At this time, the publisherVideoEncoderChanged callback will be received, indicating that the video encoding format has changed.
In this scenario, to avoid damaging recording files, the SDK will internally end and save the current recording task and automatically restart a new recording task. The recording file path of the new recording task will be regenerated to avoid overwriting the original recording file. The generation rule for new files is to add a timestamp to the original recording file name:
For example, if the original recording file path passed by the developer is: /user/data/mediarecord.mp4, then the new recording file is: /user/data/mediarecord_1626880634948.mp4, where 1626880634948 is the current timestamp.
If developers receive the publisherVideoEncoderChanged callback during recording, they need to collect other files in the recording file storage path after recording ends.
FAQ
- What to do when H.265 hardware encoding encounters errors?
You can call the enableH265EncodeFallback interface to enable fallback functionality (default enabled). If H.265 hardware encoding fails, it will fall back to H.264. If using recording functionality at the same time, the recording files will become two copies.
- Will H.265 automatically fall back from hardware decoding to software decoding?
Yes, if hardware decoding fails during decoding, it will automatically fall back to software decoding.
- How is H.265 priced?
Enabling H.265 functionality on the client does not require fees, but stream mixing output H.265 requires stream mixing fees, which are more expensive than stream mixing output H.264. For details, please consult ZEGOCLOUD Business Team.
- Is there a change in pricing when stream mixing inputs H.265 streams and outputs H.264 streams?
No change, pricing is based on H.264 output.
- What are the hardware requirements for H.265 decoding?
Currently all models on the market support H.265 decoding. Testing shows that low-end models before 2013 may have frame rate fluctuations during decoding.
