1# 音频播放开发指导 2 3## 简介 4 5音频播放的主要工作是将音频数据转码为可听见的音频模拟信号,并通过输出设备进行播放,同时对播放任务进行管理,包括开始播放、暂停播放、停止播放、释放资源、设置音量、跳转播放位置、获取轨道信息等功能控制。 6 7## 运作机制 8 9该模块提供了音频播放状态变化示意图和音频播放外部模块交互图。 10 11**图1** 音频播放状态变化示意图 12 13 14 15**注意**:当前为Idle状态,设置src不会改变状态;且src设置成功后,不能再次设置其它src,需调用reset()接口后,才能重新设置src。 16 17 18 19**图2** 音频播放外部模块交互图 20 21 22 23**说明**:三方应用通过调用JS接口层提供的js接口实现相应功能时,框架层会通过Native Framework的媒体服务,调用音频部件,将软件解码后的音频数据输出至硬件接口层的音频HDI,实现音频播放功能。 24 25## 开发指导 26 27详细API含义可参考:[媒体服务API文档AudioPlayer](../reference/apis/js-apis-media.md#audioplayer) 28 29> **说明:** 30> 31> path路径在FA模型和Stage模型下的获取方式不同,示例代码中仅给出pathDir示例,具体的path路径请开发者根据实际情况获取。获取方式请参考[应用沙箱路径使用说明](../reference/apis/js-apis-fileio.md#使用说明)。 32 33### 全流程场景 34 35音频播放的全流程场景包含:创建实例,设置uri,播放音频,跳转播放位置,设置音量,暂停播放,获取轨道信息,停止播放,重置,释放资源等流程。 36 37AudioPlayer支持的src媒体源输入类型可参考:[src属性说明](../reference/apis/js-apis-media.md#audioplayer_属性) 38 39```js 40import media from '@ohos.multimedia.media' 41import fs from '@ohos.file.fs' 42 43// 打印码流轨道信息 44function printfDescription(obj) { 45 for (let item in obj) { 46 let property = obj[item]; 47 console.info('audio key is ' + item); 48 console.info('audio value is ' + property); 49 } 50} 51 52// 设置播放器回调函数 53function setCallBack(audioPlayer) { 54 audioPlayer.on('dataLoad', () => { // 设置'dataLoad'事件回调,src属性设置成功后,触发此回调 55 console.info('audio set source success'); 56 audioPlayer.play(); // 需等待'dataLoad'事件回调完成后,才可调用play进行播放,触发'play'事件回调 57 }); 58 audioPlayer.on('play', () => { // 设置'play'事件回调 59 console.info('audio play success'); 60 audioPlayer.pause(); // 触发'pause'事件回调,暂停播放 61 }); 62 audioPlayer.on('pause', () => { // 设置'pause'事件回调 63 console.info('audio pause success'); 64 audioPlayer.seek(5000); // 触发'timeUpdate'事件回调,seek到5000ms处播放 65 }); 66 audioPlayer.on('stop', () => { // 设置'stop'事件回调 67 console.info('audio stop success'); 68 audioPlayer.reset(); // 触发'reset'事件回调后,重新设置src属性,可完成切歌 69 }); 70 audioPlayer.on('reset', () => { // 设置'reset'事件回调 71 console.info('audio reset success'); 72 audioPlayer.release(); // audioPlayer资源被销毁 73 audioPlayer = undefined; 74 }); 75 audioPlayer.on('timeUpdate', (seekDoneTime) => { // 设置'timeUpdate'事件回调 76 if (typeof(seekDoneTime) == 'undefined') { 77 console.info('audio seek fail'); 78 return; 79 } 80 console.info('audio seek success, and seek time is ' + seekDoneTime); 81 audioPlayer.setVolume(0.5); // 触发'volumeChange'事件回调 82 }); 83 audioPlayer.on('volumeChange', () => { // 设置'volumeChange'事件回调 84 console.info('audio volumeChange success'); 85 audioPlayer.getTrackDescription((error, arrlist) => { // 通过回调方式获取音频轨道信息 86 if (typeof (arrlist) != 'undefined') { 87 for (let i = 0; i < arrlist.length; i++) { 88 printfDescription(arrlist[i]); 89 } 90 } else { 91 console.log(`audio getTrackDescription fail, error:${error.message}`); 92 } 93 audioPlayer.stop(); // 触发'stop'事件回调,停止播放 94 }); 95 }); 96 audioPlayer.on('finish', () => { // 设置'finish'事件回调,播放完成触发 97 console.info('audio play finish'); 98 }); 99 audioPlayer.on('error', (error) => { // 设置'error'事件回调 100 console.info(`audio error called, errName is ${error.name}`); 101 console.info(`audio error called, errCode is ${error.code}`); 102 console.info(`audio error called, errMessage is ${error.message}`); 103 }); 104} 105 106async function audioPlayerDemo() { 107 // 1. 创建实例 108 let audioPlayer = media.createAudioPlayer(); 109 setCallBack(audioPlayer); // 设置事件回调 110 // 2. 用户选择音频,设置uri 111 let fdPath = 'fd://' 112 let pathDir = "/data/storage/el2/base/haps/entry/files" // pathDir在FA模型和Stage模型的获取方式不同,请参考开发步骤首行的说明,根据实际情况自行获取。 113 // path路径的码流可通过"hdc file send D:\xxx\01.mp3 /data/app/el2/100/base/ohos.acts.multimedia.audio.audioplayer/haps/entry/files" 命令,将其推送到设备上 114 let path = pathDir + '/01.mp3' 115 let file = await fs.open(path); 116 fdPath = fdPath + '' + file.fd; 117 audioPlayer.src = fdPath; // 设置src属性,并触发'dataLoad'事件回调 118} 119``` 120 121### 正常播放场景 122 123```js 124import media from '@ohos.multimedia.media' 125import fs from '@ohos.file.fs' 126 127export class AudioDemo { 128 // 设置播放器回调函数 129 setCallBack(audioPlayer) { 130 audioPlayer.on('dataLoad', () => { // 设置'dataLoad'事件回调,src属性设置成功后,触发此回调 131 console.info('audio set source success'); 132 audioPlayer.play(); // 调用play方法开始播放,触发'play'事件回调 133 }); 134 audioPlayer.on('play', () => { // 设置'play'事件回调 135 console.info('audio play success'); 136 }); 137 audioPlayer.on('finish', () => { // 设置'finish'事件回调,播放完成触发 138 console.info('audio play finish'); 139 audioPlayer.release(); // audioPlayer资源被销毁 140 audioPlayer = undefined; 141 }); 142 } 143 144 async audioPlayerDemo() { 145 let audioPlayer = media.createAudioPlayer(); // 创建一个音频播放实例 146 this.setCallBack(audioPlayer); // 设置事件回调 147 let fdPath = 'fd://' 148 let pathDir = "/data/storage/el2/base/haps/entry/files" // pathDir在FA模型和Stage模型的获取方式不同,请参考开发步骤首行的说明,根据实际情况自行获取。 149 // path路径的码流可通过"hdc file send D:\xxx\01.mp3 /data/app/el2/100/base/ohos.acts.multimedia.audio.audioplayer/haps/entry/files" 命令,将其推送到设备上 150 let path = pathDir + '/01.mp3' 151 let file = await fs.open(path); 152 fdPath = fdPath + '' + file.fd; 153 audioPlayer.src = fdPath; // 设置src属性,并触发'dataLoad'事件回调 154 } 155} 156``` 157 158### 切歌场景 159 160```js 161import media from '@ohos.multimedia.media' 162import fs from '@ohos.file.fs' 163 164export class AudioDemo { 165// 设置播放器回调函数 166 private isNextMusic = false; 167 setCallBack(audioPlayer) { 168 audioPlayer.on('dataLoad', () => { // 设置'dataLoad'事件回调,src属性设置成功后,触发此回调 169 console.info('audio set source success'); 170 audioPlayer.play(); // 调用play方法开始播放,触发'play'事件回调 171 }); 172 audioPlayer.on('play', () => { // 设置'play'事件回调 173 console.info('audio play success'); 174 audioPlayer.reset(); // 调用reset方法,触发'reset'事件回调 175 }); 176 audioPlayer.on('reset', () => { // 设置'reset'事件回调 177 console.info('audio play success'); 178 if (!this.isNextMusic) { // 当isNextMusic 为false时,实现切歌功能 179 this.nextMusic(audioPlayer); // 实现切歌功能 180 } else { 181 audioPlayer.release(); // audioPlayer资源被销毁 182 audioPlayer = undefined; 183 } 184 }); 185 } 186 187 async nextMusic(audioPlayer) { 188 this.isNextMusic = true; 189 let nextFdPath = 'fd://' 190 let pathDir = "/data/storage/el2/base/haps/entry/files" // pathDir在FA模型和Stage模型的获取方式不同,请参考开发步骤首行的说明,根据实际情况自行获取。 191 // path路径的码流可通过"hdc file send D:\xxx\02.mp3 /data/app/el2/100/base/ohos.acts.multimedia.audio.audioplayer/haps/entry/files" 命令,将其推送到设备上 192 let nextpath = pathDir + '/02.mp3' 193 let nextFile = await fs.open(nextpath); 194 nextFdPath = nextFdPath + '' + nextFile.fd; 195 audioPlayer.src = nextFdPath; // 设置src属性,并重新触发触发'dataLoad'事件回调 196 } 197 198 async audioPlayerDemo() { 199 let audioPlayer = media.createAudioPlayer(); // 创建一个音频播放实例 200 this.setCallBack(audioPlayer); // 设置事件回调 201 let fdPath = 'fd://' 202 let pathDir = "/data/storage/el2/base/haps/entry/files" // pathDir在FA模型和Stage模型的获取方式不同,请参考开发步骤首行的说明,根据实际情况自行获取。 203 // path路径的码流可通过"hdc file send D:\xxx\01.mp3 /data/app/el2/100/base/ohos.acts.multimedia.audio.audioplayer/haps/entry/files" 命令,将其推送到设备上 204 let path = pathDir + '/01.mp3' 205 let file = await fs.open(path); 206 fdPath = fdPath + '' + file.fd; 207 audioPlayer.src = fdPath; // 设置src属性,并触发'dataLoad'事件回调 208 } 209} 210``` 211 212### 单曲循环场景 213 214```js 215import media from '@ohos.multimedia.media' 216import fs from '@ohos.file.fs' 217 218export class AudioDemo { 219 // 设置播放器回调函数 220 setCallBack(audioPlayer) { 221 audioPlayer.on('dataLoad', () => { // 设置'dataLoad'事件回调,src属性设置成功后,触发此回调 222 console.info('audio set source success'); 223 audioPlayer.loop = true; // 设置循环播放属性 224 audioPlayer.play(); // 调用play方法开始播放,触发'play'事件回调 225 }); 226 audioPlayer.on('play', () => { // 设置'play'事件回调,开始循环播放 227 console.info('audio play success'); 228 }); 229 } 230 231 async audioPlayerDemo() { 232 let audioPlayer = media.createAudioPlayer(); // 创建一个音频播放实例 233 this.setCallBack(audioPlayer); // 设置事件回调 234 let fdPath = 'fd://' 235 let pathDir = "/data/storage/el2/base/haps/entry/files" // pathDir在FA模型和Stage模型的获取方式不同,请参考开发步骤首行的说明,根据实际情况自行获取。 236 // path路径的码流可通过"hdc file send D:\xxx\01.mp3 /data/app/el2/100/base/ohos.acts.multimedia.audio.audioplayer/haps/entry/files" 命令,将其推送到设备上 237 let path = pathDir + '/01.mp3' 238 let file = await fs.open(path); 239 fdPath = fdPath + '' + file.fd; 240 audioPlayer.src = fdPath; // 设置src属性,并触发'dataLoad'事件回调 241 } 242} 243``` 244 245## 相关实例 246 247针对音频播放开发,有以下相关实例可供参考: 248 249- [`JsDistributedMusicPlayer:`分布式音乐播放(JS)(API8)(Full SDK)](https://gitee.com/openharmony/applications_app_samples/tree/OpenHarmony-3.2-Release/ability/JsDistributedMusicPlayer) 250- [`JsAudioPlayer`:音频播放和管理(JS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/OpenHarmony-3.2-Release/media/JsAudioPlayer) 251- [`eTsAudioPlayer`: 音频播放器(ArkTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/OpenHarmony-3.2-Release/media/Recorder) 252- [音频播放器(ArkTS)(API9)](https://gitee.com/openharmony/codelabs/tree/master/Media/Audio_OH_ETS)