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 混流输出更贵,详情可咨询销售。 |
适用场景 |
所有场景。 |
推荐在直播和音视频互动场景使用。 |
目前 Web 和小程序平台,不支持连麦和 H.265 拉流。
在使用 H.265 编解码功能之前,请确保:
一些老的或低端的移动机型,不支持 H.265 视频编码。此时开发者需要在推流前先通过 isVideoEncoderSupported 接口判断本机是否支持 H.265 视频编码能力。如果支持,才能在推流前通过 setVideoCodecId 接口设置 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 技术支持开通 CDN 转码功能。
该场景下,混流服务通过 ZEGO 实时音视频云接收到主播和连麦嘉宾的推流后,直接输出一路 H.265 混流和一路 H.264 混流,并把两路流都推流到 CDN,观众可以根据自身终端设备是否支持 H.265 视频解码,选择从 CDN 拉 H.265 码流或 H.264 码流。
)
主播端
// 用户需要监听混流回调
ZEGO::MIXSTREAM::SetMixStreamExCallback(this); // 设置混流回调
ZEGO::MIXSTREAM::SetSoundLevelInMixedStreamCallback(this); // 设置混流音浪回调
// 调用 mixStreamEx 发起混流
std::string taskID = ""; // 请输入 taskID
ZEGO::MIXSTREAM::ZegoMixStreamConfig config;
// 请自行设置 videoConfig
config.nOutputFps = 15;
config.nOutputWidth = 1280;
config.nOutputHeight = 720; // 示例设置 720p, 15fps
// 注意,混流输入中流的编码格式支持 H.264 和 H.265, 请自行处理流布局及输入
std::vector<ZEGO::MIXSTREAM::ZegoMixStreamInput> inputList;
config.pInputStreamList = inputList.data();
config.nInputStreamCount = inputList.size();
// 混流两路输出
// 注意: 输出 target 可以是 streamID 或 CDN 地址,二者在观众端处理方式不同,该场景推荐直接传入 stremaID
std::string h264StreamID = ""; // 请输入 h264StreamID
std::string h265StreamID = ""; // 请输入 h265StreamID
int h264Bitrate = 2244; // 请输入 h264 码率,此码率为当前分辨率帧率(720p, 15fps)的推荐码率。
int h265Bitrate = 1795; // 请输入 h265 码率,此码率为当前分辨率帧率(720p, 15fps)的推荐码率。
ZEGO::MIXSTREAM::ZegoMixStreamOutput outputH264;
outputH264.isUrl = false;
memcpy(outputH264.target, h264StreamID.c_str(), h264StreamID.size());
outputH264.target[h264StreamID.size()] = '\0';
outputH264.videoBitrate = h264Bitrate * 1000;
outputH264.videoCodec = ZEGO::AV::VIDEO_CODEC_DEFAULT;
ZEGO::MIXSTREAM::ZegoMixStreamOutput outputH265;
outputH265.isUrl = false;
memcpy(outputH265.target, h265StreamID.c_str(), h265StreamID.size());
outputH265.target[h265StreamID.size()] = '\0';
outputH265.videoBitrate = h265Bitrate * 1000;
outputH265.videoCodec = ZEGO::AV::VIDEO_CODEC_H265;
std::vector<ZEGO::MIXSTREAM::ZegoMixStreamOutput> outputList;
outputList.push_back(outputH264);
outputList.push_back(outputH265);
config.pOutputList = outputList.data();
config.nOutputStreamCount = outputList.size();
int mixStreamTaskSeq_ = ZEGO::MIXSTREAM::MixStreamEx(taskID.c_str(), config);
// 开发者通知 App 的业务服务端流已新增
观众端
// 从 App 的业务服务端收到流新增通知
std::string h264StreamID = ""; // h264StreamID
std::string h265StreamID = ""; // h265StreamID
HWND playViewHwnd = NULL; // 拉流需要渲染的 view
bool h265DecoderSupport = ZEGO::LIVEROOM::IsVideoDecoderSupported(ZEGO::AV::VIDEO_CODEC_H265);
if (h265DecoderSupport) {
// 支持 H.265 解码
ZEGO::LIVEROOM::StartPlayingStream(h265StreamID.c_str(), playViewHwnd);
// 用户需要监听 onVideoDecoderError 回调,当编码器格式为 H.265 且错误码为 -3 时,表示软解性能不足,可能会出现低帧率现象。此时用户可以自行决定是否停止拉 H.265 码流,并重新拉 H.264 码流
}
else {
// 不支持 H.265 解码
ZEGO::LIVEROOM::StartPlayingStream(h264StreamID.c_str(), playViewHwnd);
}
该场景下,混流服务通过 ZEGO 实时音视频云接收到主播和连麦嘉宾的推流后,直接输出一路 H.265 混流,并把这路混流推流到 CDN,通过 CDN 的转码能力,观众可以根据自身终端设备是否支持 H.265 视频解码,选择从 CDN 拉 H.265 码流或 H.264 码流。
)
主播端
// 用户需要监听混流回调
ZEGO::MIXSTREAM::SetMixStreamExCallback(this); // 设置混流回调
ZEGO::MIXSTREAM::SetSoundLevelInMixedStreamCallback(this); // 设置混流音浪回调
// 调用 MixStreamEx 发起混流
std::string taskID = ""; // 请输入 taskID
ZEGO::MIXSTREAM::ZegoMixStreamConfig config;
// 请自行设置 videoConfig
config.nOutputFps = 15;
config.nOutputWidth = 1280;
config.nOutputHeight = 720; // 示例设置 720p, 15fps
// 注意,混流输入中流的编码格式支持 H.264 和 H.265, 请自行处理流布局及输入
std::vector<ZEGO::MIXSTREAM::ZegoMixStreamInput> inputList;
config.pInputStreamList = inputList.data();
config.nInputStreamCount = inputList.size();
std::string publishCdnUrl = ""; // 请输入 CDN URL
int h265Bitrate = 1795; // 请输入 h265 码率,此码率为当前分辨率帧率(720p, 15fps)的推荐码率。
// 注意,由于这里需要使用 CDN 转码, target 需要传入 CDN URL
ZEGO::MIXSTREAM::ZegoMixStreamOutput outputH265;
outputH265.isUrl = true;
memcpy(outputH265.target, publishCdnUrl.c_str(), publishCdnUrl.size());
outputH265.target[publishCdnUrl.size()] = '\0';
outputH265.videoBitrate = h265Bitrate * 1000;
outputH265.videoCodec = ZEGO::AV::VIDEO_CODEC_H265;
std::vector<ZEGO::MIXSTREAM::ZegoMixStreamOutput> outputList;
outputList.push_back(outputH265);
config.pOutputList = outputList.data();
config.nOutputStreamCount = outputList.size();
int mixStreamTaskSeq_ = ZEGO::MIXSTREAM::MixStreamEx(taskID.c_str(), config);
// 开发者通知 App 的业务服务端流已新增
观众端
// 从 App 的业务服务端收到流新增通知
std::string playStreamID = "";
HWND playViewHwnd = NULL; // 拉流需要渲染的 view
bool h265DecoderSupport = ZEGO::LIVEROOM::IsVideoDecoderSupported(ZEGO::AV::VIDEO_CODEC_H265);
if (h265DecoderSupport) {
// 支持 H.265 解码
std::string h265Url = ""; // 请填入 H265 Url 地址
// 注意: ZegoAPIStreamExtraPlayInfo 中有其他的可配置项
ZegoStreamExtraPlayInfo *playInfo = zego_stream_extra_info_create();
zego_stream_extra_info_set_play_mode(playInfo, ZEGO::AV::CDN_ONLY);
// H.265 CDN 拉流地址
zego_stream_extra_info_add_rtmp_url(playInfo, h265Url.c_str());
ZEGO::LIVEROOM::StartPlayingStream2(playStreamID.c_str(), playViewHwnd, playInfo);
// 用户需要监听 onVideoDecoderError 回调,当编码器格式为 H.265 且错误码为 -3 时,表示软解性能不足,可能会出现低帧率现象。此时用户可以自行决定是否停止拉 H.265 码流,并重新拉 H.264 码流
}
else {
// 不支持 H.265 解码
std::string h264Url = ""; // 请填入 H265 Url 地址
// 注意: ZegoAPIStreamExtraPlayInfo 中有其他的可配置项
ZegoStreamExtraPlayInfo *playInfo = zego_stream_extra_info_create();
zego_stream_extra_info_set_play_mode(playInfo, ZEGO::AV::CDN_ONLY);
// H.264 CDN 拉流地址
zego_stream_extra_info_add_rtmp_url(playInfo, h264Url.c_str());
ZEGO::LIVEROOM::StartPlayingStream2(playStreamID.c_str(), playViewHwnd, playInfo);
}
该场景具有以下两个特点:
)
主播端
// 移动端使用 H.265 编码需要开启硬件编码
ZEGO::LIVEROOM::RequireHardwareEncoder(true);
// 查询是否支持 H.265 编码
bool h265EncoderSupport = ZEGO::LIVEROOM::IsVideoEncoderSupported(ZEGO::AV::VIDEO_CODEC_H265);
if (h265EncoderSupport) {
// 支持 H.265 编码
ZEGO::LIVEROOM::SetVideoCodecId(ZEGO::AV::VIDEO_CODEC_H265, ZEGO::AV::PUBLISH_CHN_MAIN);
}
else {
// 不支持 H.265 编码
ZEGO::LIVEROOM::SetVideoCodecId(ZEGO::AV::VIDEO_CODEC_DEFAULT, ZEGO::AV::PUBLISH_CHN_MAIN);
}
if (h265EncoderSupport) {
// 通过 enableH265EncodeFallback 选择是否开启 H.265 编码失败自动降级能力。
ZEGO::LIVEROOM::EnableH265EncodeFallback(true);
}
std::string publishStreamID = ""; // 请输入 streamID
std::string publishCdnUrl = ""; // 请输入 CdnUrl
// 添加 CDN 转推地址
ZEGO::LIVEROOM::SetCustomPublishTarget(publishCdnUrl.c_str(), ZEGO::AV::PUBLISH_CHN_MAIN);
ZEGO::LIVEROOM::StartPublishing(NULL, publishStreamID.c_str(), ZEGO::AV::ZEGO_JOIN_PUBLISH);
// 开发者通知 App 的业务服务端该条推流的编码格式,以便通知拉流端根据不同的推流编码格式做相应的处理
观众端
//收到流新增通知 onStreamUpdated
void PlayDemo::OnStreamUpdated(ZegoStreamUpdateType type, ZegoStreamInfo *pStreamInfo, unsigned int streamCount, const char *pszRoomID)
{
int videoCodecID = 0; // 从 App 的业务服务端获取该条流的编码格式。
std::string playStreamID = "";
HWND playViewHwnd = NULL; // 拉流需要渲染的 view
if (videoCodecID == ZEGO::AV::VIDEO_CODEC_H265)
{
// 编码格式为 H.265
bool h265DecoderSupport = ZEGO::LIVEROOM::IsVideoDecoderSupported(ZEGO::AV::VIDEO_CODEC_H265);
if (h265DecoderSupport) {
// 支持 H.265 解码
std::string h265Url = ""; // 请填入 H265 Url 地址
// 注意: ZegoAPIStreamExtraPlayInfo 中有其他的可配置项
ZegoStreamExtraPlayInfo *playInfo = zego_stream_extra_info_create();
zego_stream_extra_info_set_play_mode(playInfo, ZEGO::AV::CDN_ONLY);
// H.265 CDN 拉流地址
zego_stream_extra_info_add_rtmp_url(playInfo, h265Url.c_str());
ZEGO::LIVEROOM::StartPlayingStream2(playStreamID.c_str(), playViewHwnd, playInfo);
// 用户需要监听 onVideoDecoderError 回调,当编码器格式为 H.265 且错误码为 -3 时,表示软解性能不足,可能会出现低帧率现象。此时用户可以自行决定是否停止拉 H.265 码流,并重新拉 H.264 码流
}
else {
// 不支持 H.265 解码
std::string h264Url = ""; // 请填入 H265 Url 地址
// 注意: ZegoAPIStreamExtraPlayInfo 中有其他的可配置项
ZegoStreamExtraPlayInfo *playInfo = zego_stream_extra_info_create();
zego_stream_extra_info_set_play_mode(playInfo, ZEGO::AV::CDN_ONLY);
// H.264 CDN 拉流地址
zego_stream_extra_info_add_rtmp_url(playInfo, h264Url.c_str());
ZEGO::LIVEROOM::StartPlayingStream2(playStreamID.c_str(), playViewHwnd, playInfo);
}
}
else if (videoCodecID == ZEGO::AV::VIDEO_CODEC_DEFAULT) {
// 编码格式为 H.264
ZEGO::LIVEROOM::StartPlayingStream(playStreamID.c_str(), playViewHwnd);
}
}
连麦嘉宾端
//收到流新增通知 onStreamUpdated
void PlayDemo::OnStreamUpdated(ZegoStreamUpdateType type, ZegoStreamInfo *pStreamInfo, unsigned int streamCount, const char *pszRoomID)
{
int videoCodecID = 0; // 从 App 的业务服务端获取该条流的编码格式。
std::string playStreamID = "";
HWND playViewHwnd = NULL; // 拉流需要渲染的 view
if (videoCodecID == ZEGO::AV::VIDEO_CODEC_H265)
{
// 编码格式为 H.265
bool h265DecoderSupport = ZEGO::LIVEROOM::IsVideoDecoderSupported(ZEGO::AV::VIDEO_CODEC_H265);
// 不支持解码则不拉流
if (h265DecoderSupport) {
// 支持 H.265 解码
ZEGO::LIVEROOM::StartPlayingStream(playStreamID.c_str(), playViewHwnd);
}
}
else if (videoCodecID == ZEGO::AV::VIDEO_CODEC_DEFAULT) {
// 编码格式为 H.264
ZEGO::LIVEROOM::StartPlayingStream(playStreamID.c_str(), playViewHwnd);
}
}
如果进行本地服务端录制、云端录制、数据流录时使用了 H.265 编解码功能,则会影响录制文件的生成,详情如下:
在对推流(H.265 视频编码码流)进行录制时,有可能因为 H.265 编码而触发编码降级,此时会收到 onVideoEncoderChanged 回调,表示视频编码格式发生变更。
该场景下,为了避免对录制文件造成损坏,SDK 内部会结束并保存当前的录制任务,并自动重启一个新的录制任务。新录制任务的录制文件路径会重新生成,避免覆盖原始录制文件。新文件的生成规则为给原始的录制文件名基础上加一个时间戳:
例如,开发者传入的原始录制文件路径为:/user/data/mediarecord.mp4,则新的录制文件为: /user/data/mediarecord_1626880634948.mp4,其中 1626880634948 为当前时间戳。
如果开发者在录制期间收到过 onVideoEncoderChanged 回调,需要在录制结束后,收集录制文件存储路径下的其他文件。
| 方法 | 描述 |
|---|---|
| InitSDK | 创建引擎 |
| requireHardwareEncoder | 开/关硬件编码 |
| startPublishing | 开始推流 |
| startPlayingStream | 开始拉流 |
| setVideoCodecId | 设置视频配置 |
| onStreamUpdated | 相同房间内其他用户推的流增加或减少的通知 |
| isVideoEncoderSupported | 是否支持指定视频编码类型 |
| isVideoDecoderSupported | 是否支持指定视频解码格式 |
| enableH265EncodeFallback | 是否开启 H.265 编码自动降级到 H.264 编码 |
| onVideoEncoderChanged | 视频编码器变更回调 |
| mixStreamEx | 开始混流任务 |
可以调用 enableH265EncodeFallback 接口开启降级功能(默认开启),若 H.265 硬编失败则降级成 H.264,若同时在使用录制功能,则录制文件变为两份。
会的,若解码时发现硬解失败,会自动降级成软解。
客户端开启 H.265 功能不需要收费,但是混流输出 H.265 需要收取混流费用,比混流输出 H.264 价格更贵,详情可咨询销售。
没有变化,按输出 H.264 计费。
目前市场上所有机型都支持 H.265 解码,经测试大概在 2013 年之前的低端机型解码可能会有帧率波动。

联系我们
文档反馈