在移动应用生态中,媒体功能是用户体验的核心。无论是构建音视频播放器、短视频应用,还是开发在线会议工具,强大的媒体能力都至关重要。鸿蒙Next通过其统一的媒体引擎,为开发者提供了一套高效、简洁的ArkTS API。本文将深入探讨四大核心场景:播放、录制、媒体信息查询视频转码,助你快速掌握鸿蒙媒体开发。

一、媒体播放:打造沉浸式视听体验

鸿蒙的@ohos.multimedia.media库提供了强大的播放器能力,支持多种协议和格式。

核心能力:

  • 格式支持:音频(AAC, MP3等)、视频(H.264, H.265/HEVC, MPEG-4等)。

  • 播放控制:播放、暂停、seek、速率控制、循环播放。

  • 渲染控制:视频支持Surface渲染,可无缝嵌入XComponent组件。

实战代码:实现一个简单的视频播放器

typescript

import media from '@ohos.multimedia.media';
import { BusinessError } from '@ohos.base';

@Entry
@Component
struct VideoPlayer {
  // 1. 定义播放器对象
  private avPlayer: media.AVPlayer | undefined = undefined;
  // 2. 获取XComponent控制器,用于渲染视频画面
  @Consume xComponentController: XComponentController;

  aboutToAppear() {
    this.initAvPlayer();
  }

  // 初始化播放器
  async initAvPlayer() {
    try {
      // 3. 创建AVPlayer实例
      this.avPlayer = await media.createAVPlayer();
      
      // 4. 设置监听器,处理状态变化和错误
      this.avPlayer.on('stateChange', (state: media.AVPlayerState) => {
        switch (state) {
          case media.AVPlayerState.IDLE:
            console.log('状态:空闲');
            break;
          case media.AVPlayerState.PREPARED:
            console.log('状态:准备完成,开始播放');
            this.avPlayer?.play(); // 准备完成后自动播放
            break;
          case media.AVPlayerState.PLAYING:
            console.log('状态:播放中');
            break;
          case media.AVPlayerState.PAUSED:
            console.log('状态:已暂停');
            break;
          case media.AVPlayerState.COMPLETED:
            console.log('状态:播放完成');
            break;
        }
      });

      this.avPlayer.on('error', (err: BusinessError) => {
        console.error(`播放器错误:${err.code}, ${err.message}`);
      });

      // 5. 设置视频源(这里使用网络URL,也支持资源路径fdSrc)
      let avFile: media.AVFile = {
        uri: 'https://www.example.com/sample.mp4' // 替换为实际视频URL
      };
      this.avPlayer.url = avFile;

      // 6. 准备播放器(异步操作,准备完成后会触发stateChange回调)
      await this.avPlayer.prepare();
    } catch (error) {
      const err: BusinessError = error as BusinessError;
      console.error(`初始化播放器失败:${err.code}, ${err.message}`);
    }
  }

  // 播放/暂停控制
  togglePlayPause() {
    if (this.avPlayer?.state === media.AVPlayerState.PLAYING) {
      this.avPlayer.pause();
    } else if (this.avPlayer?.state === media.AVPlayerState.PAUSED 
              || this.avPlayer?.state === media.AVPlayerState.PREPARED) {
      this.avPlayer.play();
    }
  }

  // 销毁播放器,释放资源
  aboutToDisappear() {
    if (this.avPlayer) {
      this.avPlayer.release();
      this.avPlayer = undefined;
    }
  }

  build() {
    Column() {
      // 7. 使用XComponent渲染视频画面
      XComponent({
        id: 'video_surface',
        type: 'surface',
        controller: this.xComponentController
      })
        .width('100%')
        .height(300)
        .onLoad(() => {
          // 获取SurfaceID并设置给播放器
          let surfaceId = this.xComponentController.getXComponentSurfaceId();
          this.avPlayer?.setSurface(surfaceId);
        })

      // 播放控制按钮
      Button('播放/暂停')
        .onClick(() => {
          this.togglePlayPause();
        })
        .margin(10)
    }
    .width('100%')
    .height('100%')
  }
}
二、媒体录制:捕捉精彩瞬间

鸿蒙的录制功能同样通过@ohos.multimedia.media提供,支持音视频录制。

核心能力:

  • 录制配置:可配置音频采样率、视频分辨率、码率、帧率等。

  • 灵活输出:支持指定输出文件路径。

  • 状态管理:完整的录制状态机(准备、录制、暂停、恢复)。

实战代码:实现音频录制

typescript

import media from '@ohos.multimedia.media';
import fileIo from '@ohos.file.fs';

@Entry
@Component
struct AudioRecorder {
  private audioRecorder: media.AudioRecorder | undefined = undefined;
  @State isRecording: boolean = false;

  async initRecorder() {
    try {
      // 1. 创建音频录制实例
      this.audioRecorder = await media.createAudioRecorder();
      
      // 2. 配置录制参数
      let audioConfig: media.AudioRecorderOptions = {
        encoder: media.AudioEncoder.AAC_LC,          // 编码格式
        sampleRate: media.AudioSampleRate.SAMPLE_RATE_44100, // 采样率
        numberOfChannels: 2,                         // 声道数
        bitRate: 32000,                              // 码率
        format: media.AudioOutputFormat.MPEG_4,      // 输出格式
        uri: 'file:///path/to/recorded_audio.m4a'    // 输出文件路径
      };

      // 3. 准备录制
      await this.audioRecorder.prepare(audioConfig);
      console.log('录制器准备就绪');
    } catch (error) {
      const err: BusinessError = error as BusinessError;
      console.error(`初始化录制器失败:${err.code}, ${err.message}`);
    }
  }

  // 开始/停止录制
  async toggleRecording() {
    if (!this.audioRecorder) return;

    if (!this.isRecording) {
      try {
        await this.audioRecorder.start();
        this.isRecording = true;
        console.log('开始录制');
      } catch (error) {
        const err: BusinessError = error as BusinessError;
        console.error(`开始录制失败:${err.code}, ${err.message}`);
      }
    } else {
      await this.audioRecorder.stop();
      this.isRecording = false;
      console.log('停止录制');
      await this.audioRecorder.release();
      this.audioRecorder = undefined;
    }
  }

  build() {
    Column() {
      Button(this.isRecording ? '停止录制' : '开始录制')
        .onClick(() => {
          this.toggleRecording();
        })
        .margin(10)
    }
  }
}
三、媒体信息查询:读懂媒体文件

在处理媒体文件前,了解其详细信息(如时长、编码格式、分辨率等)是必要的。

实战代码:查询视频文件信息

typescript

import media from '@ohos.multimedia.media';

async function getVideoInfo(fileUri: string) {
  try {
    // 1. 创建AVMetadataExtractor实例
    let extractor: media.AVMetadataExtractor = await media.createAVMetadataExtractor();
    
    // 2. 设置数据源
    extractor.src = fileUri;

    // 3. 获取文件格式信息
    let fileFormat: string = await extractor.fetchFileFormat();
    console.log(`文件格式:${fileFormat}`);

    // 4. 获取元数据(以键值对形式返回)
    let metadata: media.Metadata = await extractor.fetchMetadata();
    console.log(`视频时长:${metadata.duration} ms`);
    console.log(`视频码率:${metadata.bitrate} bps`);
    
    // 5. 获取视频轨道信息
    let videoTracks: Array<media.AVTrackInfo> = await extractor.fetchVideoTrackInfo();
    if (videoTracks.length > 0) {
      let videoTrack = videoTracks[0];
      console.log(`视频编码:${videoTrack.codecName}`);
      console.log(`视频分辨率:${videoTrack.width} x ${videoTrack.height}`);
      console.log(`视频帧率:${videoTrack.frameRate}`);
    }

    // 6. 获取音频轨道信息
    let audioTracks: Array<media.AVTrackInfo> = await extractor.fetchAudioTrackInfo();
    if (audioTracks.length > 0) {
      let audioTrack = audioTracks[0];
      console.log(`音频编码:${audioTrack.codecName}`);
      console.log(`音频采样率:${audioTrack.sampleRate} Hz`);
      console.log(`音频声道数:${audioTrack.channelCount}`);
    }

    // 7. 释放资源
    extractor.release();
  } catch (error) {
    const err: BusinessError = error as BusinessError;
    console.error(`查询媒体信息失败:${err.code}, ${err.message}`);
  }
}
四、视频转码:格式转换的利器

视频转码是将视频从一种格式转换为另一种格式的过程,常用于兼容性处理或压缩文件大小。

实战代码:将视频转为MP4格式

typescript

import media from '@ohos.multimedia.media';

async function transcodeVideo(inputUri: string, outputUri: string): Promise<void> {
  let transcode: media.Transcode | undefined = undefined;
  
  try {
    // 1. 创建转码实例
    transcode = await media.createTranscode();

    // 2. 配置转码参数
    let transcodeProfile: media.TranscodeProfile = {
      audioSampleRate: 44100,        // 音频采样率
      audioChannels: 2,              // 音频声道数
      audioBitrate: 128000,          // 音频码率
      videoFrameRate: 30,            // 视频帧率
      videoBitrate: 2000000,         // 视频码率
      videoWidth: 1280,              // 输出视频宽度
      videoHeight: 720,              // 输出视频高度
      fileFormat: media.ContainerFormatType.CFT_MP4 // 输出容器格式
    };

    // 3. 设置输入输出路径
    await transcode.configure(inputUri, outputUri, transcodeProfile);

    // 4. 开始转码(异步操作)
    transcode.on('progress', (progress: number) => {
      console.log(`转码进度:${progress}%`);
    });

    transcode.on('complete', () => {
      console.log('转码完成');
    });

    transcode.on('error', (err: BusinessError) => {
      console.error(`转码失败:${err.code}, ${err.message}`);
    });

    await transcode.start();

  } catch (error) {
    const err: BusinessError = error as BusinessError;
    console.error(`转码初始化失败:${err.code}, ${err.message}`);
  } finally {
    // 5. 释放资源
    if (transcode) {
      transcode.release();
    }
  }
}

// 使用示例
// transcodeVideo('file:///path/to/input.video', 'file:///path/to/output.mp4');
总结与最佳实践

鸿蒙Next的媒体框架通过清晰的API设计,让复杂的媒体操作变得简单:

  1. 播放:使用AVPlayer + XComponent实现流畅播放

  2. 录制:使用AudioRecorder/VideoRecorder进行音视频捕捉

  3. 查询:使用AVMetadataExtractor获取详细的媒体元数据

  4. 转码:使用Transcode服务进行格式转换

开发注意事项:

  • 权限申请:录制、访问文件等操作需要在module.json5中声明相应权限。

  • 资源释放:务必在组件销毁或不再使用时调用release()方法,避免资源泄漏。

  • 错误处理:所有媒体操作都应添加try-catch块,确保应用稳定性。

  • 性能考虑:转码等耗时操作应在后台进行,避免阻塞UI线程。

掌握这些核心媒体能力,你就能在鸿蒙生态中构建出功能丰富、性能卓越的音视频应用。现在就开始实践,为用户创造出色的媒体体验吧!

Logo

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

更多推荐