一、Media Kit概述

Media Kit是HarmonyOS提供的媒体服务框架,提供音视频播放、录制、编解码等全方位的媒体处理能力。

1.1 核心能力

能力类型说明主要API
音频播放播放各种格式音频文件AVPlayer, SoundPool, AudioRenderer
视频播放播放各种格式视频文件AVPlayer, Video组件
音频录制录制音频AVRecorder, AudioCapturer
视频录制录制视频AVRecorder
音视频解码解码音视频数据AVDemuxer, AVDecoder
音视频编码编码音视频数据AVMuxer, AVEncoder

1.2 选择合适的API

音频播放场景:

简短音效<5s

完整音频文件

PCM数据流

音振协同

选择音频播放API

场景判断

SoundPool

AVPlayer

AudioRenderer

AudioHaptic

低时延播放

支持多种格式

需要预处理

铃声/反馈

视频播放场景:

  • AVPlayer: 功能完善,支持多种格式,适合专业视频播放
  • Video组件: UI组件封装,简单易用,适合快速开发

二、音频播放开发

2.1 使用AVPlayer播放音频

AVPlayer适用于播放完整的音频文件,支持mp3、m4a、flac等格式。

2.1.1 AVPlayer状态机

createAVPlayer()

url设置

prepare()

play()

pause()

play()

stop()

prepare()

release()

release()

idle

initialized

prepared

playing

paused

stopped

released

2.1.2 完整示例

import { media } from '@kit.MediaKit'; import { BusinessError } from '@kit.BasicServicesKit'; class AudioPlayer { private avPlayer: media.AVPlayer | undefined = undefined; async init() { // 1. 创建AVPlayer实例 this.avPlayer = await media.createAVPlayer(); // 2. 设置状态变化监听 this.avPlayer.on('stateChange', (state: string, reason: media.StateChangeReason) => { console.info(`AVPlayer state changed to: ${state}, reason: ${reason}`); }); // 3. 设置错误监听 this.avPlayer.on('error', (error: BusinessError) => { console.error(`AVPlayer error: ${error.code}, ${error.message}`); }); // 4. 监听播放进度 this.avPlayer.on('timeUpdate', (time: number) => { console.info(`Current time: ${time}ms`); }); // 5. 监听播放完成 this.avPlayer.on('durationUpdate', (duration: number) => { console.info(`Total duration: ${duration}ms`); }); } async playAudio(url: string) { if (!this.avPlayer) { return; } try { // 设置音频资源 this.avPlayer.url = url; // 准备播放 await this.avPlayer.prepare(); // 开始播放 await this.avPlayer.play(); } catch (err) { let error = err as BusinessError; console.error(`Play failed: ${error.code}, ${error.message}`); } } async pause() { if (this.avPlayer && this.avPlayer.state === 'playing') { await this.avPlayer.pause(); } } async resume() { if (this.avPlayer && this.avPlayer.state === 'paused') { await this.avPlayer.play(); } } async seek(time: number) { if (this.avPlayer) { await this.avPlayer.seek(time, media.SeekMode.SEEK_PREV_SYNC); } } async stop() { if (this.avPlayer) { await this.avPlayer.stop(); } } async release() { if (this.avPlayer) { await this.avPlayer.release(); this.avPlayer = undefined; } } } // 使用示例 let player = new AudioPlayer(); await player.init(); await player.playAudio('https://example.com/audio.mp3');

2.2 使用SoundPool播放短音

SoundPool适用于播放低时延的短音效,如按键音、提示音等。

2.2.1 工作流程

应用SoundPool解码器音频系统createSoundPool()load(fd)解码音频解码完成on('loadComplete')play(soundId)播放音频播放完成on('playFinished')应用SoundPool解码器音频系统

2.2.2 代码示例

import { media } from '@kit.MediaKit'; import { audio } from '@kit.AudioKit'; import { BusinessError } from '@kit.BasicServicesKit'; class SoundEffectPlayer { private soundPool: media.SoundPool | undefined = undefined; private soundId: number = 0; private streamId: number = 0; async init() { // 1. 配置音频渲染信息 let audioRendererInfo: audio.AudioRendererInfo = { usage: audio.StreamUsage.STREAM_USAGE_MUSIC, rendererFlags: 1 }; // 2. 创建SoundPool实例,最大支持14个并发流 this.soundPool = await media.createSoundPool(14, audioRendererInfo); // 3. 监听资源加载完成 this.soundPool.on('loadComplete', (soundId: number) => { this.soundId = soundId; console.info(`Sound loaded: ${soundId}`); }); // 4. 监听播放完成 this.soundPool.on('playFinishedWithStreamId', (streamId: number) => { console.info(`Play finished: ${streamId}`); }); // 5. 监听错误 this.soundPool.on('error', (error: BusinessError) => { console.error(`SoundPool error: ${error.code}`); }); } async loadSound(fd: number, offset: number, length: number) { if (this.soundPool) { this.soundId = await this.soundPool.load(fd, offset, length); } } async playSound() { if (!this.soundPool) { return; } let playParameters: media.PlayParameters = { loop: 0, // 不循环 rate: 1, // 正常速度 leftVolume: 1.0, rightVolume: 1.0, priority: 0 }; this.soundPool.play(this.soundId, playParameters, (error, streamId: number) => { if (error) { console.error(`Play error: ${error.code}`); } else { this.streamId = streamId; console.info(`Playing stream: ${streamId}`); } }); } async release() { if (this.soundPool) { await this.soundPool.off('loadComplete'); await this.soundPool.off('playFinishedWithStreamId'); await this.soundPool.off('error'); await this.soundPool.release(); this.soundPool = undefined; } } } // 使用示例 let soundPlayer = new SoundEffectPlayer(); await soundPlayer.init(); // 从rawfile加载音频 let context = getContext(this); let fileDescriptor = await context.resourceManager.getRawFd('click.ogg'); await soundPlayer.loadSound(fileDescriptor.fd, fileDescriptor.offset, fileDescriptor.length); await soundPlayer.playSound();

三、视频播放开发

3.1 AVPlayer视频播放

视频播放在音频播放基础上增加了视窗显示功能。

3.1.1 关键步骤

应用AVPlayerXComponent视频系统createAVPlayer()设置监听url = videoUrl获取surfaceIdsurfaceIdsurfaceId = idprepare()初始化视频管道play()渲染视频帧显示画面应用AVPlayerXComponent视频系统

3.1.2 完整代码示例

import { media } from '@kit.MediaKit'; import { BusinessError } from '@kit.BasicServicesKit'; @Entry @Component struct VideoPlayer { private avPlayer: media.AVPlayer | undefined = undefined; private surfaceId: string = ''; @State isPlaying: boolean = false; @State currentTime: number = 0; @State duration: number = 0; async aboutToAppear() { await this.initPlayer(); } async initPlayer() { // 1. 创建AVPlayer this.avPlayer = await media.createAVPlayer(); // 2. 设置状态监听 this.avPlayer.on('stateChange', (state: string, reason: media.StateChangeReason) => { console.info(`State: ${state}`); if (state === 'playing') { this.isPlaying = true; } else if (state === 'paused' || state === 'stopped') { this.isPlaying = false; } }); // 3. 设置错误监听 this.avPlayer.on('error', (error: BusinessError) => { console.error(`Error: ${error.code}`); }); // 4. 监听时长 this.avPlayer.on('durationUpdate', (duration: number) => { this.duration = duration; }); // 5. 监听进度 this.avPlayer.on('timeUpdate', (time: number) => { this.currentTime = time; }); // 6. 监听视频尺寸变化 this.avPlayer.on('videoSizeChange', (width: number, height: number) => { console.info(`Video size: ${width}x${height}`); }); // 7. 监听首帧渲染 this.avPlayer.on('startRenderFrame', () => { console.info('First frame rendered'); }); } async playVideo(url: string) { if (!this.avPlayer || !this.surfaceId) { return; } try { // 设置视频URL this.avPlayer.url = url; // 设置窗口 this.avPlayer.surfaceId = this.surfaceId; // 准备播放 await this.avPlayer.prepare(); // 开始播放 await this.avPlayer.play(); } catch (err) { let error = err as BusinessError; console.error(`Play failed: ${error.message}`); } } async pauseVideo() { if (this.avPlayer && this.isPlaying) { await this.avPlayer.pause(); } } async resumeVideo() { if (this.avPlayer && !this.isPlaying) { await this.avPlayer.play(); } } async seekTo(time: number) { if (this.avPlayer) { await this.avPlayer.seek(time); } } formatTime(ms: number): string { let seconds = Math.floor(ms / 1000); let minutes = Math.floor(seconds / 60); let remainingSeconds = seconds % 60; return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`; } build() { Column() { // 视频显示区域 XComponent({ id: 'video_player', type: XComponentType.SURFACE, controller: new XComponentController() }) .onLoad((context) => { // 获取surfaceId this.surfaceId = context.getXComponentSurfaceId(); // 播放视频 this.playVideo('https://example.com/video.mp4'); }) .width('100%') .height(300) // 播放控制区域 Row({ space: 20 }) { // 播放/暂停按钮 Button(this.isPlaying ? '暂停' : '播放') .onClick(() => { if (this.isPlaying) { this.pauseVideo(); } else { this.resumeVideo(); } }) // 进度显示 Text(`${this.formatTime(this.currentTime)} / ${this.formatTime(this.duration)}`) .fontSize(14) } .width('90%') .margin({ top: 20 }) // 进度条 Slider({ value: this.currentTime, min: 0, max: this.duration, step: 1000 }) .width('90%') .onChange((value: number) => { this.seekTo(value); }) } .width('100%') .height('100%') } aboutToDisappear() { if (this.avPlayer) { this.avPlayer.release(); } } }

四、音频录制开发

4.1 使用AudioCapturer录制音频

AudioCapturer用于采集PCM音频数据。


import { audio } from '@kit.AudioKit'; import { BusinessError } from '@kit.BasicServicesKit'; import { fileIo as fs } from '@kit.CoreFileKit'; class AudioRecorder { private audioCapturer: audio.AudioCapturer | undefined = undefined; private audioFile: fs.File | undefined = undefined; async init() { // 1. 配置音频采集参数 let audioStreamInfo: audio.AudioStreamInfo = { samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_44100, channels: audio.AudioChannel.CHANNEL_2, sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE, encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW }; let audioCapturerInfo: audio.AudioCapturerInfo = { source: audio.SourceType.SOURCE_TYPE_MIC, capturerFlags: 0 }; let audioCapturerOptions: audio.AudioCapturerOptions = { streamInfo: audioStreamInfo, capturerInfo: audioCapturerInfo }; // 2. 创建AudioCapturer this.audioCapturer = await audio.createAudioCapturer(audioCapturerOptions); // 3. 监听状态变化 this.audioCapturer.on('stateChange', (state: audio.AudioState) => { console.info(`AudioCapturer state: ${state}`); }); } async startRecording(filePath: string) { if (!this.audioCapturer) { return; } try { // 创建文件 this.audioFile = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); // 启动录制 await this.audioCapturer.start(); // 读取音频数据并写入文件 let bufferSize = await this.audioCapturer.getBufferSize(); let buffer = await this.audioCapturer.read(bufferSize, true); fs.writeSync(this.audioFile.fd, buffer); } catch (err) { let error = err as BusinessError; console.error(`Recording failed: ${error.message}`); } } async stopRecording() { if (this.audioCapturer) { await this.audioCapturer.stop(); await this.audioCapturer.release(); } if (this.audioFile) { fs.closeSync(this.audioFile); } } }

五、视频录制开发

5.1 使用AVRecorder录制视频

AVRecorder集成了音视频采集、编码、封装功能。

5.1.1 录制状态机

createAVRecorder()

prepare()

start()

pause()

resume()

stop()

prepare()

release()

idle

prepared

started

paused

stopped

released

5.1.2 代码示例

import { media } from '@kit.MediaKit'; import { camera } from '@kit.CameraKit'; import { BusinessError } from '@kit.BasicServicesKit'; import { fileIo as fs } from '@kit.CoreFileKit'; class VideoRecorder { private avRecorder: media.AVRecorder | undefined = undefined; private videoFile: fs.File | undefined = undefined; async init() { // 1. 创建AVRecorder this.avRecorder = await media.createAVRecorder(); // 2. 设置状态监听 this.avRecorder.on('stateChange', (state: media.AVRecorderState, reason: media.StateChangeReason) => { console.info(`AVRecorder state: ${state}, reason: ${reason}`); }); // 3. 设置错误监听 this.avRecorder.on('error', (error: BusinessError) => { console.error(`AVRecorder error: ${error.code}`); }); } async startRecording(context: Context) { if (!this.avRecorder) { return; } try { // 1. 创建录制文件 let filePath = context.filesDir + '/video.mp4'; this.videoFile = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); // 2. 配置录制参数 let avProfile: media.AVRecorderProfile = { fileFormat: media.ContainerFormatType.CFT_MPEG_4, videoBitrate: 2000000, videoCodec: media.CodecMimeType.VIDEO_AVC, videoFrameWidth: 1920, videoFrameHeight: 1080, videoFrameRate: 30 }; let avConfig: media.AVRecorderConfig = { videoSourceType: media.VideoSourceType.VIDEO_SOURCE_TYPE_SURFACE_YUV, profile: avProfile, url: 'fd://' + this.videoFile.fd, metadata: { videoOrientation: '0' } }; // 3. 准备录制 await this.avRecorder.prepare(avConfig); // 4. 获取Surface用于相机输入 let surfaceId = await this.avRecorder.getInputSurface(); // 5. 初始化相机(省略相机初始化代码) // await this.initCamera(surfaceId); // 6. 开始录制 await this.avRecorder.start(); } catch (err) { let error = err as BusinessError; console.error(`Start recording failed: ${error.message}`); } } async pauseRecording() { if (this.avRecorder && this.avRecorder.state === 'started') { await this.avRecorder.pause(); } } async resumeRecording() { if (this.avRecorder && this.avRecorder.state === 'paused') { await this.avRecorder.resume(); } } async stopRecording() { if (this.avRecorder) { await this.avRecorder.stop(); await this.avRecorder.release(); } if (this.videoFile) { fs.closeSync(this.videoFile); } } }

六、实战示例:多媒体播放器应用

6.1 应用架构


MediaPlayerApp/ ├── entry/ │ └── src/main/ │ ├── ets/ │ │ ├── entryability/ │ │ │ └── EntryAbility.ets │ │ ├── pages/ │ │ │ ├── Index.ets (首页) │ │ │ ├── AudioPlayer.ets (音频播放器) │ │ │ └── VideoPlayer.ets (视频播放器) │ │ └── model/ │ │ ├── MediaManager.ets (媒体管理器) │ │ └── PlaylistModel.ets (播放列表) │ └── resources/ │ └── rawfile/ │ ├── audio/ │ └── video/

6.2 媒体管理器实现


import { media } from '@kit.MediaKit'; import { BusinessError } from '@kit.BasicServicesKit'; export interface MediaItem { id: string; title: string; url: string; duration: number; type: 'audio' | 'video'; } export class MediaManager { private avPlayer: media.AVPlayer | undefined = undefined; private currentMedia: MediaItem | null = null; private onStateChange?: (state: string) => void; private onTimeUpdate?: (time: number) => void; private onDurationUpdate?: (duration: number) => void; async init() { this.avPlayer = await media.createAVPlayer(); // 状态变化监听 this.avPlayer.on('stateChange', (state: string, reason: media.StateChangeReason) => { console.info(`State changed to: ${state}`); if (this.onStateChange) { this.onStateChange(state); } }); // 错误监听 this.avPlayer.on('error', (error: BusinessError) => { console.error(`Player error: ${error.code}, ${error.message}`); }); // 时长更新 this.avPlayer.on('durationUpdate', (duration: number) => { if (this.onDurationUpdate) { this.onDurationUpdate(duration); } }); // 进度更新 this.avPlayer.on('timeUpdate', (time: number) => { if (this.onTimeUpdate) { this.onTimeUpdate(time); } }); } setStateChangeListener(callback: (state: string) => void) { this.onStateChange = callback; } setTimeUpdateListener(callback: (time: number) => void) { this.onTimeUpdate = callback; } setDurationUpdateListener(callback: (duration: number) => void) { this.onDurationUpdate = callback; } async playMedia(media: MediaItem, surfaceId?: string) { if (!this.avPlayer) { return; } try { this.currentMedia = media; this.avPlayer.url = media.url; if (media.type === 'video' && surfaceId) { this.avPlayer.surfaceId = surfaceId; } await this.avPlayer.prepare(); await this.avPlayer.play(); } catch (err) { let error = err as BusinessError; console.error(`Play media failed: ${error.message}`); } } async pause() { if (this.avPlayer && this.avPlayer.state === 'playing') { await this.avPlayer.pause(); } } async resume() { if (this.avPlayer && this.avPlayer.state === 'paused') { await this.avPlayer.play(); } } async seek(time: number) { if (this.avPlayer) { await this.avPlayer.seek(time, media.SeekMode.SEEK_PREV_SYNC); } } async stop() { if (this.avPlayer) { await this.avPlayer.stop(); this.currentMedia = null; } } async release() { if (this.avPlayer) { await this.avPlayer.release(); this.avPlayer = undefined; } } getCurrentMedia(): MediaItem | null { return this.currentMedia; } getState(): string { return this.avPlayer?.state || 'idle'; } }

6.3 音频播放器页面


import { MediaManager, MediaItem } from '../model/MediaManager'; @Entry @Component struct AudioPlayerPage { @State playlist: MediaItem[] = []; @State currentIndex: number = 0; @State isPlaying: boolean = false; @State currentTime: number = 0; @State duration: number = 0; private mediaManager: MediaManager = new MediaManager(); async aboutToAppear() { // 初始化媒体管理器 await this.mediaManager.init(); // 设置监听回调 this.mediaManager.setStateChangeListener((state: string) => { this.isPlaying = (state === 'playing'); }); this.mediaManager.setTimeUpdateListener((time: number) => { this.currentTime = time; }); this.mediaManager.setDurationUpdateListener((duration: number) => { this.duration = duration; }); // 加载播放列表 this.loadPlaylist(); } loadPlaylist() { this.playlist = [ { id: '1', title: '音乐1', url: 'https://example.com/music1.mp3', duration: 0, type: 'audio' }, { id: '2', title: '音乐2', url: 'https://example.com/music2.mp3', duration: 0, type: 'audio' } ]; } async playAudio(index: number) { if (index >= 0 && index < this.playlist.length) { this.currentIndex = index; await this.mediaManager.playMedia(this.playlist[index]); } } async togglePlayPause() { if (this.isPlaying) { await this.mediaManager.pause(); } else { await this.mediaManager.resume(); } } async playNext() { let nextIndex = (this.currentIndex + 1) % this.playlist.length; await this.playAudio(nextIndex); } async playPrevious() { let prevIndex = (this.currentIndex - 1 + this.playlist.length) % this.playlist.length; await this.playAudio(prevIndex); } formatTime(ms: number): string { let totalSeconds = Math.floor(ms / 1000); let minutes = Math.floor(totalSeconds / 60); let seconds = totalSeconds % 60; return `${minutes}:${seconds.toString().padStart(2, '0')}`; } build() { Column() { // 顶部导航 Row() { Text('音频播放器') .fontSize(24) .fontWeight(FontWeight.Bold) } .width('100%') .padding(20) .backgroundColor('#f0f0f0') // 播放列表 List({ space: 10 }) { ForEach(this.playlist, (item: MediaItem, index: number) => { ListItem() { Row() { Text(item.title) .fontSize(16) .layoutWeight(1) .fontColor(index === this.currentIndex ? '#007DFF' : '#000') if (index === this.currentIndex) { Text(this.isPlaying ? '播放中' : '已暂停') .fontSize(12) .fontColor('#666') } } .width('100%') .padding(15) .backgroundColor(index === this.currentIndex ? '#e6f2ff' : '#fff') .borderRadius(8) } .onClick(() => { this.playAudio(index); }) }, (item: MediaItem) => item.id) } .width('90%') .layoutWeight(1) .margin({ top: 20 }) // 播放控制区域 Column({ space: 20 }) { // 当前播放信息 Text(this.currentIndex >= 0 ? this.playlist[this.currentIndex].title : '未选择') .fontSize(18) .fontWeight(FontWeight.Medium) // 进度条 Column({ space: 10 }) { Slider({ value: this.currentTime, min: 0, max: this.duration, step: 1000 }) .width('100%') .onChange((value: number) => { this.mediaManager.seek(value); }) Row() { Text(this.formatTime(this.currentTime)) .fontSize(12) Blank() Text(this.formatTime(this.duration)) .fontSize(12) } .width('100%') } .width('100%') // 控制按钮 Row({ space: 30 }) { Button('上一首') .onClick(() => this.playPrevious()) Button(this.isPlaying ? '暂停' : '播放') .onClick(() => this.togglePlayPause()) .width(80) Button('下一首') .onClick(() => this.playNext()) } .width('100%') .justifyContent(FlexAlign.Center) } .width('90%') .padding(20) .backgroundColor('#f8f8f8') .borderRadius(10) .margin({ bottom: 20 }) } .width('100%') .height('100%') .backgroundColor('#fff') } aboutToDisappear() { this.mediaManager.release(); } }

七、后台播放与媒体会话

7.1 实现后台播放

要实现后台播放或熄屏播放,需要:

  1. 注册AVSession(媒体会话)
  2. 申请长时任务

import { AVSessionManager } from '@kit.AVSessionKit'; import { backgroundTaskManager } from '@kit.BackgroundTasksKit'; import { BusinessError } from '@kit.BasicServicesKit'; class BackgroundAudioPlayer { private session: AVSessionManager.AVSession | undefined = undefined; async setupBackgroundPlayback() { try { // 1. 创建媒体会话 this.session = await AVSessionManager.createAVSession( getContext(this), 'audio', 'com.example.mediaplayer' ); // 2. 激活会话 await this.session.activate(); // 3. 设置会话元数据 let metadata: AVSessionManager.AVMetadata = { assetId: '001', title: '歌曲标题', artist: '艺术家', album: '专辑名称', duration: 240000 }; await this.session.setAVMetadata(metadata); // 4. 设置播放状态 let playbackState: AVSessionManager.AVPlaybackState = { state: AVSessionManager.PlaybackState.PLAYBACK_STATE_PLAY, speed: 1.0, position: { elapsedTime: 0, updateTime: Date.now() } }; await this.session.setAVPlaybackState(playbackState); // 5. 申请长时任务 let bgMode = backgroundTaskManager.BackgroundMode.AUDIO_PLAYBACK; backgroundTaskManager.startBackgroundRunning(getContext(this), bgMode); } catch (err) { let error = err as BusinessError; console.error(`Setup background playback failed: ${error.message}`); } } async stopBackgroundPlayback() { // 停止长时任务 backgroundTaskManager.stopBackgroundRunning(getContext(this)); // 销毁会话 if (this.session) { await this.session.deactivate(); await this.session.destroy(); } } }

八、最佳实践

8.1 性能优化

1. 资源预加载


class MediaResourceManager { private soundPool: media.SoundPool | undefined = undefined; private soundCache: Map<string, number> = new Map(); async preloadSounds(sounds: string[]) { for (let sound of sounds) { let fd = await this.getSoundFd(sound); let soundId = await this.soundPool!.load(fd.fd, fd.offset, fd.length); this.soundCache.set(sound, soundId); } } async playPreloadedSound(soundName: string) { let soundId = this.soundCache.get(soundName); if (soundId) { await this.soundPool!.play(soundId, {} as media.PlayParameters, () => {}); } } private async getSoundFd(name: string) { let context = getContext(this); return await context.resourceManager.getRawFd(name); } }

2. 内存管理


class PlayerLifecycleManager { private player: media.AVPlayer | undefined = undefined; async onPageShow() { // 页面显示时创建播放器 if (!this.player) { this.player = await media.createAVPlayer(); } } async onPageHide() { // 页面隐藏时释放播放器资源 if (this.player) { await this.player.stop(); await this.player.release(); this.player = undefined; } } }

8.2 错误处理


class RobustMediaPlayer { private avPlayer: media.AVPlayer | undefined = undefined; private retryCount: number = 0; private maxRetries: number = 3; async playWithRetry(url: string) { try { await this.play(url); this.retryCount = 0; } catch (err) { let error = err as BusinessError; console.error(`Play failed: ${error.code}`); if (this.retryCount < this.maxRetries) { this.retryCount++; console.info(`Retry ${this.retryCount}/${this.maxRetries}`); setTimeout(() => { this.playWithRetry(url); }, 1000 * this.retryCount); } else { console.error('Max retries reached'); // 通知用户播放失败 } } } private async play(url: string) { if (!this.avPlayer) { this.avPlayer = await media.createAVPlayer(); } this.avPlayer.url = url; await this.avPlayer.prepare(); await this.avPlayer.play(); } }

8.3 音频焦点管理


import { audio } from '@kit.AudioKit'; class AudioFocusManager { private avPlayer: media.AVPlayer | undefined = undefined; async setupAudioFocus() { if (!this.avPlayer) { return; } // 设置音频中断模式 this.avPlayer.audioInterruptMode = audio.InterruptMode.INDEPENDENT_MODE; // 监听音频焦点变化 this.avPlayer.on('audioInterrupt', (info: audio.InterruptEvent) => { console.info(`Audio interrupt: ${info.hintType}`); switch (info.hintType) { case audio.InterruptHint.INTERRUPT_HINT_PAUSE: // 暂停播放 this.avPlayer?.pause(); break; case audio.InterruptHint.INTERRUPT_HINT_RESUME: // 恢复播放 this.avPlayer?.play(); break; case audio.InterruptHint.INTERRUPT_HINT_STOP: // 停止播放 this.avPlayer?.stop(); break; case audio.InterruptHint.INTERRUPT_HINT_DUCK: // 降低音量 this.avPlayer?.setVolume(0.3); break; case audio.InterruptHint.INTERRUPT_HINT_UNDUCK: // 恢复音量 this.avPlayer?.setVolume(1.0); break; } }); } }

九、支持的格式

9.1 音频格式

格式编解码器封装格式
AACAAC-LC, HE-AACMP4, M4A, AAC
MP3MP3MP3
FLACFLACFLAC
VorbisVorbisOGG
OpusOpusOGG

9.2 视频格式

格式视频编解码器音频编解码器封装格式
H.264AVCAAC, MP3MP4, MKV
H.265HEVCAAC, MP3MP4, MKV

十、总结

本文全面介绍了HarmonyOS Media Kit的核心能力:

功能模块主要API适用场景
音频播放AVPlayer播放完整音频文件
短音播放SoundPool低时延音效播放
视频播放AVPlayer播放视频文件
音频录制AudioCapturer, AVRecorder录制音频
视频录制AVRecorder + Camera录制视频
后台播放AVSession + 长时任务后台音乐播放

开发要点:

  1. ✅ 根据场景选择合适的API
  2. ✅ 正确处理播放器状态转换
  3. ✅ 做好错误处理和重试机制
  4. ✅ 及时释放资源避免内存泄漏
  5. ✅ 后台播放需注册AVSession
  6. ✅ 正确处理音频焦点事件

通过本文学习,您应该能够:

  • 熟练使用AVPlayer播放音视频
  • 使用SoundPool实现低时延音效
  • 实现音视频录制功能
  • 开发完整的多媒体播放器应用
  • 实现后台播放和媒体会话管理
Logo

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

更多推荐