audio-playback.md 11.6 KB
Newer Older
W
wusongqing 已提交
1
# 音频播放开发指导
M
mamingshuai 已提交
2

3
## 简介
M
mamingshuai 已提交
4

5
音频播放的主要工作是将音频数据转码为可听见的音频模拟信号,并通过输出设备进行播放,同时对播放任务进行管理,包括开始播放、暂停播放、停止播放、释放资源、设置音量、跳转播放位置、获取轨道信息等功能控制。
M
mamingshuai 已提交
6

7 8 9 10 11
## 运作机制

该模块提供了音频播放状态变化示意图和音频播放外部模块交互图。

**图1** 音频播放状态变化示意图
12

W
wusongqing 已提交
13
![zh-ch_image_audio_state_machine](figures/zh-ch_image_audio_state_machine.png)
14

15
**注意**:当前为Idle状态,设置src不会改变状态;且src设置成功后,不能再次设置其它src,需调用reset()接口后,才能重新设置src。
16

Z
zengyawen 已提交
17

18

19
**图2** 音频播放外部模块交互图
20

W
wusongqing 已提交
21
![zh-ch_image_audio_player](figures/zh-ch_image_audio_player.png)
22

23 24 25
**说明**:三方应用通过调用JS接口层提供的js接口实现相应功能时,框架层会通过Native Framework的媒体服务,调用音频部件,将软件解码后的音频数据输出至硬件接口层的音频HDI,实现音频播放功能。

## 开发指导
26

27
详细API含义可参考:[媒体服务API文档AudioPlayer](../reference/apis/js-apis-media.md#audioplayer)
28

29 30 31 32
> **说明:**
>
> path路径在FA模型和Stage模型下的获取方式不同,示例代码中仅给出pathDir示例,具体的path路径请开发者根据实际情况获取。获取方式请参考[应用沙箱路径使用说明](../reference/apis/js-apis-fileio.md#使用说明)。

33
### 全流程场景
34

35
音频播放的全流程场景包含:创建实例,设置uri,播放音频,跳转播放位置,设置音量,暂停播放,获取轨道信息,停止播放,重置,释放资源等流程。
36

W
wusongqing 已提交
37
AudioPlayer支持的src媒体源输入类型可参考:[src属性说明](../reference/apis/js-apis-media.md#audioplayer_属性)
38 39

```js
40
import media from '@ohos.multimedia.media'
41
import fs from '@ohos.file.fs'
42

43
// 打印码流轨道信息
44 45 46 47 48 49 50 51
function printfDescription(obj) {
    for (let item in obj) {
        let property = obj[item];
        console.info('audio key is ' + item);
        console.info('audio value is ' + property);
    }
}

52
// 设置播放器回调函数
53
function 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 77
        if (typeof(seekDoneTime) == 'undefined') {
            console.info('audio seek fail');
M
mamingshuai 已提交
78 79
            return;
        }
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 87 88 89 90 91 92
            if (typeof (arrlist) != 'undefined') {
                for (let i = 0; i < arrlist.length; i++) {
                    printfDescription(arrlist[i]);
                }
            } else {
                console.log(`audio getTrackDescription fail, error:${error.message}`);
            }
93
            audioPlayer.stop(); // 触发'stop'事件回调,停止播放
94
        });
95
    });
96
    audioPlayer.on('finish', () => { // 设置'finish'事件回调,播放完成触发
97 98
        console.info('audio play finish');
    });
99
    audioPlayer.on('error', (error) => { // 设置'error'事件回调
100 101 102 103 104 105
        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}`);
    });
}

106 107 108
async function audioPlayerDemo() {
    // 1. 创建实例
    let audioPlayer = media.createAudioPlayer();
109 110
    setCallBack(audioPlayer); // 设置事件回调
    // 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 116
    let file = await fs.open(path);
    fdPath = fdPath + '' + file.fd;
117
    audioPlayer.src = fdPath; // 设置src属性,并触发'dataLoad'事件回调
118 119 120
}
```

W
wusongqing 已提交
121
### 正常播放场景
122 123

```js
124
import media from '@ohos.multimedia.media'
125
import fs from '@ohos.file.fs'
126

127 128 129
export class AudioDemo {
  // 设置播放器回调函数
  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 146
    let audioPlayer = media.createAudioPlayer(); // 创建一个音频播放实例
    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 152
    let file = await fs.open(path);
    fdPath = fdPath + '' + file.fd;
153
    audioPlayer.src = fdPath; // 设置src属性,并触发'dataLoad'事件回调
154
  }
155
}
156 157
```

W
wusongqing 已提交
158
### 切歌场景
159 160

```js
161
import media from '@ohos.multimedia.media'
162
import fs from '@ohos.file.fs'
163

164 165 166 167
export class AudioDemo {
// 设置播放器回调函数
  private isNextMusic = false;
  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 179
      if (!this.isNextMusic) { // 当isNextMusic 为false时,实现切歌功能
        this.nextMusic(audioPlayer); // 实现切歌功能
180
      } else {
181
        audioPlayer.release(); // audioPlayer资源被销毁
182 183 184 185 186 187 188 189
        audioPlayer = undefined;
      }
    });
  }

  async nextMusic(audioPlayer) {
    this.isNextMusic = true;
    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 194
    let nextFile = await fs.open(nextpath);
    nextFdPath = nextFdPath + '' + nextFile.fd;
195
    audioPlayer.src = nextFdPath; // 设置src属性,并重新触发触发'dataLoad'事件回调
196 197 198
  }

  async audioPlayerDemo() {
199 200
    let audioPlayer = media.createAudioPlayer();       // 创建一个音频播放实例
    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 206
    let file = await fs.open(path);
    fdPath = fdPath + '' + file.fd;
207
    audioPlayer.src = fdPath; // 设置src属性,并触发'dataLoad'事件回调
208
  }
209 210 211
}
```

W
wusongqing 已提交
212
### 单曲循环场景
213 214

```js
215
import media from '@ohos.multimedia.media'
216
import fs from '@ohos.file.fs'
217

218 219 220
export class AudioDemo {
  // 设置播放器回调函数
  setCallBack(audioPlayer) {
221
    audioPlayer.on('dataLoad', () => { // 设置'dataLoad'事件回调,src属性设置成功后,触发此回调
222
      console.info('audio set source success');
223 224
      audioPlayer.loop = true; // 设置循环播放属性
      audioPlayer.play(); // 调用play方法开始播放,触发'play'事件回调
225
    });
226
    audioPlayer.on('play', () => { // 设置'play'事件回调,开始循环播放
227
      console.info('audio play success');
228
    });
229 230 231
  }

  async audioPlayerDemo() {
232 233
    let audioPlayer = media.createAudioPlayer(); // 创建一个音频播放实例
    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 239
    let file = await fs.open(path);
    fdPath = fdPath + '' + file.fd;
240
    audioPlayer.src = fdPath; // 设置src属性,并触发'dataLoad'事件回调
241
  }
242
}
Z
zengyawen 已提交
243 244 245 246 247 248
```

## 相关实例

针对音频播放开发,有以下相关实例可供参考:

Z
zwx1094577 已提交
249 250 251
- [`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)
252
- [音频播放器(ArkTS)(API9)](https://gitee.com/openharmony/codelabs/tree/master/Media/Audio_OH_ETS)