# 音频播放开发指导 ## 简介 音频播放的主要工作是将音频数据转码为可听见的音频模拟信号,并通过输出设备进行播放,同时对播放任务进行管理,包括开始播放、暂停播放、停止播放、释放资源、设置音量、跳转播放位置、获取轨道信息等功能控制。 ## 运作机制 该模块提供了音频播放状态变化示意图和音频播放外部模块交互图。 **图1** 音频播放状态变化示意图 ![zh-ch_image_audio_state_machine](figures/zh-ch_image_audio_state_machine.png) **注意**:当前为Idle状态,设置src不会改变状态;且src设置成功后,不能再次设置其它src,需调用reset()接口后,才能重新设置src。 **图2** 音频播放外部模块交互图 ![zh-ch_image_audio_player](figures/zh-ch_image_audio_player.png) **说明**:三方应用通过调用JS接口层提供的js接口实现相应功能时,框架层会通过Native Framework的媒体服务,调用音频部件,将软件解码后的音频数据输出至硬件接口层的音频HDI,实现音频播放功能。 ## 开发指导 详细API含义可参考:[媒体服务API文档AudioPlayer](../reference/apis/js-apis-media.md#audioplayer) > **说明:** > > path路径在FA模型和Stage模型下的获取方式不同,示例代码中仅给出pathDir示例,具体的path路径请开发者根据实际情况获取。获取方式请参考[应用沙箱路径使用说明](../reference/apis/js-apis-fileio.md#使用说明)。 ### 全流程场景 音频播放的全流程场景包含:创建实例,设置uri,播放音频,跳转播放位置,设置音量,暂停播放,获取轨道信息,停止播放,重置,释放资源等流程。 AudioPlayer支持的src媒体源输入类型可参考:[src属性说明](../reference/apis/js-apis-media.md#audioplayer_属性) ```js import media from '@ohos.multimedia.media' import fs from '@ohos.file.fs' // 打印码流轨道信息 function printfDescription(obj) { for (let item in obj) { let property = obj[item]; console.info('audio key is ' + item); console.info('audio value is ' + property); } } // 设置播放器回调函数 function setCallBack(audioPlayer) { audioPlayer.on('dataLoad', () => { // 设置'dataLoad'事件回调,src属性设置成功后,触发此回调 console.info('audio set source success'); audioPlayer.play(); // 需等待'dataLoad'事件回调完成后,才可调用play进行播放,触发'play'事件回调 }); audioPlayer.on('play', () => { // 设置'play'事件回调 console.info('audio play success'); audioPlayer.pause(); // 触发'pause'事件回调,暂停播放 }); audioPlayer.on('pause', () => { // 设置'pause'事件回调 console.info('audio pause success'); audioPlayer.seek(5000); // 触发'timeUpdate'事件回调,seek到5000ms处播放 }); audioPlayer.on('stop', () => { // 设置'stop'事件回调 console.info('audio stop success'); audioPlayer.reset(); // 触发'reset'事件回调后,重新设置src属性,可完成切歌 }); audioPlayer.on('reset', () => { // 设置'reset'事件回调 console.info('audio reset success'); audioPlayer.release(); // audioPlayer资源被销毁 audioPlayer = undefined; }); audioPlayer.on('timeUpdate', (seekDoneTime) => { // 设置'timeUpdate'事件回调 if (typeof(seekDoneTime) == 'undefined') { console.info('audio seek fail'); return; } console.info('audio seek success, and seek time is ' + seekDoneTime); audioPlayer.setVolume(0.5); // 触发'volumeChange'事件回调 }); audioPlayer.on('volumeChange', () => { // 设置'volumeChange'事件回调 console.info('audio volumeChange success'); audioPlayer.getTrackDescription((error, arrlist) => { // 通过回调方式获取音频轨道信息 if (typeof (arrlist) != 'undefined') { for (let i = 0; i < arrlist.length; i++) { printfDescription(arrlist[i]); } } else { console.log(`audio getTrackDescription fail, error:${error.message}`); } audioPlayer.stop(); // 触发'stop'事件回调,停止播放 }); }); audioPlayer.on('finish', () => { // 设置'finish'事件回调,播放完成触发 console.info('audio play finish'); }); audioPlayer.on('error', (error) => { // 设置'error'事件回调 console.info(`audio error called, errName is ${error.name}`); console.info(`audio error called, errCode is ${error.code}`); console.info(`audio error called, errMessage is ${error.message}`); }); } async function audioPlayerDemo() { // 1. 创建实例 let audioPlayer = media.createAudioPlayer(); setCallBack(audioPlayer); // 设置事件回调 // 2. 用户选择音频,设置uri let fdPath = 'fd://' let pathDir = "/data/storage/el2/base/haps/entry/files" // pathDir在FA模型和Stage模型的获取方式不同,请参考开发步骤首行的说明,根据实际情况自行获取。 // path路径的码流可通过"hdc file send D:\xxx\01.mp3 /data/app/el2/100/base/ohos.acts.multimedia.audio.audioplayer/haps/entry/files" 命令,将其推送到设备上 let path = pathDir + '/01.mp3' let file = await fs.open(path); fdPath = fdPath + '' + file.fd; audioPlayer.src = fdPath; // 设置src属性,并触发'dataLoad'事件回调 } ``` ### 正常播放场景 ```js import media from '@ohos.multimedia.media' import fs from '@ohos.file.fs' export class AudioDemo { // 设置播放器回调函数 setCallBack(audioPlayer) { audioPlayer.on('dataLoad', () => { // 设置'dataLoad'事件回调,src属性设置成功后,触发此回调 console.info('audio set source success'); audioPlayer.play(); // 调用play方法开始播放,触发'play'事件回调 }); audioPlayer.on('play', () => { // 设置'play'事件回调 console.info('audio play success'); }); audioPlayer.on('finish', () => { // 设置'finish'事件回调,播放完成触发 console.info('audio play finish'); audioPlayer.release(); // audioPlayer资源被销毁 audioPlayer = undefined; }); } async audioPlayerDemo() { let audioPlayer = media.createAudioPlayer(); // 创建一个音频播放实例 this.setCallBack(audioPlayer); // 设置事件回调 let fdPath = 'fd://' let pathDir = "/data/storage/el2/base/haps/entry/files" // pathDir在FA模型和Stage模型的获取方式不同,请参考开发步骤首行的说明,根据实际情况自行获取。 // path路径的码流可通过"hdc file send D:\xxx\01.mp3 /data/app/el2/100/base/ohos.acts.multimedia.audio.audioplayer/haps/entry/files" 命令,将其推送到设备上 let path = pathDir + '/01.mp3' let file = await fs.open(path); fdPath = fdPath + '' + file.fd; audioPlayer.src = fdPath; // 设置src属性,并触发'dataLoad'事件回调 } } ``` ### 切歌场景 ```js import media from '@ohos.multimedia.media' import fs from '@ohos.file.fs' export class AudioDemo { // 设置播放器回调函数 private isNextMusic = false; setCallBack(audioPlayer) { audioPlayer.on('dataLoad', () => { // 设置'dataLoad'事件回调,src属性设置成功后,触发此回调 console.info('audio set source success'); audioPlayer.play(); // 调用play方法开始播放,触发'play'事件回调 }); audioPlayer.on('play', () => { // 设置'play'事件回调 console.info('audio play success'); audioPlayer.reset(); // 调用reset方法,触发'reset'事件回调 }); audioPlayer.on('reset', () => { // 设置'reset'事件回调 console.info('audio play success'); if (!this.isNextMusic) { // 当isNextMusic 为false时,实现切歌功能 this.nextMusic(audioPlayer); // 实现切歌功能 } else { audioPlayer.release(); // audioPlayer资源被销毁 audioPlayer = undefined; } }); } async nextMusic(audioPlayer) { this.isNextMusic = true; let nextFdPath = 'fd://' let pathDir = "/data/storage/el2/base/haps/entry/files" // pathDir在FA模型和Stage模型的获取方式不同,请参考开发步骤首行的说明,根据实际情况自行获取。 // path路径的码流可通过"hdc file send D:\xxx\02.mp3 /data/app/el2/100/base/ohos.acts.multimedia.audio.audioplayer/haps/entry/files" 命令,将其推送到设备上 let nextpath = pathDir + '/02.mp3' let nextFile = await fs.open(nextpath); nextFdPath = nextFdPath + '' + nextFile.fd; audioPlayer.src = nextFdPath; // 设置src属性,并重新触发触发'dataLoad'事件回调 } async audioPlayerDemo() { let audioPlayer = media.createAudioPlayer(); // 创建一个音频播放实例 this.setCallBack(audioPlayer); // 设置事件回调 let fdPath = 'fd://' let pathDir = "/data/storage/el2/base/haps/entry/files" // pathDir在FA模型和Stage模型的获取方式不同,请参考开发步骤首行的说明,根据实际情况自行获取。 // path路径的码流可通过"hdc file send D:\xxx\01.mp3 /data/app/el2/100/base/ohos.acts.multimedia.audio.audioplayer/haps/entry/files" 命令,将其推送到设备上 let path = pathDir + '/01.mp3' let file = await fs.open(path); fdPath = fdPath + '' + file.fd; audioPlayer.src = fdPath; // 设置src属性,并触发'dataLoad'事件回调 } } ``` ### 单曲循环场景 ```js import media from '@ohos.multimedia.media' import fs from '@ohos.file.fs' export class AudioDemo { // 设置播放器回调函数 setCallBack(audioPlayer) { audioPlayer.on('dataLoad', () => { // 设置'dataLoad'事件回调,src属性设置成功后,触发此回调 console.info('audio set source success'); audioPlayer.loop = true; // 设置循环播放属性 audioPlayer.play(); // 调用play方法开始播放,触发'play'事件回调 }); audioPlayer.on('play', () => { // 设置'play'事件回调,开始循环播放 console.info('audio play success'); }); } async audioPlayerDemo() { let audioPlayer = media.createAudioPlayer(); // 创建一个音频播放实例 this.setCallBack(audioPlayer); // 设置事件回调 let fdPath = 'fd://' let pathDir = "/data/storage/el2/base/haps/entry/files" // pathDir在FA模型和Stage模型的获取方式不同,请参考开发步骤首行的说明,根据实际情况自行获取。 // path路径的码流可通过"hdc file send D:\xxx\01.mp3 /data/app/el2/100/base/ohos.acts.multimedia.audio.audioplayer/haps/entry/files" 命令,将其推送到设备上 let path = pathDir + '/01.mp3' let file = await fs.open(path); fdPath = fdPath + '' + file.fd; audioPlayer.src = fdPath; // 设置src属性,并触发'dataLoad'事件回调 } } ``` ## 相关实例 针对音频播放开发,有以下相关实例可供参考: - [`JsDistributedMusicPlayer:`分布式音乐播放(JS)(API10)(Full SDK)](https://gitee.com/openharmony/applications_app_samples/tree/master/code/SuperFeature/DistributedAppDev/JsDistributedMusicPlayer) - [`MediaCollections`:媒体管理合集(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/FileManagement/MediaCollections) - [`Recorder`: 录音机(ArkTS)(API9)(Full SDK)](https://gitee.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/Media/Recorder) - [音频播放器(ArkTS)(API9)](https://gitee.com/openharmony/codelabs/tree/master/Media/Audio_OH_ETS)