H.265 是一种高效的视频编码标准,旨在有限带宽下传输更高质量的网络视频。开发者可以在编码或混流时输出 H.265 格式的视频码流。
H.265 和 H.264 的区别如下:
差异项 | H.264 | H.265 |
---|---|---|
同等画质下的码率 |
- |
H.265 相比于 H.264 可以节约 30% 码率(实测值)。 |
软编性能 |
- |
H.265 消耗的算力是 H.264 的 3 倍左右。 |
软解性能 |
- |
H.265 消耗的算力是 H.264 的 1.5 倍左右。 |
硬件生态 |
所有机型基本都支持硬编和硬解。 |
大部分机型都支持硬编,绝大部分机型都支持硬解。 |
混流输出 |
支持。 |
支持,但价格比 H.264 混流输出更贵,详情可咨询 ZEGO 商务人员。 |
适用场景 |
所有场景。 |
推荐在直播和音视频互动场景使用。 |
在如下应用场景中,可使用 H.265 进行编码:
应用场景类型 | 说明 |
---|---|
秀场直播、电商直播、互动直播、游戏直播 |
通过 H.265 编码,将码率降低 30% 码率(实测值),分发给万千观众,极大降低 CDN 分发成本。 |
视频通话、视频会议、在线教育 |
通过 H.265 编码,在同等码率下,提高画面清晰度,让这些场景通话效果更好。 |
目前 Web 和小程序平台,不支持 H.265 拉流。
请参考 下载示例源码 获取源码。
相关源码请查看 “/ZegoExpressExample/Examples/AdvancedStreaming/H265” 目录下的文件。
在使用 H.265 编解码功能之前,请确保:
一些老的或低端的移动机型,不支持 H.265 视频编码。此时开发者需要在推流前先通过 isVideoEncoderSupported 接口判断本机是否支持 H.265 视频编码能力。如果支持,才能在推流前通过 setVideoConfig 接口设置 H.265 视频编码类型,否则不生效。
一些老的或低端的移动机型,不支持 H.265 视频解码。在支持拉不同视频码流的场景下,如 CDN 场景,开发者需要在拉流前先通过 isVideoDecoderSupported 接口判断本机是否支持 H.265 视频解码能力。如果支持,才能拉 H.265 视频码流,否则只能拉其他格式的视频码流,例如 H.264。
连麦混流直播包括如下两种实现方式,开发者可以根据实际情况按需接入:
混出不同格式的码流(推荐):混流服务直接输出一路 H.265 混流和一路 H.264 混流,该场景只需要在混流服务进行一次转码,无需 CDN 再转码。相比于混流推 CDN 转码,具有更高的清晰度,费用也更便宜,推荐使用。
混流推 CDN 转码:混流服务直接输出一路 H.265 混流,需要通过 CDN 的转码能力,转出一路 H.265 和一路 H.264 码流。
需要联系 ZEGO 技术支持开通 CDN 转码功能。
该场景下,混流服务通过 ZEGO 实时音视频云接收到主播和连麦嘉宾的推流后,直接输出一路 H.265 混流和一路 H.264 混流,并把两路流都推流到 CDN,观众可以根据自身终端设备是否支持 H.265 视频解码,选择从 CDN 拉 H.265 码流或 H.264 码流。
主播端
// 调用 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 的业务服务端流已新增
观众端
// 从 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];
}
该场景下,混流服务通过 ZEGO 实时音视频云接收到主播和连麦嘉宾的推流后,直接输出一路 H.265 混流,并把这路混流推流到 CDN,通过 CDN 的转码能力,观众可以根据自身终端设备是否支持 H.265 视频解码,选择从 CDN 拉 H.265 码流或 H.264 码流。
主播端
// 调用 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 的业务服务端流已新增
观众端
观众端从 App 的业务服务端收到流新增通知。
调用 isVideoDecoderSupported 接口查询观众端自身设备是否支持 H.265 解码格式。
// 从 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];
}
该场景具有以下两个特点:
主播端
// 移动端使用 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 的业务服务端该条推流的编码格式,以便通知拉流端根据不同的推流编码格式做相应的处理
观众端
//收到流新增通知 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];
}
}
连麦嘉宾端
//收到流新增通知 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 回调,表示视频编码格式发生变更。
该场景下,为了避免对录制文件造成损坏,SDK 内部会结束并保存当前的录制任务,并自动重启一个新的录制任务。新录制任务的录制文件路径会重新生成,避免覆盖原始录制文件。新文件的生成规则为给原始的录制文件名基础上加一个时间戳:
例如,开发者传入的原始录制文件路径为:/user/data/mediarecord.mp4,则新的录制文件为: /user/data/mediarecord_1626880634948.mp4,其中 1626880634948 为当前时间戳。
如果开发者在录制期间收到过 onPublisherVideoEncoderChanged 回调,需要在录制结束后,收集录制文件存储路径下的其他文件。
可以调用 enableH265EncodeFallback 接口开启降级功能(默认开启),若 H.265 硬编失败则降级成 H.264,若同时在使用录制功能,则录制文件变为两份。
会的,若解码时发现硬解失败,会自动降级成软解。
客户端开启 H.265 功能不需要收费,但是混流输出 H.265 需要收取混流费用,比混流输出 H.264 价格更贵,详情可咨询 ZEGO 商务人员。
没有变化,按输出 H.264 计费。
目前市场上所有机型都支持 H.265 解码,经测试大概在 2013 年之前的低端机型解码可能会有帧率波动。
联系我们
文档反馈