logo
Video Call
On this page

H.265

2026-03-05

Feature Overview

Feature Description

H.265 is an efficient video coding standard designed to transmit higher quality network video over limited bandwidth. Developers can output H.265 format video streams during encoding or stream mixing.

Note
  • ZEGO Express SDK has supported this feature since version 2.12.0 (released on 2021-09-09).
  • If you need to support H.265 video encoding, you need to upgrade all online ZEGO Express SDK versions to 2.12.0 or above, otherwise the online version may experience anomalies when decoding H.265.

The differences between H.265 and H.264 are as follows:

Difference ItemH.264H.265
Bitrate at same picture quality-H.265 can save 30% bitrate compared to H.264 (measured value).
Software encoding performance-H.265 consumes about 3 times the computing power of H.264.
Software decoding performance-H.265 consumes about 1.5 times the computing power of H.264.
Hardware ecosystemBasically all device models support hardware encoding and decoding.Most device models support hardware encoding, and the vast majority of device models support hardware decoding.
Stream mixing outputSupported.Supported, but the price is more expensive than H.264 stream mixing output. For details, please consult ZEGO business personnel.
Applicable scenariosAll scenarios.Recommended for live streaming and audio/video interactive scenarios.

Application Scenarios

H.265 encoding can be used in the following application scenarios:

Application Scenario TypeDescription
Show live streaming, e-commerce live streaming, interactive live streaming, gaming live streamingThrough H.265 encoding, reduce the bitrate by 30% (measured value) and distribute to thousands of viewers, greatly reducing CDN distribution costs.
Video call, video conference, online educationThrough H.265 encoding, improve picture clarity at the same bitrate, making call effects better in these scenarios.
Warning

Currently, Web and Mini Program platforms do not support H.265 stream playing.

Concept Explanation

  • Video encoding: A method of converting 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 from the cloud into one stream. It supports three methods: manual stream mixing, automatic stream mixing, and fully automatic stream mixing. For details, please refer to Stream Mixing.
  • Forward to CDN: The process of pushing audio and video streams from ZEGO audio and video cloud to CDN. For details, please refer to Publish/Play Streams via CDN.
  • Co-hosting: A form of interaction between users in a room. By pushing your own stream through the startPublishingStream interface while calling the startPlayingStream interface to pull the other party's stream, two users can engage in interactive calls after successfully co-hosting.

Service Activation

  1. When using stream mixing to output H.265 streams, you need to contact ZEGO technical support to activate the service.
  2. When using stream mixing to output H.265 streams, there are changes in billing. Please contact ZEGO business personnel for specific pricing information.

Example Source Code Download

Please refer to Download Example Source Code to obtain the source code.

For related source code, please check the files in the “/ZegoExpressExample/Examples/AdvancedStreaming/H265” directory.

Prerequisites

Before using the H.265 encoding and decoding feature, please ensure:

Implementation Method

Detect H.265 Encoding and Decoding Capabilities

Detect H.265 Encoding Capability

Some older or low-end mobile device models do not support H.265 video encoding. In this case, developers need to determine whether the local device supports H.265 video encoding capability through the isVideoEncoderSupported interface before streaming. Only if supported, the H.265 video encoding type can be set through the setVideoConfig interface before streaming, otherwise it will not take effect.

Detect H.265 Decoding Capability

Some older or low-end mobile device models do not support H.265 video decoding. In scenarios that support pulling different video streams, such as CDN scenarios, developers need to determine whether the local device supports H.265 video decoding capability through the isVideoDecoderSupported interface before playing stream. Only if supported, H.265 video streams can be pulled, otherwise only other format video streams can be pulled, such as H.264.

Co-hosting Stream Mixing Live Streaming

Co-hosting stream mixing live streaming includes the following two implementation methods. Developers can integrate as needed according to the actual situation:

  • Mix out streams of different formats (recommended): The stream mixing service directly outputs one H.265 mixed stream and one H.264 mixed stream. This scenario only requires one transcoding in the stream mixing service, without the need for CDN transcoding. Compared with stream mixing pushing to CDN for transcoding, it has higher clarity and lower cost, so it is recommended.
  • Stream mixing pushes to CDN for transcoding: The stream mixing service directly outputs one H.265 mixed stream, which needs to be transcoded by the CDN's transcoding capability to output one H.265 and one H.264 stream.
Warning

You need to contact ZEGO technical support to activate the CDN transcoding feature.

Mix out streams of different formats (recommended)

In this scenario, after the stream mixing service receives the streams from the host and co-hosting guests through ZEGOCLOUD, it directly outputs one H.265 mixed stream and one H.264 mixed stream, and pushes both streams to the CDN. The audience can choose to pull H.265 streams or H.264 streams from the CDN according to whether their terminal devices support H.265 video decoding.

  • Host Side

    1. Create a new stream mixing task object through the constructor ZegoMixerTask, and then call instance methods to set input, output and other parameters respectively.
    2. Set the input stream list for the stream mixing task through the inputList property in the stream mixing task object ZegoMixerTask (the encoding formats of streams in stream mixing input support H.264 and H.265), and supports up to 9 input streams by default. Please handle the stream layout yourself.
    3. Set the output stream list for the stream mixing task through the outputList property in the stream mixing task object ZegoMixerTask. Assuming the current scenario, the stream mixing service directly transcodes out 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.
    4. Call the startMixerTask interface to initiate the stream mixing task.
    5. The developer notifies the app's business server that the stream has been added.
    // Call startMixerTask to initiate stream mixing
    // Please enter taskID
    std::string taskID = “”;
    ZegoMixerTask task(mixerTaskID);
    
    // Please set videoConfig yourself
    ZegoMixerVideoConfig videoConfig;
    videoConfig.fps = 15;
    videoConfig.height = 720;
    videoConfig.width = 1280;
    task.videoConfig = videoConfig;
    
    ZegoMixerAudioConfig audioConfig;
    task.audioConfig = audioConfig;
    
    // Note, the encoding formats of streams in stream mixing input support H.264 and H.265, please handle stream layout and input yourself
    task.inputList = {};
    
    // Stream mixing two outputs
    // Note: The output target can be streamID or CDN address, the two are handled differently on the audience side, in this scenario it is recommended to directly pass in stremaID
    // Note: The bitrate in ZegoMixerOutput has higher priority than the bitrate in ZegoMixerVideoConfig
    std::string h264StreamID = “”; // Please enter h264StreamID
    std::string h265StreamID = “”; // Please enter h265StreamID
    // Please enter h264 bitrate, this bitrate is the recommended bitrate for the current resolution and frame rate (720p, 15fps)
    int h264Bitrate = 2244;
    // Please enter h265 bitrate, this bitrate is the recommended bitrate for the current resolution and frame rate (720p, 15fps)
    int h265Bitrate = 1795;
    
    // H.264 target
    ZegoMixerOutput mixer_output_h264;
    mixer_output_h264.target = h264StreamID;
    mixer_output_h264.videoConfig.bitrate = h264Bitrate;
    mixer_output_h264.videoConfig.videoCodecID = ZegoVideoCodecID::ZEGO_VIDEO_CODEC_ID_SVC;
    // H.265 target
    ZegoMixerOutput mixer_output_h265;
    mixer_output_h265.target = h265StreamID;
    mixer_output_h265.videoConfig.bitrate = h265Bitrate;
    mixer_output_h265.videoConfig.videoCodecID = ZegoVideoCodecID::ZEGO_VIDEO_CODEC_ID_H265;
    
    task.outputList = {
        mixer_output_h264,
        mixer_output_h265
    };
    
    engine->startMixerTask(task, [=](int errorCode, std::string extendData){
        // Stream mixing task callback
    });
    
    // The developer notifies the app's business server that the stream has been added
  • Audience Side

    1. The audience side receives a stream addition notification from the app's business server.
    2. Call the isVideoDecoderSupported interface to query whether the audience side's own device supports H.265 decoding format.
      • If supported, call the startPlayingStream interface to pull H.265 streams from the CDN.
      • If not supported, call the startPlayingStream interface to pull H.264 streams from the CDN.
    // Receive stream addition notification from the app's business server
    
    bool h265DecodeSupport = engine->isVideoDecoderSupported(ZegoVideoCodecID::ZEGO_VIDEO_CODEC_ID_H265);;
    // h264StreamID
    std::string h264StreamID = "";
    // h265StreamID
    std::string h265StreamID = "";
    //winId is the window handle
    ZegoCanvas canvas((void*)ui->playView->winId());
    
    if (h265DecodeSupport) {
        // Supports H.265 decoding
        engine->startPlayingStream(h265StreamID, &canvas);
    
    }
    else {
        // Does not support H.265 decoding
        engine->startPlayingStream(h264StreamID, &canvas);
    }

Stream mixing then push to CDN for transcoding

In this scenario, after the stream mixing service receives the streams from the host and co-hosting guests through ZEGOCLOUD, it directly outputs one H.265 mixed stream and pushes this mixed stream to the CDN. Through the CDN's transcoding capability, the audience can choose to pull H.265 streams or H.264 streams from the CDN according to whether their terminal devices support H.265 video decoding.

  • Host Side

    1. Create a new stream mixing task object through the constructor ZegoMixerTask, and then call instance methods to set input, output and other parameters respectively.
    2. Set the input stream list for the stream mixing task through the inputList property in the stream mixing task object ZegoMixerTask (the encoding formats of streams in stream mixing input support H.264 and H.265), and supports up to 9 input streams by default. Please handle the stream layout yourself.
    3. Set the output stream list for the stream mixing task through the outputList property in the stream mixing task object ZegoMixerTask. Assuming 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.
    4. Call the startMixerTask interface to initiate the stream mixing task.
    5. The developer notifies the app's business server that the stream has been added.
    // Call startMixerTask to initiate stream mixing
    // Please enter taskID
    std::string taskID = "";
    ZegoMixerTask task(mixerTaskID);
    
    // Please set videoConfig
    ZegoMixerVideoConfig videoConfig;
    videoConfig.fps = 15;
    videoConfig.height = 720;
    videoConfig.width = 1280;
    task.videoConfig = videoConfig;
    
    ZegoMixerAudioConfig audioConfig;
    task.audioConfig = audioConfig;
    
    // Note, the encoding formats of streams in stream mixing input support H.264 and H.265
    task.inputList = {};
    // Please enter CDN URL
    std::string publishCdnUrl = "";
    // Please enter h265 bitrate, this bitrate is the recommended bitrate for the current resolution and frame rate (720p, 15fps)
    int h265Bitrate = 1795;
    // Note, since CDN transcoding is required here, the target needs to be passed in as CDN URL
    ZegoMixerOutput outputH265;
    outputH265.target = publishCdnUrl;
    outputH265.videoConfig.bitrate = h265Bitrate;
    outputH265.videoConfig.videoCodecID = ZegoVideoCodecID::ZEGO_VIDEO_CODEC_ID_H265;
    
    task.outputList = {
        outputH265
    };
    
    engine->startMixerTask(task, [=](int errorCode, std::string extendData){
        // Stream mixing task callback
    });
    
    // The developer notifies the app's business server that the stream has been added
  • Audience Side

    1. The audience side receives a stream addition notification from the app's business server.
    2. Call the isVideoDecoderSupported interface to query whether the audience side's own device supports H.265 decoding format.
      • If supported, call the startPlayingStream interface to pull H.265 streams from the CDN.
      • If not supported, call the startPlayingStream interface to pull H.264 streams from the CDN.
    // Receive stream addition notification from the app's business server
    bool h265DecodeSupport = engine->isVideoDecoderSupported(ZegoVideoCodecID::ZEGO_VIDEO_CODEC_ID_H265);;
    
    std::string playStreamID = "";
    //winId is the window handle
    ZegoCanvas canvas((void*)ui->playView->winId());
    
    if (h265DecodeSupport) {
        // Supports H.265 decoding
        // Please fill in the H.265 URL address
        std::string h265Url = "";
    
        // Note: ZegoCDNConfig and ZegoPlayerConfig have other configurable options
        ZegoCDNConfig cdnConfig;
        // H.265 CDN playing address
        cdnConfig.url = h265Url;
        ZegoPlayerConfig playerConfig;
        playerConfig.cdnConfig = &cdnConfig;
        engine->startPlayingStream(playStreamID, &canvas, playerConfig);
    
      }
      else {
          // Does not support H.265 decoding
          // Please fill in the H264 URL address
          std::string h264Url = "";
    
          // Note: ZegoCDNConfig and ZegoPlayerConfig have other configurable options
          ZegoCDNConfig cdnConfig;
          // H.264 CDN playing address
          cdnConfig.url = h264Url;
        ZegoPlayerConfig playerConfig;
        playerConfig.cdnConfig = &cdnConfig;
        engine->startPlayingStream(playStreamID, &canvas, playerConfig);
    }

Single Host Live Streaming

Real-time Network Forward to CDN Live Streaming

This scenario has the following two characteristics:

  • The host forwards to the CDN through ZEGOCLOUD. Through the CDN's transcoding capability, the audience can choose to pull H.265 streams or H.264 streams from the CDN according to whether their terminal devices support H.265 video decoding.
  • When the host pushes H.265 streams, co-hosting guests pull streams directly from ZEGOCLOUD for real-time interaction. In this case, it is required that the co-hosting guests' terminal devices support H.265 video decoding capability.
  • Host Side
1

After creating the engine, call the enableHardwareEncoder interface to enable hardware encoding (if the configuration is changed after streaming, it will take effect only from the next streaming). After enabling, GPU will be used for encoding, reducing CPU usage.

2

Call the isVideoEncoderSupported interface to query whether the host side device supports the specified video encoding type.

3

Before streaming, call the setVideoConfig interface to set the video encoding format through codecID (if the configuration is changed after streaming, it will take effect only from the next streaming). If H.265 encoding is set, then:

1

You can call the enableH265EncodeFallback interface to enable automatic fallback to H.264 encoding when H.265 encoding fails (enabled by default). After enabling, when H.265 encoding is not supported or H.265 encoding fails, the SDK will internally try to downgrade to use H.264 encoding for streaming. After disabling, when H.265 encoding is not supported or H.265 encoding fails, streaming will directly fail.

2

Call the addPublishCdnUrl interface to add the URL address for forwarding the audio and video streams from ZEGOCLOUD to the CDN.

3

Call the startPublishingStream interface to start streaming. After streaming is successful, other users in the same room can get the stream addition status by listening to the onRoomStreamUpdate callback.

4

The developer notifies the app's business server of the encoding format of this stream, so that the playing side can make corresponding processing according to different streaming encoding formats.

// Mobile devices using H.265 encoding need to enable hardware encoding
engine->enableHardwareEncoder(true);
PrintLogToView("enableH265EncodeFallback:1");
engine->enableH265EncodeFallback(true);

// Query whether H.265 encoding is supported
bool h265EncoderSupport = engine->isVideoEncoderSupported(ZegoVideoCodecID::ZEGO_VIDEO_CODEC_ID_H265);;

ZegoVideoConfig videoConfig;
if (h265EncoderSupport) {
    // Supports H.265 encoding
    videoConfig.codecID = ZegoVideoCodecID::ZEGO_VIDEO_CODEC_ID_H265;
} else {
    // Does not support H.265 encoding
    videoConfig.codecID = ZegoVideoCodecID::ZEGO_VIDEO_CODEC_ID_DEFAULT;
}
engine->setVideoConfig(videoConfig);

if (h265EncoderSupport) {
    // Choose whether to enable H.265 encoding failure automatic fallback capability through enableH265EncodeFallback
    engine->enableH265EncodeFallback(true);
}
// Please enter streamID
std::string publishStreamID = "";
// Please enter CdnUrl
std::string publishCdnUrl = "";

// Add CDN forwarding address
engine->addPublishCdnUrl(publishStreamID, publishCdnUrl, [](int errorCode){
    // Determine whether the forwarding CDN address was added successfully
});

engine->startPublishingStream(publishStreamID);

// The developer notifies the app's business server of the encoding format of this stream, so that the playing side can make corresponding processing according to different streaming encoding formats
  • Audience Side

    1. After the host starts streaming, the audience side receives a stream addition notification through the onRoomStreamUpdate interface.
    2. The audience side obtains the encoding format of this stream from the app's business server.
    • If it is H.264 format, the audience can call the startPlayingStream interface to pull the host's stream directly from the CDN.
    • If it is H.265 format, they need to first call the isVideoDecoderSupported interface to query whether the audience side's own device supports H.265 decoding format.
      • If supported, call the startPlayingStream interface to pull H.265 streams from the CDN.
      • If not supported, call the startPlayingStream interface to pull H.264 streams from the CDN.
    //Receive stream addition notification onRoomStreamUpdate
    void H265::onRoomStreamUpdate(const std::string &currentRoomID, ZegoUpdateType updateType, const std::vector<ZegoStream> &streamList)
    {
        // Obtain the encoding format of this stream from the app's business server
        int videoCodecID = 0;
        // Please enter streamID
        std::string playStreamID = "";
        //winId is the window handle
        ZegoCanvas canvas((void*)ui->playView->winId());
    
        if (videoCodecID == ZegoVideoCodecID::ZEGO_VIDEO_CODEC_ID_H265) {
            // Encoding format is H.265, specific fallback strategy needs to be coordinated with advanced playing
            BOOL h265DecoderSupport = engine->isVideoDecoderSupported(ZegoVideoCodecID::ZEGO_VIDEO_CODEC_ID_H265);
    
            if (h265DecoderSupport) {
                // Supports H.265 decoding
                // Please fill in the H.265 URL address
                std::string h265Url = "";
                // Note: ZegoCDNConfig and ZegoPlayerConfig have other configurable options
                ZegoCDNConfig cdnConfig;
                // H.265 CDN playing address
                cdnConfig.url = h265Url;
                ZegoPlayerConfig playerConfig;
                playerConfig.cdnConfig = &cdnConfig;
                engine->startPlayingStream(playStreamID, &canvas, playerConfig);
    
            }
            else {
                // Does not support H.265 decoding
                // Please fill in the H264 URL address
                std::string h264Url = "";
                // Note: ZegoCDNConfig and ZegoPlayerConfig have other configurable options
                ZegoCDNConfig cdnConfig;
                // H.264 CDN playing address
                cdnConfig.url = h264Url;
                ZegoPlayerConfig playerConfig;
                playerConfig.cdnConfig = &cdnConfig;
                engine->startPlayingStream(playStreamID, &canvas, playerConfig);
            }
        }
        else if (videoCodecID == ZegoVideoCodecID::ZEGO_VIDEO_CODEC_ID_DEFAULT) {
            // Encoding format is H.264
            engine->startPlayingStream(playStreamID, canvas);
        }
    }
  • Co-hosting Guest Side

    1. After the host starts streaming, the co-hosting guest receives a stream addition notification through the onRoomStreamUpdate interface.
    2. The co-hosting guest obtains the encoding format of this stream from the app's business server.
    • If it is H.264 format, the co-hosting guest can call the startPlayingStream interface to pull the host's stream directly from ZEGOCLOUD.
    • If it is H.265 format, they need to first call the isVideoDecoderSupported interface to query whether their own device supports H.265 decoding format.
      • If supported, call the startPlayingStream interface to pull H.265 streams from ZEGOCLOUD.
      • If not supported, prompt that this terminal device does not support pulling this stream.
    //Receive stream addition notification onRoomStreamUpdate
    void H265::onRoomStreamUpdate(const std::string &currentRoomID, ZegoUpdateType updateType, const std::vector<ZegoStream> &streamList)
    {
        // Obtain the encoding format of this stream from the app's business server
        int videoCodecID = 0;
        // Please enter streamID
        std::string playStreamID = "";
        //winId is the window handle
        ZegoCanvas canvas((void*)ui->playView->winId());
        ZegoPlayerConfig playerConfig;
        playerConfig.resourceMode = ZEGO_STREAM_RESOURCE_MODE_ONLY_RTC; // Only pull streams from RTC
    
        if (videoCodecID == ZegoVideoCodecID::ZEGO_VIDEO_CODEC_ID_H265) {
            // Encoding format is H.265, specific fallback strategy needs to be coordinated with advanced playing
            bool h265DecoderSupport = engine_->isVideoDecoderSupported(ZegoVideoCodecID::ZEGO_VIDEO_CODEC_ID_H265);
    
            if (h265DecoderSupport) {
                // Supports H.265 decoding
                engine_->startPlayingStream(playStreamID, &canvas, playerConfig);
            }
        }
        else if (videoCodecID == ZegoVideoCodecID::ZEGO_VIDEO_CODEC_ID_DEFAULT) {
            // Encoding format is H.264
            engine_->startPlayingStream(playStreamID, &canvas, playerConfig);
        }
    }

Recording

If you use H.265 encoding and decoding functionality when performing local server recording, cloud recording, or data stream recording, it will affect the generation of recording files. Details are as follows:

When recording streams (H.265 video encoded streams), encoding downgrade may be triggered due to H.265 encoding failure. At this time, you will receive the onPublisherVideoEncoderChanged callback, indicating that the video encoding format has changed.

In this scenario, to avoid damaging the 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 new file generation rule is to add a timestamp to the original recording file name:

For example, if the original recording file path passed in 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.

Note

If the developer has received the onPublisherVideoEncoderChanged callback during recording, they need to collect other files in the recording file storage path after recording ends.

FAQ

  1. What to do if H.265 hardware encoding encounters an error?

You can call the enableH265EncodeFallback interface to enable the fallback function (enabled by default). If H.265 hardware encoding fails, it will downgrade to H.264. If you are using the recording function at the same time, the recording files will become two copies.

  1. Will H.265 automatically downgrade from hardware decoding to software decoding?

Yes, if hardware decoding fails during decoding, it will automatically downgrade to software decoding.

  1. How is H.265 priced?

Enabling H.265 functionality on the client side does not require additional fees, but stream mixing output H.265 requires stream mixing fees, which is more expensive than stream mixing output H.264. For details, please consult ZEGO business personnel.

  1. Is there any change in billing when mixing H.265 stream input and H.264 stream output?

No change, billing is based on H.264 output.

  1. What are the hardware requirements for H.265 decoding?

Currently, all device models on the market support H.265 decoding. Testing shows that low-end device models from before 2013 may experience frame rate fluctuations during decoding.

2024-01-02

Previous

Custom Video Preprocessing

Next

Video Small/Large Stream and Layered Encoding