过去开发者们在使用多媒体能力时,往往会遇到这样的问题,比如:为什么我开发的相机不如系统相机的效果好?为什么我的应用和其他的音乐一起发声了,我要怎么处理?以及我应该怎么做才能在系统的播控中心里可以看到呢?对于开发者的这些疑问,HarmonyOS 通过提供简单易用体验一致的生态接口,使得开发者可以轻松解决上述问题。下面会按照不同模块逐个进行介绍。
一、相机
1.1 问题背景
相机应用在早期的版本开发时,会发现三方相机和系统相机拍照的效果会有较明显的不一致。如下图对比,可以看到,在色彩/饱和度/纹理细节等方面有一些明显的差异。
三方相机:
系统相机:
1.2 问题原因
那么这一问题是怎么产生的呢?主要有两个原因:
1、系统相机采用了私有通路,从而获取了更好的效果
2、预览流拍照效果差
1.3 问题解决
针对以上问题,系统提出了如下的解决思路:
1、统一接口,统一流程,统一效果:通过统一开发接口和流程,从而使得三方相机和系统相机获取一致的体验
2、分离预览、拍照、录像,明确流定义,让正确的流做正确的事
3、相机管道流水线模型
1.4 代码示例
1、相机基本控制流程如下:
2、示例参考:
使用 PreviewOutput 实现相机预览:
//1.创建预览视图XComponent,获取SurfaceId
surfaceId=xComponent.getXComponentSurfaceId();
//2.创建预览数据流输出PreviewOutput
previewOutput=createPreviewOutput(profile,surfaceId);
//3.添加预览数据流输出到相机会话
session.addOutput(previewOutput);
使用 PhotoOutput 实现相机拍照:
//1.创建图片接收器ImageReceiver,获取SurfaceId
surfaceId=imageReceiver.getReceivingSurfaceId();
//2.创建拍照数据流输出PhotoOutput
photoOutput=createPhotoOutput(profile,surfaceId);
//3.添加拍照数据流输出到相机会话
session.addOutput(photoOutput);
使用 VideoOutput 实现相机录像:
//1.创建视频编码器AVRecorder,获取SurfaceId
surfaceId=avRecorder.getInputSurface();
//2.创建录像数据流输出VideoOutput
videoOutput=createVideoOutput(profile,surfaceId);
//3.添加录像数据流输出到相机会话
session.addOutput(videoOutput);
更多详细的代码参考:
https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/media/camera-overview.md
二、音视频焦点
2.1 问题背景
音视频应用开发中遇到的很常见的一个场景,就是并发播放,而并发播放的一般解决思路是各个应用对焦点的申请和处理。
传统的焦点管理方法,依赖应用遵守约定好的策略,如果有的应用不遵守,比如不响应或者滥用焦点,就可能会出现不发声或者乱发声的现象,影响了用户的体验。
2.2解决思路
针对以上的问题,鸿蒙系统改进了焦点管理的设计,提供了统一的焦点处理策略,来规范应用对于焦点的使用,以达成统一的发声体验。
系统中的焦点管理模块会存储一个焦点策略表,定义了不同的场景下,哪些应用可以获取焦点进行播放,哪些应用会失去焦点而停止播放,等等其他策略。
2.3 代码示例
可以通过接口的使用来看一下实际处理策略。
首先,在 A 应用创建并使用 AudioRenderer 播放的时候,系统会自动为其申请焦点,这个是系统的行为。
A 应用播放后,系统的焦点策略会进行判断,如果 A 应用可以抢到焦点,那就会使得失去焦点的应用暂停播放;同时被暂停的应用也会在 INTERRUPT_FORCE 的回调事件中,得到暂停的状态,应用在收到这个事件后,就需要存储并更新应用内的状态。
当 A 应用停止播放,之前被暂停的应用也会收到一个恢复播放的事件,这个事件会在 INTERRUPT_SHARE 中,应用可以进行恢复播放的操作,或者忽略,这个非强制行为。
//1.AudioRenderer进行播放时,系统会申请焦点
audioRenderer.start((err)=>{});
//2.注册音频打断事件的回调
audioRenderer.on('audioInterrupt',(event)=>{
if(event.forceType===audio.InterruptForceType.INTERRUPT_FORCE){
//3.强制打断类型:音频相关处理已由系统执行,应用需更新自身状态
}elseif(event.forceType===audio.InterruptForceType.INTERRUPT_SHARE){
//4.共享打断类型:应用可自主选择执行相关操作或忽略打断事件
}});
更多详细的代码参考:
https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/media/audio-playback-concurrency.md
三、低时延播放
3.1 问题背景
游戏、K 歌、乐器等应用,对于音频的输出时延要求很高,常规的播放通路一般只能达到 60ms 左右甚至更高的时延,无法满足这些应用的使用诉求。
3.2 解决思路
鸿蒙系统提供了低时延通路的设计。如下图所服务器托管网示,在系统中的普通通路之外,新增了一条垂直打通硬件的低时延通路,通过 bypass框架层直接在 DSP 进行混音,可以达成最低 20ms 的音频输出时延。
同时,为了简化应用的接入,通过在接口中提供不同的参数配置,使开发者可以用一套接口同时支持低时延和普通通路两种播放模式。
3.3 代码示例
可以通过 OH_AudioStreamXXX 接口来进行低时延通路的创建,通过传入不同参数可以设置低时延模式,亦可以设置普通模式,从而使用一套接口来适配不同场景。
同时,低时延模式一般采用来 pull 模式来获取数据,这里提供了一个 callback,需要应用创建并填入。
//1.创建音频流构造器,设置参数
OH_AudioStreamBuilder_Create(&builder,AUDIOSTREAM_TYPE_RENDERER);
OH_AudioStreamBuilder_S服务器托管网etSamplingRate(builder,rate);//其他参数设置…
//2.设置低延时模式和数据回调
OH_AudioStreamBuilder_SetLatencyMode(builder,AUDIOSTREAM_LATENCY_MODE_FAST);
OH_AudioStreamBuilder_SetRendererCallback(builder,callback,nullptr);
//3.构造播放的音频流并使用
OH_AudioStreamBuilder_GenerateRenderer(builder,&audioRenderer);
OH_AudioRenderer_Start(audioRenderer);•OH_AudioRenderer_Release(audioRenderer);
更多详细的代码参考:
https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/media/using-ohaudio-for-playback.md
四、播控能力
4.1 系统能力通过前面所说的焦点管理策略,系统解决了音视频应用并发播放的问题;对于播放中的应用的控制,系统也提供了规范支持。
系统提供了 C/S 模式的播控管理的框架,应用作为客户端,接入 AVSession 的会话端,设置必要的信息;系统的播控中心获取与之对应的会话控制器,获取信息进行展示,以及对应用发送控制命令。
通过标准接口的接入,规范了应用的播放行为;同时通过统一的播控中心的入口,使得用户对于播放的控制做到一键直达。
4.2代码示例
importAVSessionManagerfrom'@ohos.multimedia.avsession';
//开始创建并激活媒体会话
//创建session
letcontext:Context=getContext(this);
asyncfunctioncreateSession(){
lettype:AVSessionManager.AVSessionType='audio';
letsession=awaitAVSessionManager.createAVSession(context,'SESSION_NAME',type);
awaitsession.activate();
}
asyncfunctionsetSessionInfo(){
//播放器逻辑引发媒体信息与播放状态的变更
//设置必要的媒体信息
letmetadata:AVSessionManager.AVMetadata={
assetId:'0',
title:'TITLE',
artist:'ARTIST'
};
session.setAVMetadata(metadata).then(()=>{
}).catch((err:BusinessError)=>{
});
//简单设置一个播放状态-暂停未收藏
letplaybackState:AVSessionManager.AVPlaybackState={
state:AVSessionManager.PlaybackState.PLAYBACK_STATE_PAUSE,
isFavorite:false
};
session.setAVPlaybackState(playbackState,(err)=>{
});
}
asyncfunctionsetListenerForMesFromController(){
//一般在监听器中会对播放器做相应逻辑处理
//不要忘记处理完后需要通过set接口同步播放相关信息,参考上面的用例
session.on('play',()=>{
//dosometasks
});
session.on('pause',()=>{
//dosometasks
});
}
更多详细的代码参考:
https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/media/avsession-overview.md
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
相关推荐: 【scikit-learn基础】–『数据加载』之玩具数据集
机器学习的第一步是准备数据,好的数据能帮助我们加深对机器学习算法的理解。 不管是在学习还是实际工作中,准备数据永远是一个枯燥乏味的步骤。scikit-learn库显然看到了这个痛点,才在它的数据加载子模块中为我们准备了直接可用的数据集。 在它的数据加载子模块中…