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

W
wusongqing 已提交
3
## 场景介绍
M
mamingshuai 已提交
4

W
wusongqing 已提交
5
音频播放的主要工作是将音频数据转码为可听见的音频模拟信号并通过输出设备进行播放,同时对播放任务进行管理。
M
mamingshuai 已提交
6

W
wusongqing 已提交
7
**图1** 音频播放状态机
8

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

Z
zengyawen 已提交
11

12

W
wusongqing 已提交
13
**图2** 音频播放零层图
14

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

W
wusongqing 已提交
17
## 开发步骤
18

Z
zengyawen 已提交
19
详细API含义可参考:[媒体服务API文档AudioPlayer](../reference/apis/js-apis-media.md)
20

21
### 全流程场景
22

W
wusongqing 已提交
23
包含流程:创建实例,设置uri,播放音频,跳转播放位置,设置音量,暂停播放,获取轨道信息,停止播放,重置,释放资源等流程。
24

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

```js
28 29 30
import media from '@ohos.multimedia.media'
import fileIO from '@ohos.fileio'

31
// 打印码流轨道信息
32 33 34 35 36 37 38 39
function printfDescription(obj) {
    for (let item in obj) {
        let property = obj[item];
        console.info('audio key is ' + item);
        console.info('audio value is ' + property);
    }
}

40
// 设置播放器回调函数
41
function setCallBack(audioPlayer) {
42
    audioPlayer.on('dataLoad', () => { // 设置'dataLoad'事件回调,src属性设置成功后,触发此回调
43
        console.info('audio set source success');
44
        audioPlayer.play(); // 需等待'dataLoad'事件回调完成后,才可调用play进行播放,触发'play'事件回调
45
    });
46
    audioPlayer.on('play', () => { // 设置'play'事件回调
47
        console.info('audio play success');
48
        audioPlayer.pause(); // 触发'pause'事件回调,暂停播放
49
    });
50
    audioPlayer.on('pause', () => { // 设置'pause'事件回调
51
        console.info('audio pause success');
52
        audioPlayer.seek(5000); // 触发'timeUpdate'事件回调,seek到5000ms处播放
53
    });
54
    audioPlayer.on('stop', () => { // 设置'stop'事件回调
55
        console.info('audio stop success');
56
        audioPlayer.reset(); // 触发'reset'事件回调后,重新设置src属性,可完成切歌
57
    });
58
    audioPlayer.on('reset', () => { // 设置'reset'事件回调
59
        console.info('audio reset success');
60
        audioPlayer.release(); // audioPlayer资源被销毁
61
        audioPlayer = undefined;
62
    });
63
    audioPlayer.on('timeUpdate', (seekDoneTime) => { // 设置'timeUpdate'事件回调
64 65
        if (typeof(seekDoneTime) == 'undefined') {
            console.info('audio seek fail');
M
mamingshuai 已提交
66 67
            return;
        }
68
        console.info('audio seek success, and seek time is ' + seekDoneTime);
69
        audioPlayer.setVolume(0.5); // 触发'volumeChange'事件回调
70
    });
71
    audioPlayer.on('volumeChange', () => { // 设置'volumeChange'事件回调
72
        console.info('audio volumeChange success');
73
        audioPlayer.getTrackDescription((error, arrlist) => { // 通过回调方式获取音频轨道信息
74 75 76 77 78 79 80
            if (typeof (arrlist) != 'undefined') {
                for (let i = 0; i < arrlist.length; i++) {
                    printfDescription(arrlist[i]);
                }
            } else {
                console.log(`audio getTrackDescription fail, error:${error.message}`);
            }
81
            audioPlayer.stop(); // 触发'stop'事件回调,停止播放
82
        });
83
    });
84
    audioPlayer.on('finish', () => { // 设置'finish'事件回调,播放完成触发
85 86
        console.info('audio play finish');
    });
87
    audioPlayer.on('error', (error) => { // 设置'error'事件回调
88 89 90 91 92 93
        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}`);
    });
}

94 95 96
async function audioPlayerDemo() {
    // 1. 创建实例
    let audioPlayer = media.createAudioPlayer();
97 98
    setCallBack(audioPlayer); // 设置事件回调
    // 2. 用户选择音频,设置uri
99 100 101 102 103
    let fdPath = 'fd://'
    // path路径的码流可通过"hdc file send D:\xxx\01.mp3 /data/app/el1/bundle/public/ohos.acts.multimedia.audio.audioplayer/ohos.acts.multimedia.audio.audioplayer/assets/entry/resources/rawfile" 命令,将其推送到设备上
    let path = '/data/app/el1/bundle/public/ohos.acts.multimedia.audio.audioplayer/ohos.acts.multimedia.audio.audioplayer/assets/entry/resources/rawfile/01.mp3';
    await fileIO.open(path).then((fdNumber) => {
        fdPath = fdPath + '' + fdNumber;
JoyboyCZ's avatar
JoyboyCZ 已提交
104
        console.info('open fd success fd is' + fdPath);
105 106 107 108 109
    }, (err) => {
        console.info('open fd failed err is' + err);
    }).catch((err) => {
        console.info('open fd failed err is' + err);
    });
110
    audioPlayer.src = fdPath; // 设置src属性,并触发'dataLoad'事件回调
111 112 113
}
```

W
wusongqing 已提交
114
### 正常播放场景
115 116

```js
117 118
import media from '@ohos.multimedia.media'
import fileIO from '@ohos.fileio'
119 120 121
export class AudioDemo {
  // 设置播放器回调函数
  setCallBack(audioPlayer) {
122
    audioPlayer.on('dataLoad', () => { // 设置'dataLoad'事件回调,src属性设置成功后,触发此回调
123
      console.info('audio set source success');
124
      audioPlayer.play(); // 调用play方法开始播放,触发'play'事件回调
125
    });
126
    audioPlayer.on('play', () => { // 设置'play'事件回调
127
      console.info('audio play success');
128
    });
129
    audioPlayer.on('finish', () => { // 设置'finish'事件回调,播放完成触发
130
      console.info('audio play finish');
131
      audioPlayer.release(); // audioPlayer资源被销毁
132
      audioPlayer = undefined;
133
    });
134 135 136
  }

  async audioPlayerDemo() {
137 138
    let audioPlayer = media.createAudioPlayer(); // 创建一个音频播放实例
    this.setCallBack(audioPlayer); // 设置事件回调
139 140 141 142 143
    let fdPath = 'fd://'
    // path路径的码流可通过"hdc file send D:\xxx\01.mp3 /data/app/el1/bundle/public/ohos.acts.multimedia.audio.audioplayer/ohos.acts.multimedia.audio.audioplayer/assets/entry/resources/rawfile" 命令,将其推送到设备上
    let path = '/data/app/el1/bundle/public/ohos.acts.multimedia.audio.audioplayer/ohos.acts.multimedia.audio.audioplayer/assets/entry/resources/rawfile/01.mp3';
    await fileIO.open(path).then((fdNumber) => {
      fdPath = fdPath + '' + fdNumber;
JoyboyCZ's avatar
JoyboyCZ 已提交
144
      console.info('open fd success fd is' + fdPath);
145 146 147 148 149
    }, (err) => {
      console.info('open fd failed err is' + err);
    }).catch((err) => {
      console.info('open fd failed err is' + err);
    });
150
    audioPlayer.src = fdPath; // 设置src属性,并触发'dataLoad'事件回调
151
  }
152
}
153 154
```

W
wusongqing 已提交
155
### 切歌场景
156 157

```js
158 159
import media from '@ohos.multimedia.media'
import fileIO from '@ohos.fileio'
160 161 162 163
export class AudioDemo {
// 设置播放器回调函数
  private isNextMusic = false;
  setCallBack(audioPlayer) {
164
    audioPlayer.on('dataLoad', () => { // 设置'dataLoad'事件回调,src属性设置成功后,触发此回调
165
      console.info('audio set source success');
166
      audioPlayer.play(); // 调用play方法开始播放,触发'play'事件回调
167
    });
168
    audioPlayer.on('play', () => { // 设置'play'事件回调
169
      console.info('audio play success');
170
      audioPlayer.reset(); // 调用reset方法,触发'reset'事件回调
171
    });
172
    audioPlayer.on('reset', () => { // 设置'reset'事件回调
173
      console.info('audio play success');
174 175
      if (!this.isNextMusic) { // 当isNextMusic 为false时,实现切歌功能
        this.nextMusic(audioPlayer); // 实现切歌功能
176
      } else {
177
        audioPlayer.release(); // audioPlayer资源被销毁
178 179 180 181 182 183 184 185 186 187 188 189
        audioPlayer = undefined;
      }
    });
  }

  async nextMusic(audioPlayer) {
    this.isNextMusic = true;
    let nextFdPath = 'fd://'
    // path路径的码流可通过"hdc file send D:\xxx\02.mp3 /data/app/el1/bundle/public/ohos.acts.multimedia.audio.audioplayer/ohos.acts.multimedia.audio.audioplayer/assets/entry/resources/rawfile" 命令,将其推送到设备上
    let nextpath = '/data/app/el1/bundle/public/ohos.acts.multimedia.audio.audioplayer/ohos.acts.multimedia.audio.audioplayer/assets/entry/resources/rawfile/02.mp3';
    await fileIO.open(nextpath).then((fdNumber) => {
      nextFdPath = nextFdPath + '' + fdNumber;
JoyboyCZ's avatar
JoyboyCZ 已提交
190
      console.info('open fd success fd is' + nextFdPath);
191 192 193 194 195
    }, (err) => {
      console.info('open fd failed err is' + err);
    }).catch((err) => {
      console.info('open fd failed err is' + err);
    });
196
    audioPlayer.src = nextFdPath; // 设置src属性,并重新触发触发'dataLoad'事件回调
197 198 199
  }

  async audioPlayerDemo() {
200 201
    let audioPlayer = media.createAudioPlayer();       // 创建一个音频播放实例
    this.setCallBack(audioPlayer);                     // 设置事件回调
202 203 204 205 206
    let fdPath = 'fd://'
    // path路径的码流可通过"hdc file send D:\xxx\01.mp3 /data/app/el1/bundle/public/ohos.acts.multimedia.audio.audioplayer/ohos.acts.multimedia.audio.audioplayer/assets/entry/resources/rawfile" 命令,将其推送到设备上
    let path = '/data/app/el1/bundle/public/ohos.acts.multimedia.audio.audioplayer/ohos.acts.multimedia.audio.audioplayer/assets/entry/resources/rawfile/01.mp3';
    await fileIO.open(path).then((fdNumber) => {
      fdPath = fdPath + '' + fdNumber;
JoyboyCZ's avatar
JoyboyCZ 已提交
207
      console.info('open fd success fd is' + fdPath);
208 209 210 211
    }, (err) => {
      console.info('open fd failed err is' + err);
    }).catch((err) => {
      console.info('open fd failed err is' + err);
212
    });
213
    audioPlayer.src = fdPath; // 设置src属性,并触发'dataLoad'事件回调
214
  }
215 216 217
}
```

W
wusongqing 已提交
218
### 单曲循环场景
219 220

```js
221 222
import media from '@ohos.multimedia.media'
import fileIO from '@ohos.fileio'
223 224 225
export class AudioDemo {
  // 设置播放器回调函数
  setCallBack(audioPlayer) {
226
    audioPlayer.on('dataLoad', () => { // 设置'dataLoad'事件回调,src属性设置成功后,触发此回调
227
      console.info('audio set source success');
228 229
      audioPlayer.loop = true; // 设置循环播放属性
      audioPlayer.play(); // 调用play方法开始播放,触发'play'事件回调
230
    });
231
    audioPlayer.on('play', () => { // 设置'play'事件回调,开始循环播放
232
      console.info('audio play success');
233
    });
234 235 236
  }

  async audioPlayerDemo() {
237 238
    let audioPlayer = media.createAudioPlayer(); // 创建一个音频播放实例
    this.setCallBack(audioPlayer); // 设置事件回调
239 240 241 242 243
    let fdPath = 'fd://'
    // path路径的码流可通过"hdc file send D:\xxx\01.mp3 /data/app/el1/bundle/public/ohos.acts.multimedia.audio.audioplayer/ohos.acts.multimedia.audio.audioplayer/assets/entry/resources/rawfile" 命令,将其推送到设备上
    let path = '/data/app/el1/bundle/public/ohos.acts.multimedia.audio.audioplayer/ohos.acts.multimedia.audio.audioplayer/assets/entry/resources/rawfile/01.mp3';
    await fileIO.open(path).then((fdNumber) => {
      fdPath = fdPath + '' + fdNumber;
JoyboyCZ's avatar
JoyboyCZ 已提交
244
      console.info('open fd success fd is' + fdPath);
245 246 247 248
    }, (err) => {
      console.info('open fd failed err is' + err);
    }).catch((err) => {
      console.info('open fd failed err is' + err);
249
    });
250
    audioPlayer.src = fdPath; // 设置src属性,并触发'dataLoad'事件回调
251
  }
252
}
Z
zengyawen 已提交
253 254 255 256 257 258
```

## 相关实例

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

259 260 261
- [`JsDistributedMusicPlayer:`分布式音乐播放(JS)(API8)(Full SDK)](https://gitee.com/openharmony/applications_app_samples/tree/master/ability/JsDistributedMusicPlayer)
- [`JsAudioPlayer`:音频播放和管理(JS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/media/JsAudioPlayer)
- [`eTsAudioPlayer`: 音频播放器(eTS)(API8)](https://gitee.com/openharmony/applications_app_samples/blob/master/media/Recorder/entry/src/main/ets/MainAbility/pages/Play.ets)
262
- [音频播放器(eTS)(API9)](https://gitee.com/openharmony/codelabs/tree/master/Media/Audio_OH_ETS)