logo
Video Call
On this page

H.265

2024-01-02

Feature Overview

Feature Description

H.265 is an efficient video coding standard designed to transmit higher quality network video under limited bandwidth. Developers can output H.265 format video bitstreams 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 SDKs to version 2.12.0 or above, otherwise online version decoding of H.265 may cause abnormalities.

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

Difference ItemH.264H.265
Bitrate under same image quality-H.265 can save 30% bitrate compared to H.264 (measured value).
Soft encoding performance-H.265 consumes about 3 times the computing power of H.264.
Soft decoding performance-H.265 consumes about 1.5 times the computing power of H.264.
Hardware ecosystemBasically all models support hard encoding and hard decoding.Most models support hard encoding, and the vast majority of models support hard 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 use in live streaming and audio/video interaction scenarios.

Application Scenarios

In the following application scenarios, H.265 can be used for encoding:

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

Currently, Web and mini-program platforms do not support H.265 play stream.

Concept Explanation

  • Video encoding: A way to convert 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.
  • Forwarding to CDN: The process of pushing audio and video streams from ZEGO audio and video cloud to CDN. For details, please refer to Push/Play Stream Through CDN.
  • Co-hosting: A form of interaction between users in a Room. While pushing their own stream through the startPublishingStream interface, they also call the startPlayingStream interface to pull the other party's stream. After two users successfully co-host, they can conduct interactive calls.

Service Activation

  1. When using stream mixing to output H.265 bitstreams, you need to contact ZEGO Technical Support to activate the service.
  2. When using stream mixing to output H.265 bitstreams, there are changes in billing. Please contact ZEGO business personnel to understand the specific cost situation.

Example Source Code Download

Please refer to Download Example Source Code to get 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 Capability

Detect H.265 Encoding Capability

Some older or low-end mobile models do not support H.265 video encoding. At this time, developers need to before publishing stream first judge through the isVideoEncoderSupported interface whether the local device supports H.265 video encoding capability. If supported, the H.265 video encoding type can be set 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 that support pulling different video bitstreams, such as CDN scenarios, developers need to before playing stream first judge through the isVideoDecoderSupported interface whether the local device supports H.265 video decoding capability. If supported, H.265 video bitstreams can be pulled, otherwise only other format video bitstreams 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 choose to integrate according to actual needs:

  • Mix different format bitstreams (recommended): The 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, no need for CDN transcoding again. Compared with stream mixing push CDN transcoding, it has higher clarity and is cheaper, so it is recommended.
  • Stream mixing push CDN transcoding: The 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.
Warning

You need to contact ZEGO Technical Support to activate the CDN transcoding feature.

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 CDN. The audience can choose to pull H.265 bitstreams or H.264 bitstreams from CDN according to whether their own terminal devices support H.265 video decoding.

  • Host end

    1. Create a new stream mixing task object through the constructor ZegoMixerTask, then call instance methods to set input, output and other parameters respectively.
    2. Set the stream mixing task input stream list through the setInputList property in the stream mixing task object ZegoMixerTask (the encoding format of streams in stream mixing input supports H.264 and H.265), by default supports up to 9 streams input, please handle the stream layout yourself.
    3. Set the stream mixing task output stream list through the setOutputList property in the stream mixing 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.
    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
    String taskID = "";
    ZegoMixerTask task = new ZegoMixerTask(taskID);
    
    // Please set videoConfig yourself
    ZegoMixerVideoConfig videoConfig = new ZegoMixerVideoConfig(720, 1280, 15, 1500);
    task.setVideoConfig(videoConfig);
    
    task.setAudioConfig(new ZegoMixerAudioConfig());
    
    // Note, the encoding format of streams in stream mixing input supports H.264 and H.265, please handle stream layout and input yourself
    ArrayList<ZegoMixerInput> inputList = new ArrayList<>();
    task.setInputList(inputList);
    
    // Stream mixing two outputs
    // Note: output target can be streamID or CDN address, the two are handled differently at the audience end, this scenario recommends directly passing in streamID
    // Note: The bitrate in ZegoMixerOutput has higher priority than the bitrate in ZegoMixerVideoConfig
    // Please enter h264StreamID
    String h264StreamID = "";
    // Please enter h265StreamID
    String 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;
    ArrayList<ZegoMixerOutput> outputList = new ArrayList<>();
    ZegoMixerOutput outputH264 = new ZegoMixerOutput(h264StreamID);
    ZegoMixerOutputVideoConfig outputH264VideoConfig = new ZegoMixerOutputVideoConfig
    (ZegoVideoCodecID.getZegoVideoCodecID(0), h264Bitrate);
    outputH264.setVideoConfig(outputH264VideoConfig);
    outputList.add(outputH264);
    ZegoMixerOutput outputH265 = new ZegoMixerOutput(h265StreamID);
    ZegoMixerOutputVideoConfig outputH265VideoConfig = new ZegoMixerOutputVideoConfig
    (ZegoVideoCodecID.getZegoVideoCodecID(3), h265Bitrate);
    outputH265.setVideoConfig(outputH265VideoConfig);
    outputList.add(outputH265);
    task.setOutputList(outputList);
    
    // Start stream mixing
    engine.startMixerTask(task, new IZegoMixerStartCallback() {
    
        @Override
        public void onMixerStartResult(int errorCode, JSONObject var2) {
            // Stream mixing task callback
        }
    });
    // Developer notifies App's business server that the stream has been added
  • Audience end

    1. The audience end receives the stream addition notification from the App's business server.
    2. Call the isVideoDecoderSupported interface to query whether the audience end's own device supports H.265 decoding format.
    // Receive stream addition notification from App's business server
    
    boolean h265DecoderSupport = engine.isVideoDecoderSupported(ZegoVideoCodecID.getZegoVideoCodecID(3));
    // h264StreamID
    String h264StreamID = "";
    // h265StreamID
    String h265StreamID = "";
    // View needed for play stream rendering
    View view = playView;
    ZegoCanvas playCanvas = new ZegoCanvas(view);
    
    if (h265DecoderSupport) {
        // Support H.265 decoding
        engine.startPlayingStream(h265StreamID, playCanvas);
    }
    else {
        // Does not support H.265 decoding
        engine.startPlayingStream(h264StreamID, playCanvas);
    }

Stream mixing then push 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 CDN. Through CDN's transcoding capability, the audience can choose to pull H.265 bitstreams or H.264 bitstreams from CDN according to whether their own terminal devices support H.265 video decoding.

  • Host end

    1. Create a new stream mixing task object through the constructor ZegoMixerTask, then call instance methods to set input, output and other parameters respectively.
    2. Set the stream mixing task input stream list through the setInputList property in the stream mixing task object ZegoMixerTask (the encoding format of streams in stream mixing input supports H.264 and H.265), by default supports up to 9 streams input, please handle the stream layout yourself.
    3. Set the stream mixing task output stream list through the setOutputList property in the stream mixing 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.
    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
    String taskID = "";
    ZegoMixerTask task = new ZegoMixerTask(taskID);
    
    // Please set videoConfig yourself
    ZegoMixerVideoConfig videoConfig = new ZegoMixerVideoConfig(720, 1280, 15, 1500);
    task.setVideoConfig(videoConfig);
    
    task.setAudioConfig(new ZegoMixerAudioConfig());
    
    // Note, the encoding format of streams in stream mixing input supports H.264 and H.265, please handle stream layout and input yourself
    ArrayList<ZegoMixerInput> inputList = new ArrayList<>();
    task.setInputList(inputList);
    // Please enter CDN URL
    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 needed here, target needs to pass in CDN URL
    ArrayList<ZegoMixerOutput> outputList = new ArrayList<>();
    
    ZegoMixerOutput outputH265 = new ZegoMixerOutput(publishCdnUrl);
    ZegoMixerOutputVideoConfig outputH265VideoConfig = new ZegoMixerOutputVideoConfig
    (ZegoVideoCodecID.getZegoVideoCodecID(3), h265Bitrate);
    outputH265.setVideoConfig(outputH265VideoConfig);
    outputList.add(outputH265);
    task.setOutputList(outputList);
    
    // Start stream mixing
    engine.startMixerTask(task, new IZegoMixerStartCallback() {
    
        @Override
        public void onMixerStartResult(int errorCode, JSONObject var2) {
            // Stream mixing task callback
        }
    });
    
    // Developer notifies App's business server that the stream has been added
  • Audience end

    1. The audience end receives the stream addition notification from the App's business server.
    2. Call the isVideoDecoderSupported interface to query whether the audience end's own device supports H.265 decoding format.
    // Receive stream addition notification from App's business server
    
    boolean h265DecoderSupport = engine.isVideoDecoderSupported(ZegoVideoCodecID.getZegoVideoCodecID(3));
    
    String playStreamID = "";
    // View needed for play stream rendering
    View view = playView;
    ZegoCanvas playCanvas = new ZegoCanvas(view);
    
    if (h265DecoderSupport) {
        // Support H.265 decoding
        // Please fill in H.265 Url address
        String h265Url = "";
    
        // Note: ZegoCDNConfig and ZegoPlayerConfig have other configurable items
        ZegoCDNConfig cdnConfig = new ZegoCDNConfig();
        // H.265 CDN play stream address
        cdnConfig.url = h265Url;
        ZegoPlayerConfig playerConfig = new ZegoPlayerConfig();
        playerConfig.cdnConfig = cdnConfig;
        engine.startPlayingStream(playStreamID, playCanvas, playerConfig);
    }
    else {
        // Does not support H.265 decoding
        // Please fill in H.264 Url address
        String h264Url = "";
    
        // Note: ZegoCDNConfig and ZegoPlayerConfig have other configurable items
        ZegoCDNConfig cdnConfig = new ZegoCDNConfig();
        // H.264 CDN play stream address
        cdnConfig.url = h264Url;
        ZegoPlayerConfig playerConfig = new ZegoPlayerConfig();
        playerConfig.cdnConfig = cdnConfig;
        engine.startPlayingStream(playStreamID, playCanvas, playerConfig);
    }

Single Host Live Streaming

Real-time Network Forward CDN Live Streaming

This scenario has the following two characteristics:

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

After creating the Engine, call the enableHardwareEncoder interface to enable hardware encoding (if you change the configuration 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.

2

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

3

Call the setVideoConfig interface to set the video encoding format through codecID (if you change the configuration after publishing stream, you need to wait for the next publishing stream to take effect). 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 publishing. After disabling, when H.265 encoding is not supported or H.265 encoding fails, publishing will fail directly.

2

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

3

Call the startPublishingStream interface to start publishing stream. After the publishing is successful, other users in the same Room can obtain the stream addition situation by listening to the onRoomStreamUpdate callback.
4

The developer notifies the App's business server of the encoding format of this published stream, so as to notify the play stream end to handle accordingly according to different published encoding formats.
// Mobile devices using H.265 encoding need to enable hardware encoding
engine.enableHardwareEncoder(true);

// Query whether H.265 encoding is supported
boolean h265EncoderSupport = engine.isVideoEncoderSupported(ZegoVideoCodecID.getZegoVideoCodecID(3));

ZegoVideoConfig videoConfig = new ZegoVideoConfig();
if (h265EncoderSupport) {
    // Support H.265 encoding
    videoConfig.codecID = ZegoVideoCodecID.getZegoVideoCodecID(3);
} else {
    // Does not support H.265 encoding
    videoConfig.codecID = ZegoVideoCodecID.getZegoVideoCodecID(0);
}
engine.setVideoConfig(videoConfig);

if (h265EncoderSupport) {
    // Through enableH265EncodeFallback, choose whether to enable automatic fallback capability when H.265 encoding fails
    engine.enableH265EncodeFallback(true);
}
// Please enter streamID
String publishStreamID = "";
// Please enter CdnUrl
String publishCdnUrl = "";
// Add CDN forwarding address
engine.addPublishCdnUrl(publishCdnUrl, publishStreamID, new IZegoPublisherUpdateCdnUrlCallback() {
    @Override
    public void onPublisherUpdateCdnUrlResult(int i) {
        // Judge whether the forwarding CDN address was added successfully
    }
});
engine.startPublishingStream(publishStreamID);

// Developer notifies App's business server of the encoding format of this published stream, so as to notify the play stream end to handle accordingly according to different published encoding formats
  • Audience end

    1. After the host publishes stream, the audience end receives the stream addition notification through the onRoomStreamUpdate interface.
    2. The audience end obtains the encoding format of this published stream from the App's business server.
      • If it is H.264 format, the audience can call the startPlayingStream interface to pull the host end's stream directly from CDN.
      • If it is H.265 format, you need to first call the isVideoDecoderSupported interface to query whether the audience end's own device supports H.265 decoding format.
    // Receive stream addition notification onRoomStreamUpdate
    @Override
    public void onRoomStreamUpdate(String roomID, ZegoUpdateType updateType, ArrayList<ZegoStream> streamList, JSONObject extendedData) {
        super.onRoomStreamUpdate(roomID, updateType, streamList, extendedData);
        // Obtain the encoding format of this stream from the App's business server
        int videoCodecID = 0;
        // Please enter streamID
        String playStreamID = "";
        // View needed for play stream rendering
        View view = playView;
        ZegoCanvas playCanvas = new ZegoCanvas(view);
    
        if (videoCodecID == ZegoVideoCodecID.getZegoVideoCodecID(3).value()) {
            // Encoding format is H.265
            boolean h265DecoderSupport = engine.isVideoDecoderSupported(ZegoVideoCodecID.getZegoVideoCodecID(3));
    
            // If decoding is not supported, do not pull stream
            if (h265DecoderSupport) {
                // Support H.265 decoding
                // Please fill in H.265 Url address
                String h265Url = "";
    
                // Note: ZegoCDNConfig and ZegoPlayerConfig have other configurable items
                ZegoCDNConfig cdnConfig = new ZegoCDNConfig();
                // H.265 CDN play stream address
                cdnConfig.url = h265Url;
                ZegoPlayerConfig playerConfig = new ZegoPlayerConfig();
                playerConfig.cdnConfig = cdnConfig;
                engine.startPlayingStream(playStreamID, playCanvas, playerConfig);
            } else {
                // Does not support H.265 decoding
                // Please fill in H.264 Url address
                String h264Url = "";
    
                // Note: ZegoCDNConfig and ZegoPlayerConfig have other configurable items
                ZegoCDNConfig cdnConfig = new ZegoCDNConfig();
                // H.264 CDN play stream address
                cdnConfig.url = h264Url;
                ZegoPlayerConfig playerConfig = new ZegoPlayerConfig();
                playerConfig.cdnConfig = cdnConfig;
                engine.startPlayingStream(playStreamID, playCanvas, playerConfig);
            }
        }
        else if (videoCodecID == ZegoVideoCodecID.getZegoVideoCodecID(0).value()) {
            // Encoding format is H.264
            engine.startPlayingStream(playStreamID, playCanvas);
        }
    }
  • Co-hosting guest end

    1. After the host publishes stream, co-hosting guests receive the stream addition notification through the onRoomStreamUpdate interface.
    2. Co-hosting guests obtain the encoding format of this published stream from the App's business server.
      • If it is H.264 format, co-hosting guests can call the startPlayingStream interface to pull the host end's stream directly from ZEGOCLOUD.
      • If it is H.265 format, you 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 bitstreams from ZEGOCLOUD.
        • If not supported, prompt that this terminal device does not support pulling this stream.
    // Receive stream addition notification onRoomStreamUpdate
    @Override
    public void onRoomStreamUpdate(String roomID, ZegoUpdateType updateType, ArrayList<ZegoStream> streamList, JSONObject extendedData) {
        super.onRoomStreamUpdate(roomID, updateType, streamList, extendedData);
        // Obtain the encoding format of this stream from the App's business server
        int videoCodecID = 0;
        // Please enter streamID
        String playStreamID = "";
        // View needed for play stream rendering
        View view = playView;
        ZegoCanvas playCanvas = new ZegoCanvas(view);
        ZegoPlayerConfig config = new ZegoPlayerConfig();
        config.resourceMode = ZegoStreamResourceMode.ONLY_RTC; // Only pull stream from RTC
    
        if (videoCodecID == ZegoVideoCodecID.getZegoVideoCodecID(3).value()) {
            // Encoding format is H.265
            boolean h265DecoderSupport = engine.isVideoDecoderSupported(ZegoVideoCodecID.getZegoVideoCodecID(3));
    
            // If decoding is not supported, do not pull stream
            if (h265DecoderSupport) {
                // Support H.265 decoding
                engine.startPlayingStream(playStreamID, playCanvas, config);
            }
        }
        else if (videoCodecID == ZegoVideoCodecID.getZegoVideoCodecID(0).value()) {
            // Encoding format is H.264
            engine.startPlayingStream(playStreamID, playCanvas, config);
         }
     }

Recording

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

When recording the published stream (H.265 video encoding bitstream), it may trigger encoding fallback 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 generation rule for the new file 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 storage path of the recording files after the recording ends.

FAQ

  1. What to do when H.265 encounters errors in hardware encoding?

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

  1. 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.

  1. How is H.265 charged?

Clients enabling the H.265 feature do not need to pay, but stream mixing output H.265 needs to charge stream mixing fees, which is more expensive than stream mixing output H.264. For details, please consult ZEGO business personnel.

  1. Is there a change in billing when stream mixing inputs H.265 streams and outputs H.264 streams?

No change, billed as H.264 output.

  1. 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 around 2013 may have frame rate fluctuations during decoding.

Previous

Object Segmentation

Next

Video Small-Large Stream and Layered Encoding