目录
BRTC HarmonyOS SDK 从 1.1.0 开始,对 XComponent 的 ID 取消了命名约束。但我们仍然建议您按照每一个用户的每一种流类型,给予独立、不重复的 ID,便于识别和区分不同的视频画面。另外,您必需将 XComponent 的 libraryname 指定为 BRTC HarmonyOS SDK 的包名 brtcohossdk
brtcohossdk
举例如下:
getXcomponentUniqueId(): string { return this.userItem.userId + "_" + this.userItem.streamType; } XComponent({ id: this.getXcomponentUniqueId(), type: XComponentType.SURFACE, libraryname: 'brtcohossdk', controller: this.xComponentController}) .onLoad(async () => { hilog.info(0x0000, this.TAG, 'XComponent id:%{public}s on load', this.getXcomponentUniqueId()); })
强烈您关注 XComponent 的 onLoad 事件!在 HarmonyOS 系统上,有一定可能性会发生当前已存在的 XComponent 被重复加载不释放的情况,这多数可能跟您实现的界面逻辑有关。如果 XComponent 被反复 onLoad,最终可能导致您的应用主界面失去响应。
根据 HarmonyOS 官方介绍文字:
设备返回主界面、锁屏、应用切换等操作会使应用退至后台。应用退至后台后,如果继续活动,可能会造成设备耗电快、用户界面卡顿等现象。为了降低设备耗电速度、保障用户使用流畅度,系统会对退至后台的应用进行管控,包括进程挂起(即系统不再为应用进程分配CPU资源,同时对应的公共事件等不再发给应用进程)和进程终止。
对于音视频应用来说,退后台继续播放房间内的声音、继续通过麦克风采集等是非常普遍的需求。因此,为了实现这一目的,您的应用程序需要添加后台任务保活功能。具体到后台服务类型,建议您创建长时任务,具体介绍请参考华为技术文档:Background Tasks Kit - 长时任务
长时任务
另外,您也可以在 BRTC HarmonyOS Demo App 源代码中找到保活任务的代码示例(参考 BrtcBackgroundUtil.ets)
BrtcBackgroundUtil.ets
HarmonyOS 不提供音频输出设备切换的 API (参考 使用通话设备切换组件 上面的说明)。如果您想在您的应用中实现音频输出路由的切换,您需要利用 AVCastPicker投播组件来完成。开发步骤请参考华为技术文档使用通话设备切换组件 。或者您也可以在 BRTC HarmonyOS Demo App 源代码中找到使用示例。
AVCastPicker
在 HarmonyOS SDK 中,我们没有内嵌混流播放器。主要原因一是自带播放器会大大增加 SDK 的体积,对于那些不需要使用互动直播功能的用户来说,无疑是一个巨大的浪费。第二是互动直播的混流,实际上就是 rtmp、flv、m3u8 这种位于 CDN 上的直播流,用户可以自行选择适合自己的播放器,不一定局限于使用百家云提供的。不过,如果您确实需要一款直播流播放器,我们也为您提供了一个现成的选择,那就是基于ijkplayer的 HarmonyOS 版本,代码仓库:https://git2.baijiashilian.com/open-android/brtc/ohos_ijkplayer。您只需要 clone 下来,使用 DevEco Studio 编译生成 ijkplayer.har 导入到您的项目中使用即可。代码示例如下:
ijkplayer
ijkplayer.har
import { IjkMediaPlayer, OnErrorListener } from '@ohos/ijkplayer'; @State isLiveStreamPlaying: boolean = false; private mIjkMediaPlayer: IjkMediaPlayer = IjkMediaPlayer.getInstance(); private ijkNativeContext : object | undefined = undefined; XComponent({ id: 'live_stream_view', type: XComponentType.SURFACE, libraryname: 'ijkplayer_napi'}) .onLoad((xComponentContext?: object) => { hilog.info(0x0000, this.TAG, 'Live stream XComponent onload'); this.ijkNativeContext = xComponentContext; }) .width('100%').height(CommonConstants.DEFAULT_VIDEO_CARD_HEIGHT) playLiveStream() { if (this.mixStreamId === '') { return; } if (this.brtcEngine) { let liveStreamInfo = this.brtcEngine.queryLiveStreamInfo(this.mixStreamId) as BrtcQueriedLiveStreamInfo; if (liveStreamInfo) { this.logInfo('获取到了流地址:' + liveStreamInfo.rtmpUrl + ', 准备播放'); if (!!this.ijkNativeContext) { this.mIjkMediaPlayer.setContext(this.ijkNativeContext); this.mIjkMediaPlayer.setDebug(true); this.mIjkMediaPlayer.native_setup(); this.mIjkMediaPlayer.setDataSource(liveStreamInfo.rtmpUrl); this.mIjkMediaPlayer.setScreenOnWhilePlaying(true); this.mIjkMediaPlayer.setLoopCount(false); this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "max-buffer-size", "102400"); this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "min-frames", "100"); this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", "1"); this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "packet-buffering", "0"); this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "framedrop", "5"); this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "max_cached_duration", "3000"); this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "timeout", "10000000"); this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "connect_timeout", "10000000"); this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "addrinfo_timeout", "10000000"); this.mIjkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "dns_cache_timeout", "10000000"); let mOnErrorListener: OnErrorListener = { onError: (what: number, extra: number) => { hilog.error(0x0000, this.TAG, 'ijkLiveStream onError what:' + what + ' extra:' + extra); } }; this.mIjkMediaPlayer.setOnErrorListener(mOnErrorListener); this.mIjkMediaPlayer.setMessageListener(); this.mIjkMediaPlayer.prepareAsync(); this.mIjkMediaPlayer.start(); this.isLiveStreamPlaying = true; } } else { this.logInfo('无法获取到流地址,无法播放'); } } } stopLiveStream() { this.logInfo('请求停止播放'); this.mIjkMediaPlayer.stop(); this.mIjkMediaPlayer.release(); this.isLiveStreamPlaying = false; }
ijkplayer 提供了非常丰富的配置参数,您可以根据需要自行设置调整达到符合自己使用场景的一套参数配置。
HarmonyOS
目录
视频视图控件 XComponent 的命名规则
BRTC HarmonyOS SDK 从 1.1.0 开始,对 XComponent 的 ID 取消了命名约束。但我们仍然建议您按照每一个用户的每一种流类型,给予独立、不重复的 ID,便于识别和区分不同的视频画面。另外,您必需将 XComponent 的 libraryname 指定为 BRTC HarmonyOS SDK 的包名
brtcohossdk
举例如下:
添加应用后台保活
根据 HarmonyOS 官方介绍文字:
对于音视频应用来说,退后台继续播放房间内的声音、继续通过麦克风采集等是非常普遍的需求。因此,为了实现这一目的,您的应用程序需要添加后台任务保活功能。具体到后台服务类型,建议您创建
长时任务
,具体介绍请参考华为技术文档:Background Tasks Kit - 长时任务另外,您也可以在 BRTC HarmonyOS Demo App 源代码中找到保活任务的代码示例(参考
BrtcBackgroundUtil.ets
)音频路由切换
HarmonyOS 不提供音频输出设备切换的 API (参考 使用通话设备切换组件 上面的说明)。如果您想在您的应用中实现音频输出路由的切换,您需要利用
AVCastPicker
投播组件来完成。开发步骤请参考华为技术文档使用通话设备切换组件 。或者您也可以在 BRTC HarmonyOS Demo App 源代码中找到使用示例。互动直播模式下,如何播放混流?
在 HarmonyOS SDK 中,我们没有内嵌混流播放器。主要原因一是自带播放器会大大增加 SDK 的体积,对于那些不需要使用互动直播功能的用户来说,无疑是一个巨大的浪费。第二是互动直播的混流,实际上就是 rtmp、flv、m3u8 这种位于 CDN 上的直播流,用户可以自行选择适合自己的播放器,不一定局限于使用百家云提供的。不过,如果您确实需要一款直播流播放器,我们也为您提供了一个现成的选择,那就是基于
ijkplayer
的 HarmonyOS 版本,代码仓库:https://git2.baijiashilian.com/open-android/brtc/ohos_ijkplayer。您只需要 clone 下来,使用 DevEco Studio 编译生成ijkplayer.har
导入到您的项目中使用即可。代码示例如下:ijkplayer 提供了非常丰富的配置参数,您可以根据需要自行设置调整达到符合自己使用场景的一套参数配置。