• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 音频播放开发指导
2
3## 简介
4
5音频播放的主要工作是将音频数据转码为可听见的音频模拟信号,并通过输出设备进行播放,同时对播放任务进行管理,包括开始播放、暂停播放、停止播放、释放资源、设置音量、跳转播放位置、获取轨道信息等功能控制。
6
7## 运作机制
8
9该模块提供了音频播放状态变化示意图和音频播放外部模块交互图。
10
11**图1** 音频播放状态变化示意图
12
13![zh-ch_image_audio_state_machine](figures/zh-ch_image_audio_state_machine.png)
14
15**注意**:当前为Idle状态,设置src不会改变状态;且src设置成功后,不能再次设置其它src,需调用reset()接口后,才能重新设置src。
16
17
18
19**图2** 音频播放外部模块交互图
20
21![zh-ch_image_audio_player](figures/zh-ch_image_audio_player.png)
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)