# H.265

- - -

## 功能简介

### 功能描述

H.265 是一种高效的视频编码标准，旨在有限带宽下传输更高质量的网络视频。开发者可以在编码或混流时输出 H.265 格式的视频码流。

<Note title="说明">


- ZEGO Express SDK 从 2.12.0 版本（2021-09-09 发布）开始支持该功能。
- 如果您需要支持 H.265 视频编码，则需要将线上的 ZEGO Express SDK 都升级到 2.12.0 或以上版本，否则线上版本解码 H.265 可能会出现异常。
</Note>

H.265 和 H.264 的区别如下：

<table>

  <tbody><tr>
    <th>差异项</th>
    <th>H.264</th>
    <th>H.265</th>
  </tr>
  <tr>
    <td>同等画质下的码率</td>
    <td>-</td>
    <td>H.265 相比于 H.264 可以节约 30% 码率（实测值）。</td>
  </tr>
  <tr>
    <td>软编性能</td>
    <td>-</td>
    <td>H.265&nbsp;消耗的算力是 H.264 的 3 倍左右。</td>
  </tr>
  <tr>
    <td>软解性能</td>
    <td>-</td>
    <td>H.265&nbsp;消耗的算力是 H.264 的 1.5 倍左右。</td>
  </tr>
  <tr>
    <td>硬件生态</td>
    <td>所有机型基本都支持硬编和硬解。</td>
    <td>大部分机型都支持硬编，绝大部分机型都支持硬解。</td>
  </tr>
  <tr>
    <td>混流输出</td>
    <td>支持。</td>
    <td>支持，但价格比 H.264 混流输出更贵，详情可咨询 ZEGO 商务人员。</td>
  </tr>
  <tr>
    <td>适用场景</td>
    <td>所有场景。</td>
    <td>推荐在直播和音视频互动场景使用。</td>
  </tr>
</tbody></table>


### 应用场景
 在如下应用场景中，可使用 H.265 进行编码：

<table>

<tbody><tr>
<th>应用场景类型</th>
<th>说明</th>
</tr>
<tr>
<td>秀场直播、电商直播、互动直播、游戏直播</td>
<td>通过 H.265 编码，将码率降低 30% 码率（实测值），分发给万千观众，极大降低 CDN 分发成本。</td>
</tr>
<tr>
<td>视频通话、视频会议、在线教育</td>
<td>通过 H.265 编码，在同等码率下，提高画面清晰度，让这些场景通话效果更好。</td>
</tr>
</tbody></table>
<Warning title="注意">



目前 Web 和小程序平台，不支持 H.265 拉流。
</Warning>


### 概念解释

- 视频编码：通过特定的压缩技术，将原始视频格式的文件转换成另一种视频格式的方式，便于传输和存储。
- 混流：是一种把多路音视频流从云端混合成一路流的技术，支持手动混流、自动混流和全自动混流三种方式，详情请参考 [混流](/real-time-video-ios-oc/live-streaming/stream-mixing)。
- 转推 CDN：将音视频流从 ZEGO 音视频云推送到 CDN 的过程，详情请参考 [通过 CDN 推流/拉流](/real-time-video-ios-oc/live-streaming/using-cdn-for-live-streaming)。
- 连麦：是房间内用户之间互动的一种形式，通过 [startPublishingStream](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoExpressEngine#start-publishing-stream) 接口推自己流的同时，也调用 [startPlayingStream](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoExpressEngine#start-playing-stream-canvas) 接口拉对方的流，两个用户连麦成功之后即可进行互动通话。


## 服务开通

1. 使用混流输出 H.265 码流时，需要联系 ZEGO 技术支持开通服务。
2. 使用混流输出 H.265 码流时，计费有变化，请联系 ZEGO 商务人员了解具体的费用情况。

## 示例源码下载

请参考 [下载示例源码](/real-time-video-ios-oc/quick-start/run-example-code) 获取源码。

相关源码请查看 “/ZegoExpressExample/Examples/AdvancedStreaming/H265” 目录下的文件。

## 前提条件

在使用 H.265 编解码功能之前，请确保：

- 已在 [ZEGO 控制台](https://console.zego.im) 创建项目，并申请有效的 AppID 和 AppSign，详情请参考 [控制台 - 项目信息](/console/project-info)。
- 已在项目中集成 ZEGO Express SDK，并实现了基本的音视频推拉流功能，详情请参考 [快速开始 - 集成](/real-time-video-ios-oc/quick-start/integrating-sdk) 和 [快速开始 - 实现流程](/real-time-video-ios-oc/quick-start/implementing-video-call)。


## 实现方法

### 检测 H.265 编解码能力

#### 检测 H.265 编码能力

一些老的或低端的移动机型，不支持 H.265 视频**编码**。此时开发者需要在**推流前**先通过 [isVideoEncoderSupported](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoExpressEngine#is-video-encoder-supported) 接口判断本机是否支持 H.265 视频编码能力。如果支持，才能在推流前通过 [setVideoConfig](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoMixerOutput#set-video-config) 接口设置 H.265 视频编码类型，否则不生效。

#### 检测 H.265 解码能力

一些老的或低端的移动机型，不支持 H.265 视频**解码**。在支持拉不同视频码流的场景下，如 CDN 场景，开发者需要在**拉流前**先通过 [isVideoDecoderSupported](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoExpressEngine#is-video-decoder-supported) 接口判断本机是否支持 H.265 视频解码能力。如果支持，才能拉 H.265 视频码流，否则只能拉其他格式的视频码流，例如 H.264。

### 连麦混流直播

连麦混流直播包括如下两种实现方式，开发者可以根据实际情况按需接入：
- 混出不同格式的码流（推荐）：混流服务直接输出一路 H.265 混流和一路 H.264 混流，该场景只需要在混流服务进行一次转码，无需 CDN 再转码。相比于混流推 CDN 转码，具有更高的清晰度，费用也更便宜，推荐使用。
- 混流推 CDN 转码：混流服务直接输出一路 H.265 混流，需要通过 CDN 的转码能力，转出一路 H.265 和一路 H.264 码流。

   <Warning title="注意">


   需要联系 ZEGO 技术支持开通 CDN 转码功能。
  </Warning>



#### 混出不同格式的码流（推荐）

该场景下，混流服务通过 ZEGO 实时音视频云接收到主播和连麦嘉宾的推流后，直接输出一路 H.265 混流和一路 H.264 混流，并把两路流都推流到 CDN，观众可以根据自身终端设备是否支持 H.265 视频解码，选择从 CDN 拉 H.265 码流或 H.264 码流。

<Frame width="512" height="auto" caption="">
  <img src="https://doc-media.zego.im/sdk-doc/Pics/LiveRoom/H265/Mix.png" />
</Frame>

- **主播端**

  1. 通过构造函数 [ZegoMixerTask](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoMixerTask) 新建一个混流任务对象，然后调用实例方法分别设置输入、输出等参数。
  2. 通过混流任务对象 [ZegoMixerTask](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoMixerTask) 中的 [setInputList](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoMixerTask#set-input-list) 属性设置混流任务输入流列表（混流输入中流的编码格式支持 H.264 和 H.265 ），默认最多支持输入 9 路流，请自行处理流布局。
  3. 通过混流任务对象 [ZegoMixerTask](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoMixerTask) 中的 [setOutputList](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoMixerTask#set-output-list) 属性设置混流任务输出流列表。假设当前场景下，混流服务直接转码出一路 H.264 混流和一路 H.265混流，即混流输出视频编码格式为 H.264 和 H.265。
  4. 调用 [startMixerTask](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoExpressEngine#start-mixer-task-callback) 接口发起混流任务。
  5. 开发者通知 App 的业务服务端流已新增。

  ```objc
  // 调用 startMixerTask 发起混流
  // 请输入 taskID
  NSString *taskID = @"";
  ZegoMixerTask *task = [[ZegoMixerTask alloc] initWithTaskID:taskID];

  // 请自行设置 videoConfig
  CGSize resolution = CGSizeMake(720, 1280);
  int fps = 15;
  int bitrate = 1500;

  ZegoMixerVideoConfig *videoConfig = [[ZegoMixerVideoConfig alloc] initWithResolution:resolution fps:fps bitrate:bitrate];
  [task setVideoConfig:videoConfig];

  [task setAudioConfig:[ZegoMixerAudioConfig defaultConfig]];

  // 注意，混流输入中流的编码格式支持 H.264 和 H.265, 请自行处理流布局及输入
  NSArray<ZegoMixerInput *> *inputArray = [NSArray new];
  [task setInputList:inputArray];

  // 混流两路输出
  // 注意: 输出 target 可以是 streamID 或 CDN 地址，二者在观众端处理方式不同，该场景推荐直接传入 stremaID
  // 注意: ZegoMixerOutput 中的码率优先级高于 ZegoMixerVideoConfig 中的码率
  NSString *h264StreamID = @""; // 请输入 h264StreamID
  NSString *h265StreamID = @""; // 请输入 h265StreamID
  // 请输入 h264 码率，此码率为当前分辨率帧率(720p, 15fps)的推荐码率
  int h264Bitrate = 2244;
  // 请输入 h265 码率，此码率为当前分辨率帧率(720p, 15fps)的推荐码率
  int h265Bitrate = 1795;
  ZegoMixerOutput *outputH264 = [[ZegoMixerOutput alloc] initWithTarget:h264StreamID];
  ZegoMixerOutputVideoConfig *outputH264VideoConfig = [[ZegoMixerOutputVideoConfig alloc] init];
  [outputH264VideoConfig configWithCodecID:ZegoVideoCodecIDDefault bitrate:h264Bitrate];
  [outputH264 setVideoConfig:outputH264VideoConfig];

  ZegoMixerOutput *outputH265 = [[ZegoMixerOutput alloc] initWithTarget:h265StreamID];
  ZegoMixerOutputVideoConfig *outputH265VideoConfig = [ZegoMixerOutputVideoConfig new];
  [outputH265VideoConfig configWithCodecID:ZegoVideoCodecIDH265 bitrate:h265Bitrate];
  [outputH265 setVideoConfig:outputH265VideoConfig];

  NSArray<ZegoMixerOutput *> *outputArray = @[outputH264, outputH265];
  [task setOutputList:outputArray];

  [[ZegoExpressEngine sharedEngine] startMixerTask:task callback:^(int errorCode, NSDictionary * _Nullable extendedData) {
      // 混流任务回调
  }];

  // 开发者通知 App 的业务服务端流已新增
  ```

 - **观众端**

   1. 观众端从 App 的业务服务端收到流新增通知。
   2. 调用 [isVideoDecoderSupported](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoExpressEngine#is-video-decoder-supported) 接口查询观众端自身设备是否支持 H.265 解码格式。
      - 若支持，则调用 [startPlayingStream](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoExpressEngine#start-playing-stream-canvas) 接口从 CDN 拉 H.265 码流。
      - 若不支持，则调用 [startPlayingStream](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoExpressEngine#start-playing-stream-canvas) 接口从 CDN 拉 H.264 码流。

   ```objc
   // 从 App 的业务服务端收到流新增通知

   BOOL h265DecodeSupport = [[ZegoExpressEngine sharedEngine] isVideoDecoderSupported:ZegoVideoCodecIDH265];
   // h264StreamID
   NSString *h264StreamID = @"";
   // h265StreamID
   NSString *h265StreamID = @"";
   // 拉流需要渲染的 view
   UIView *playView;
   ZegoCanvas *playCanvas = [ZegoCanvas canvasWithView:playView];

   if (h265DecodeSupport) {
       // 支持 H.265 解码
       [[ZegoExpressEngine sharedEngine] startPlayingStream:h265StreamID canvas:playCanvas];

   }
   else {
       // 不支持 H.265 解码
       [[ZegoExpressEngine sharedEngine] startPlayingStream:h264StreamID canvas:playCanvas];
   }
   ```

#### 混流后推 CDN 再转码

该场景下，混流服务通过 ZEGO 实时音视频云接收到主播和连麦嘉宾的推流后，直接输出一路 H.265 混流，并把这路混流推流到 CDN，通过 CDN 的转码能力，观众可以根据自身终端设备是否支持 H.265 视频解码，选择从 CDN 拉 H.265 码流或 H.264 码流。

<Frame width="512" height="auto" caption="">
  <img src="https://doc-media.zego.im/sdk-doc/Pics/LiveRoom/H265/MixCDN.png" />
</Frame>

- **主播端**

  1. 通过构造函数 [ZegoMixerTask](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoMixerTask) 新建一个混流任务对象，然后调用实例方法分别设置输入、输出等参数。
  2. 通过混流任务对象 [ZegoMixerTask](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoMixerTask) 中的 [setInputList](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoMixerTask#set-input-list) 属性设置混流任务输入流列表（混流输入中流的编码格式支持 H.264 和 H.265 ），默认最多支持输入 9 路流，请自行处理流布局。
  3. 通过混流任务对象 [ZegoMixerTask](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoMixerTask) 中的 [setOutputList](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoMixerTask#set-output-list) 属性设置混流任务输出流列表。假设当前场景下，混流服务直接输出一路 H.265 混流，即混流输出视频编码格式为H.265。
  4. 调用 [startMixerTask](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoExpressEngine#start-mixer-task-callback) 接口发起混流任务。
  5. 开发者通知 App 的业务服务端流已新增。

  ```objc
  // 调用 startMixerTask 发起混流
  // 请输入 taskID
  NSString *taskID = @"";
  ZegoMixerTask *task = [[ZegoMixerTask alloc] initWithTaskID:taskID];

  // 请设置 videoConfig
  CGSize resolution = CGSizeMake(720, 1280);
  int fps = 15;
  int bitrate = 1500;

  ZegoMixerVideoConfig *videoConfig = [[ZegoMixerVideoConfig alloc] initWithResolut ion:resolution fps:fps bitrate:bitrate];
  [task setVideoConfig:videoConfig];

  [task setAudioConfig:[ZegoMixerAudioConfig defaultConfig]];

  // 注意，混流输入中流的编码格式支持 H.264 和 H.265
  NSArray<ZegoMixerInput *> *inputArray = [NSArray new];
  [task setInputList:inputArray];
  // 请输入 CDN URL
  NSString *publishCdnUrl = @"";
  // 请输入 h265 码率，此码率为当前分辨率帧率(720p, 15fps)的推荐码率
  int h265Bitrate = 1795;
  // 注意，由于这里需要使用 CDN 转码， target 需要传入 CDN URL
  ZegoMixerOutput *outputH265 = [[ZegoMixerOutput alloc] initWithTarget:publishCdnUrl];
  ZegoMixerOutputVideoConfig *outputH265VideoConfig = [ZegoMixerOutputVideoConfig new];
  [outputH265VideoConfig configWithCodecID:ZegoVideoCodecIDH265 bitrate:h265Bitrate];
  [outputH265 setVideoConfig:outputH265VideoConfig];

  NSArray<ZegoMixerOutput *> *outputArray = @[outputH265];
  [task setOutputList:outputArray];

  [[ZegoExpressEngine sharedEngine] startMixerTask:task callback:^(int errorCode, NSDictionary * _Nullable extendedData) {
      // 混流任务回调
  }];

  // 开发者通知 App 的业务服务端流已新增
  ```


- **观众端**

  1. 观众端从 App 的业务服务端收到流新增通知。
  2. 调用 [isVideoDecoderSupported](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoExpressEngine#is-video-decoder-supported) 接口查询观众端自身设备是否支持 H.265 解码格式。
      - 若支持，则调用 [startPlayingStream](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoExpressEngine#start-playing-stream-canvas) 接口从 CDN 拉 H.265 码流。
      - 若不支持，则调用 [startPlayingStream](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoExpressEngine#start-playing-stream-canvas) 接口从 CDN 拉 H.264 码流。

   ```objc
   // 从 App 的业务服务端收到流新增通知
   BOOL h265DecodeSupport = [[ZegoExpressEngine sharedEngine] isVideoDecoderSupported:ZegoVideoCodecIDH265];
   NSString *playStreamID = @"";
   // 拉流需要渲染的 view
   UIView *playView;
   ZegoCanvas *playCanvas = [ZegoCanvas canvasWithView:playView];
   if (h265DecodeSupport) {
       // 支持 H.265 解码
       // 请填入 H.265 Url 地址
       NSString *h265Url = @"";

       // 注意: ZegoCDNConfig 和 ZegoPlayerConfig 中有其他的可配置项
       ZegoCDNConfig *cdnConfig = [ZegoCDNConfig new];
       // H.265 CDN 拉流地址
       cdnConfig.url = h265Url;
       ZegoPlayerConfig *playerConfig = [ZegoPlayerConfig new];
       playerConfig.cdnConfig = cdnConfig;
       [[ZegoExpressEngine sharedEngine] startPlayingStream:playStreamID canvas:playCanvas config:playerConfig];
   }
   else {
       // 不支持 H.265 解码
       NSString *h264Url = @""; // 请填入 H264 Url 地址
       // 注意: ZegoCDNConfig 和 ZegoPlayerConfig 中有其他的可配置项
       ZegoCDNConfig *cdnConfig = [ZegoCDNConfig new];
       // H.264 CDN 拉流地址
       cdnConfig.url = h264Url;
       ZegoPlayerConfig *playerConfig = [ZegoPlayerConfig new];
       playerConfig.cdnConfig = cdnConfig;
       [[ZegoExpressEngine sharedEngine] startPlayingStream:playStreamID canvas:playCanvas config:playerConfig];
   }
   ```



### 单主播直播

#### 实时网络转推 CDN 直播

该场景具有以下两个特点：

- 主播通过 ZEGO 实时音视频云转推到 CDN，通过 CDN 的转码能力，观众可以根据自身终端设备是否支持 H.265 视频解码，选择从 CDN 拉 H.265 码流或 H.264 码流。
- 主播推 H.265 码流时，连麦嘉宾从 ZEGO 实时音视频云直接拉流进行实时互动，此时要求连麦嘉宾的终端设备支持 H.265 视频解码能力。


<Frame width="512" height="auto" caption="">
  <img src="https://doc-media.zego.im/sdk-doc/Pics/LiveRoom/H265/RetweetCDN.png" />
</Frame>

- **主播端**

  <Steps>
  <Step >
  创建引擎后，调用 [enableHardwareEncoder](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoExpressEngine#enable-hardware-encoder) 接口开启硬件编码（若推流后更改配置，需要等下一次推流才生效），开启后会使用 GPU 进行编码，降低 CPU 使用率。
  </Step>
  <Step>
  调用 [isVideoEncoderSupported](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoExpressEngine#is-video-encoder-supported) 接口查询主播端设备是否支持指定视频编码类型。
  </Step>
  <Step>
  推流前调用 [setVideoConfig](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoMixerOutput#set-video-config) 接口，通过 codecID 设置视频编码格式（若推流后更改配置，需要等下一次推流才生效）。如果设置了 H.265 编码，则：
    <Steps>
    <Step >
    可以调用 [enableH265EncodeFallback](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoExpressEngine#enable-h265encode-fallback) 接口开启 H.265 编码失败后自动降级到 H.264 编码（默认开启）。开启后，当不支持 H.265 编码或 H.265 编码失败时，SDK 内部会尝试降级使用 H.264 编码进行推流。关闭后，当不支持 H.265 编码或 H.265 编码失败时，直接推流失败。
    </Step>
    <Step >
    调用 [addPublishCdnUrl](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoExpressEngine#add-publish-cdn-url-stream-id-callback) 接口添加 ZEGO 实时音视频云的音视频流转推至 CDN 的 URL 地址。
    </Step>
    <Step>
    调用 [startPublishingStream](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoExpressEngine#start-publishing-stream) 接口开始推流，当推流成功后，同房间内其他用户可通过监听 [onRoomStreamUpdate](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~protocol~ZegoEventHandler#on-room-stream-update-stream-list-extended-data-room-id)  回调来获取流的新增情况。
    </Step>
    <Step>
    开发者通知 App 的业务服务端该条推流的编码格式，以便通知拉流端根据不同的推流编码格式做相应的处理。
    </Step>
    </Steps>
  </Step>
  </Steps>
  ```objc
  // 移动端使用 H.265 编码需要开启硬件编码
  [[ZegoExpressEngine sharedEngine] enableHardwareEncoder:YES];

  // 查询是否支持 H.265 编码
  BOOL h265EncoderSupport = [[ZegoExpressEngine sharedEngine] isVideoEncoderSupported:ZegoVideoCodecIDH265];

  ZegoVideoConfig *videoConfig = [ZegoVideoConfig defaultConfig];
  if (h265EncoderSupport) {
      // 支持 H.265 编码
      videoConfig.codecID = ZegoVideoCodecIDH265;
  } else {
      // 不支持 H.265 编码
      videoConfig.codecID = ZegoVideoCodecIDDefault;
  }
  [[ZegoExpressEngine sharedEngine] setVideoConfig:videoConfig];

  if (h265EncoderSupport) {
      // 通过 enableH265EncodeFallback 选择是否开启 H.265 编码失败自动降级能力
      [[ZegoExpressEngine sharedEngine] enableH265EncodeFallback:YES];
  }
  // 请输入 streamID
  NSString *publishStreamID = @"";
  // 请输入 CdnUrl
  NSString *publishCdnUrl = @"";
  // 添加 CDN 转推地址
  [[ZegoExpressEngine sharedEngine] addPublishCdnUrl:publishCdnUrl streamID:publishStreamID callback:^(int errorCode) {
      // 判断转推 CDN 地址是否添加成功
  }];
  [[ZegoExpressEngine sharedEngine] startPublishingStream:publishStreamID];

  // 开发者通知 App 的业务服务端该条推流的编码格式，以便通知拉流端根据不同的推流编码格式做相应的处理
  ```

- **观众端**

  1. 主播推流后，观众端通过 [onRoomStreamUpdate](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~protocol~ZegoEventHandler#on-room-stream-update-stream-list-extended-data-room-id) 接口收到流新增通知。
  2. 观众端从 App 的业务服务端获取该条推流的编码格式。
    - 如果是 H.264 格式，观众可以调用 [startPlayingStream](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoExpressEngine#start-playing-stream-canvas) 接口从 CDN 直接拉主播端的流。
    - 如果是 H.265 格式，需要先调用 [isVideoDecoderSupported](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoExpressEngine#is-video-decoder-supported) 接口查询观众端自身设备是否支持 H.265 解码格式。
        - 若支持，则调用 [startPlayingStream](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoExpressEngine#start-playing-stream-canvas) 接口从 CDN 拉 H.265 码流。
        - 若不支持，则调用 [startPlayingStream](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoExpressEngine#start-playing-stream-canvas) 接口从 CDN 拉 H.264 码流。

  ```objc
  //收到流新增通知 onRoomStreamUpdate
  - (void)onRoomStreamUpdate:(ZegoUpdateType)updateType streamList:(NSArray<ZegoStream *> *)streamList extendedData:(NSDictionary *)extendedData roomID:(NSString *)roomID {
      // 从 App 的业务服务端获取该条流的编码格式
      int videoCodecID = 0;
      // 请输入 streamID
      NSString *playStreamID = @"";
      // 拉流需要渲染的 view
      UIView *playView;
      ZegoCanvas *playCanvas = [ZegoCanvas canvasWithView:playView];

      if (videoCodecID == ZegoVideoCodecIDH265) {
          // 编码格式为 H.265, 具体的降级策略需要配合进阶拉流
          BOOL h265DecoderSupport = [[ZegoExpressEngine sharedEngine] isVideoDecoderSupported:ZegoVideoCodecIDH265];

          if (h265DecoderSupport) {
              // 支持 H.265 解码
              // 请填入 H.265 Url 地址
              NSString *h265Url = @"";

              // 注意: ZegoCDNConfig 和 ZegoPlayerConfig 中有其他的可配置项
              ZegoCDNConfig *cdnConfig = [ZegoCDNConfig new];
              // H.265 CDN 拉流地址
              cdnConfig.url = h265Url;
              ZegoPlayerConfig *playerConfig = [ZegoPlayerConfig new];
              playerConfig.cdnConfig = cdnConfig;
              [[ZegoExpressEngine sharedEngine] startPlayingStream:playStreamID canvas:playCanvas config:playerConfig];

          }
          else {
              // 不支持 H.265 解码
              // 请填入 H264 Url 地址
              NSString *h264Url = @"";

              // 注意: ZegoCDNConfig 和 ZegoPlayerConfig 中有其他的可配置项
              ZegoCDNConfig *cdnConfig = [ZegoCDNConfig new];
              // H.264 CDN 拉流地址
              cdnConfig.url = h264Url;
              ZegoPlayerConfig *playerConfig = [ZegoPlayerConfig new];
              playerConfig.cdnConfig = cdnConfig;
              [[ZegoExpressEngine sharedEngine] startPlayingStream:playStreamID canvas:playCanvas config:playerConfig];
          }
      }
      else if (videoCodecID == ZegoVideoCodecIDDefault) {
          // 编码格式为 H.264
          [[ZegoExpressEngine sharedEngine] startPlayingStream:playStreamID canvas:playCanvas];
      }
  }
  ```

- **连麦嘉宾端**

  1. 主播推流后，连麦嘉宾通过 [onRoomStreamUpdate](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~protocol~ZegoEventHandler#on-room-stream-update-stream-list-extended-data-room-id) 接口收到流的新增通知。
  2. 连麦嘉宾从 App 的业务服务端获取该条推流的编码格式。
     - 如果是 H.264 格式，连麦嘉宾可以调用 [startPlayingStream](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoExpressEngine#start-playing-stream-canvas) 接口从 ZEGO 实时音视频云直接拉主播端的流。
     - 如果是 H.265 格式，需要先调用 [isVideoDecoderSupported](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoExpressEngine#is-video-decoder-supported) 接口查询自身设备是否支持 H.265 解码格式。
         - 若支持，则调用 [startPlayingStream](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoExpressEngine#start-playing-stream-canvas) 接口从 ZEGO 实时音视频云 拉 H.265 码流。
         - 若不支持，则提示本终端设备不支持拉该流。

  ```objc
  //收到流新增通知 onRoomStreamUpdate
  - (void)onRoomStreamUpdate:(ZegoUpdateType)updateType streamList:(NSArray<ZegoStream *> *)streamList extendedData:(NSDictionary *)extendedData roomID:(NSString *)roomID {
      // 从 App 的业务服务端获取该条流的编码格式
      int videoCodecID = 0;
      // 请输入 streamID
      NSString *playStreamID = @"";
      // 拉流需要渲染的 view
      UIView *playView;
      ZegoCanvas *playCanvas = [ZegoCanvas canvasWithView:playView];
      ZegoPlayerConfig *config = [[ZegoPlayerConfig alloc]init];
      // 仅从 RTC 拉流
      config.resourceMode = ZegoStreamResourceModeOnlyRTC;

      if (videoCodecID == ZegoVideoCodecIDH265) {
          // 编码格式为 H.265
          BOOL h265DecoderSupport = [[ZegoExpressEngine sharedEngine] isVideoDecoderSupported:ZegoVideoCodecIDH265];

          // 不支持解码则不拉流
          if (h265DecoderSupport) {
              // 支持 H.265 解码
              [[ZegoExpressEngine sharedEngine] startPlayingStream:playStreamID canvas:playCanvas config:config];
          }
      }
      else if (videoCodecID == ZegoVideoCodecIDDefault) {
          // 编码格式为 H.264
          [[ZegoExpressEngine sharedEngine] startPlayingStream:playStreamID canvas:playCanvas config:config];
      }
  }
  ```

### 录制

如果进行本地服务端录制、云端录制、数据流录制时使用了 H.265 编解码功能，则会影响录制文件的生成，详情如下：

在对推流（H.265 视频编码码流）进行录制时，有可能因为 H.265 编码失败而触发编码降级，此时会收到 [onPublisherVideoEncoderChanged](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~protocol~ZegoEventHandler#on-publisher-video-encoder-changed-to-codec-id-channel) 回调，表示视频编码格式发生变更。

该场景下，为了避免对录制文件造成损坏，SDK 内部会结束并保存当前的录制任务，并自动重启一个新的录制任务。新录制任务的录制文件路径会重新生成，避免覆盖原始录制文件。新文件的生成规则为给原始的录制文件名基础上加一个时间戳：

例如，开发者传入的原始录制文件路径为：/user/data/mediarecord.mp4，则新的录制文件为: /user/data/mediarecord_1626880634948.mp4，其中 1626880634948 为当前时间戳。


<Note title="说明">


如果开发者在录制期间收到过 [onPublisherVideoEncoderChanged](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~protocol~ZegoEventHandler#on-publisher-video-encoder-changed-to-codec-id-channel) 回调，需要在录制结束后，收集录制文件存储路径下的其他文件。
</Note>


## 常见问题

1. **H.265 在硬编出现错误怎么办？**

可以调用 [enableH265EncodeFallback](https://doc-zh.zego.im/article/api?doc=Express_Video_SDK_API~objective-c_ios~class~ZegoExpressEngine#enable-h265encode-fallback) 接口开启降级功能（默认开启），若 H.265 硬编失败则降级成 H.264，若同时在使用录制功能，则录制文件变为两份。

2. **H.265 是否会自动从硬解降到软解？**

会的，若解码时发现硬解失败，会自动降级成软解。

3. **H.265 如何收费？**

客户端开启 H.265 功能不需要收费，但是混流输出 H.265 需要收取混流费用，比混流输出 H.264 价格更贵，详情可咨询 ZEGO 商务人员。

4. **混流输入 H.265 流，输出 H.264 流时，计费是否有变化？**

没有变化，按输出 H.264 计费。

5. **H.265 解码对于硬件的要求是什么？**

目前市场上所有机型都支持 H.265 解码，经测试大概在 2013 年之前的低端机型解码可能会有帧率波动。
