图片与多媒体开发:Image、Camera、音频播放

图片与音视频是富媒体应用的核心。鸿蒙在 @kit.ArkUI@kit.CameraKit@kit.MediaKit 中提供完整能力。本文讲清图片加载/处理、相机调用、音频播放与录制,给出可运行示例与权限要点。


一、Image 图片加载

回顾 Image 的多种来源:

// 1. 本地资源
Image($r('app.media.logo')).width(80).height(80)

// 2. 网络图片(需 INTERNET 权限)
Image('https://example.com/p.jpg')
  .width(200).height(200)
  .objectFit(ImageFit.Cover)
  .onComplete((msg) => { console.info('尺寸:' + msg.width + 'x' + msg.height); })
  .onError(() => { console.error('加载失败'); })

// 3. 沙箱文件路径
Image('file://' + getContext(this).filesDir + '/local.png').width(100)

// 4. PixelMap(内存位图,可做圆角/模糊处理)
Image(this.pixelMap).width(100).height(100)

二、图片处理:圆角、裁剪、模糊

// 圆角
Image($r('app.media.avatar'))
  .width(60).height(60)
  .borderRadius(30)   // 圆形头像
  .clip(true)

// 模糊(背景虚化)
Image($r('app.media.bg'))
  .blur(10)           // 模糊半径
  .width('100%').height(200)

// 缩放模式
Image(src)
  .objectFit(ImageFit.Contain) // 完整显示不裁剪

圆形头像 = .borderRadius(宽高一半) + .clip(true),是社区最常用技巧。


三、图片选择器(用户选图)

调用系统图库选图,用 @kit.ImageKitphotoAccessHelper

import { photoAccessHelper } from '@kit.ImageKit';
import { common } from '@kit.AbilityKit';

async function pickImage(context: common.UIAbilityContext): Promise<void> {
  const picker = new photoAccessHelper.PhotoViewPicker();
  const result = await picker.select({
    MIMEType: photoAccessHelper.PhotoViewMimeType.IMAGE_TYPE,
    maxSelectNumber: 1
  });
  const uri = result.photoUris[0];
  console.info('选中图片:' + uri);
  // 用 Image(uri) 直接显示,或复制到沙箱处理
}

选完拿到的是 URI,可直接给 Image() 显示,或复制到应用沙箱再做处理。


四、相机调用

拍照/录像需相机权限与 @kit.CameraKit

// module.json5 权限
"requestPermissions": [
  { "name": "ohos.permission.CAMERA" },
  { "name": "ohos.permission.MICROPHONE" }
]

XComponent 承载相机预览,Camera Kit 控制采集。简化思路:

import { camera } from '@kit.CameraKit';

// 1) 获取相机管理器与相机输入
const cameraManager = camera.getCameraManager(context);
const cameras = cameraManager.getSupportedCameras();
const cameraInput = cameraManager.createCameraInput(cameras[0]);

// 2) 创建预览输出,绑定到 XComponent 的 surfaceId
const previewOutput = cameraManager.createPreviewOutput(profile, surfaceId);

// 3) 会话 start
const session = cameraManager.createCaptureSession();
session.addInput(cameraInput);
session.addOutput(previewOutput);
await session.start();

// 4) 拍照:创建 photoOutput,capture()

相机能力较强,真实项目建议封装成 CameraManager 单例,管理生命周期与权限弹窗。


五、音频播放

@kit.MediaKitAVPlayer 播放音频/视频:

import { media } from '@kit.MediaKit';

async function playAudio(url: string): Promise<void> {
  const player = await media.createAVPlayer();
  player.url = url; // 网络或沙箱路径
  player.on('stateChange', (state) => {
    if (state === 'initialized') player.prepare();
    if (state === 'prepared') player.play();
  });
  player.on('error', (err) => { console.error('播放错误:' + err); });
}

// 控制
// player.pause(); player.seek(10 * 1000); player.release();

状态机:idle → initialized → prepared → playing → paused → stopped。务必按状态流转调用,别在 initializedplay,否则报错。


六、音频录制

AVRecorder 录制:

import { media } from '@kit.MediaKit';

async function record(context: common.UIAbilityContext): Promise<void> {
  const recorder = await media.createAVRecorder();
  const avProfile: media.AVRecorderProfile = {
    audioBitrate: 48000,
    audioChannels: 1,
    audioSampleRate: 48000,
    audioCodec: media.CodecMimeType.AUDIO_AAC,
    fileFormat: media.ContainerFormatType.CFT_MPEG_4A
  };
  const fd = fileIo.openSync(context.filesDir + '/rec.aac', 0o102, 0o666).fd;
  await recorder.prepare(avProfile, fd);
  await recorder.start();
  // recorder.pause(); recorder.stop(); recorder.release();
}

录音需 MICROPHONE 权限。


七、视频播放

AVPlayer 同样支持视频,预览用 XComponent

@Component
struct VideoPlayer {
  private player?: media.AVPlayer;
  private surfaceId: string = '';

  build() {
    Column() {
      XComponent({ id: 'video', type: 'surface', controller: this.xc })
        .onLoad((surfaceId) => { this.surfaceId = surfaceId; })
        .width('100%').height(240)
      Button('播放').onClick(() => { this.start(); })
    }
  }

  async start(): Promise<void> {
    this.player = await media.createAVPlayer();
    this.player.url = 'https://example.com/a.mp4';
    this.player.surfaceId = this.surfaceId; // 绑定渲染面
    this.player.on('stateChange', (s) => { if (s === 'prepared') this.player!.play(); });
  }
}

八、媒体库写入(保存图片/视频)

拍完的图要存进系统相册,用 photoAccessHelpergetAssets 写入:

async function saveToGallery(context: common.UIAbilityContext, fileUri: string): Promise<void> {
  const ph = photoAccessHelper.getPhotoAccessHelper(context);
  const asset = await ph.createAsset(photoAccessHelper.PhotoType.IMAGE, 'jpg');
  // 用 asset 的 fd 把文件内容写入相册
}

九、权限最佳实践

媒体类权限大多需在 module.json5 声明,且敏感权限(相机、麦克风)运行时弹窗申请

import { abilityAccessCtrl, PermissionRequestResult, common } from '@kit.AbilityKit';

async function reqCamera(context: common.UIAbilityContext): Promise<boolean> {
  const atManager = abilityAccessCtrl.createAtManager();
  const result: PermissionRequestResult = await atManager.requestPermissionsFromUser(
    context, ['ohos.permission.CAMERA']
  );
  return result.authResults[0] === 0;
}

十、常见坑

现象 原因 解决
图片不显示 网络图未申 INTERNET 加权限
相机黑屏 surfaceId 未绑定 XComponent onLoad 后设置
播放报错 状态未就绪就调用 按 stateChange 流转
录音频无声音 未申 MICROPHONE 加权限并弹窗

十一、实战:头像上传

// 选图 → 显示 → 上传
@Component
struct AvatarUpload {
  @State avatarUri: string = '';

  build() {
    Column() {
      if (this.avatarUri !== '') {
        Image(this.avatarUri).width(80).height(80).borderRadius(40).clip(true)
      }
      Button('选择头像').onClick(() => {
        pickImage(getContext(this) as common.UIAbilityContext).then(uri => {
          this.avatarUri = uri;
          // 再调 api.post('/avatar', { file: uri })
        });
      })
    }
  }
}

十二、总结

鸿蒙的多媒体能力覆盖图片、相机、音视频全链路。Image 负责展示与处理(圆角/模糊/裁剪),photoAccessHelper 负责选图与存库,CameraKit 负责相机采集,MediaKit 的 AVPlayer/AVRecorder 负责播放与录制。核心三件事:权限先声明再申请、媒体对象按状态机流转、资源用完 release。掌握这些,你能做出带图、带声、带影像的富媒体应用。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐