媒体能力概览
鸿蒙的多媒体能力分布在 CameraKit、MediaLibraryKit、AVPlayer 等 Kit 里:相机管拍摄,媒体库管相册文件,播放器管音频视频。先摸清能力地图,再动手写代码。
先想清楚数据从哪来、到哪去,再决定用哪个 Kit。
大多数业务其实只需要三件事:调相机拍一张、从相册选一张、把音视频放出来。这三条链路走通,多媒体的地基就稳了。
相机调用与权限
调用相机前必须申请 ohos.permission.CAMERA,用 abilityAccessCtrl 动态申请,拒绝后要能引导用户去设置。权限是敏感能力的第一道门,别绕过。
import { abilityAccessCtrl, common } from '@kit.AbilityKit'
import { camera } from '@kit.CameraKit'
async function openCamera(context: common.Context) {
const atManager = abilityAccessCtrl.createAtManager()
const grant = await atManager.requestPermissionsFromUser(context,
['ohos.permission.CAMERA'])
if (grant.authResults[0] !== 0) {
return // 未授权,提示用户
}
const cameraManager = camera.getCameraManager(context)
const cameras = cameraManager.getSupportedCameras()
const cameraDevice = cameras.find(c => c.cameraPosition === camera.CameraPosition.CAMERA_POSITION_BACK)
}
- CAMERA拍摄画面。
- READ_MEDIA读取相册。
- WRITE_MEDIA写入相册。
申请权限时把用途说清楚,系统弹窗里的一段说明文字能大幅提升授权率。别在启动时一口气申请所有权限,用到再申请,用户反感度最低。
拍照与相册存取
拍照流程:建会话、配输出、拍一张、拿 buffer。鸿蒙里用 cameraManager 创建会话,PhotoOutput 负责出图,保存走 photoAccessHelper。
import { photoAccessHelper } from '@kit.MediaLibraryKit'
async function saveImage(context: common.Context, buffer: ArrayBuffer) {
const helper = photoAccessHelper.getPhotoAccessHelper(context)
const uri = await helper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'jpg')
const fp = await helper.openAsset(uri, photoAccessHelper.PhotoViewMode.READ_WRITE)
// 向 fp 写入图片数据后关闭
}
相册读取用 photoAccessHelper 的 getAssets 按条件查,按创建时间排序、按类型过滤都能做。别忘了在 Info 配置里声明媒体权限对应的 useScene。
音频播放与录制
音频播放用 AVPlayer,录制用 AudioCapturer 或直接走系统录音。AVPlayer 是统一入口,音频视频都归它管。
import { avPlayer } from '@kit.MediaKit'
async function play(url: string) {
const player = await avPlayer.createAVPlayer()
player.url = url
await player.prepare()
await player.play()
}
播放状态监听 player.on('stateChange'),缓冲、就绪、结束都从这里拿。录制注意采样率和声道配置,语音场景 16k 单声道就够,别白白占空间。
媒体能力的接入路径并不复杂,但有几个容易踩的坑值得留意:一是权限要在调用前声明并在运行时动态申请,摄像头和麦克风属于敏感权限,用户拒绝后要给出合理的引导说明;二是资源释放,播放器用完要调用 release,避免后台继续占用解码资源;三是格式兼容,鸿蒙的媒体框架对常见容器和编码支持比较全面,但个别低码率或老旧格式可能出现不支持的情况,接入时最好先做一次能力查询,再根据返回值决定是否提示用户升级版本或转码。把这三个问题在开发早期解决掉,多媒体功能上线后出问题的概率会小很多。
视频播放与编辑
视频播放同样走 AVPlayer,配合 XComponent 绑定渲染 surface。编辑能力(裁剪、拼接、加字幕)鸿蒙提供视频处理能力,接口偏底层,先从小需求做起。
// 视频画面绑定到 XComponent 的 surface
player.setVideoSurface(surfaceId)
await player.prepare()
await player.play()
播放列表要预加载下一个、释放上一个,避免卡顿。全屏切换时同步 surface 尺寸,否则画面会拉伸变形。
实战:图片选择与压缩
头像上传的完整链路:相册选图、压缩、上传。相机原图可能好几 MB,上传前必须压。用 ImagePacker 按质量压缩,再按尺寸缩放。
import { image } from '@kit.ImageKit'
async function compress(src: image.ImageSource, targetBytes: number) {
const packer = image.createImagePacker()
const quality = 80
const data = await packer.packToData(src, {
format: 'image/jpeg',
quality: quality
})
return data // 不满意的循环降 quality 再压
}
压缩不是无限降质量:先限宽高(如 1080),再调质量到目标体积。压完用原图比例校验,别把用户照片压变形。
小结
鸿蒙多媒体四件套:相机权限要动态申请、拍照走会话出图、相册用 photoAccessHelper、音视频播放统一 AVPlayer。上传场景记得压缩,播放场景记得预加载。把权限说明写清楚、把资源释放做干净,多媒体功能就能既好用又不惹事。从小链路练起,逐步吃透整套媒体能力。