使用AVPlayer開發(fā)音頻播放功能

2024-02-16 13:52 更新

使用AVPlayer可以實現(xiàn)端到端播放原始媒體資源,本開發(fā)指導(dǎo)將以完整地播放一首音樂作為示例,向開發(fā)者講解AVPlayer音頻播放相關(guān)功能。

播放的全流程包含:創(chuàng)建AVPlayer,設(shè)置播放資源,設(shè)置播放參數(shù)(音量/倍速/焦點模式),播放控制(播放/暫停/跳轉(zhuǎn)/停止),重置,銷毀資源。

在進行應(yīng)用開發(fā)的過程中,開發(fā)者可以通過AVPlayer的state屬性主動獲取當前狀態(tài)或使用on('stateChange')方法監(jiān)聽狀態(tài)變化。如果應(yīng)用在音頻播放器處于錯誤狀態(tài)時執(zhí)行操作,系統(tǒng)可能會拋出異?;蛏善渌炊x的行為。

圖1 播放狀態(tài)變化示意圖

狀態(tài)的詳細說明請參考AVPlayerState。當播放處于prepared / playing / paused / completed狀態(tài)時,播放引擎處于工作狀態(tài),這需要占用系統(tǒng)較多的運行內(nèi)存。當客戶端暫時不使用播放器時,調(diào)用reset()或release()回收內(nèi)存資源,做好資源利用。

開發(fā)步驟及注意事項

詳細的API說明請參考AVPlayer API參考

  1. 創(chuàng)建實例createAVPlayer(),AVPlayer初始化idle狀態(tài)。
  2. 設(shè)置業(yè)務(wù)需要的監(jiān)聽事件,搭配全流程場景使用。支持的監(jiān)聽事件包括:

    事件類型

    說明

    stateChange

    必要事件,監(jiān)聽播放器的state屬性改變。

    error

    必要事件,監(jiān)聽播放器的錯誤信息。

    durationUpdate

    用于進度條,監(jiān)聽進度條長度,刷新資源時長。

    timeUpdate

    用于進度條,監(jiān)聽進度條當前位置,刷新當前時間。

    seekDone

    響應(yīng)API調(diào)用,監(jiān)聽seek()請求完成情況。

    當使用seek()跳轉(zhuǎn)到指定播放位置后,如果seek操作成功,將上報該事件。

    speedDone

    響應(yīng)API調(diào)用,監(jiān)聽setSpeed()請求完成情況。

    當使用setSpeed()設(shè)置播放倍速后,如果setSpeed操作成功,將上報該事件。

    volumeChange

    響應(yīng)API調(diào)用,監(jiān)聽setVolume()請求完成情況。

    當使用setVolume()調(diào)節(jié)播放音量后,如果setVolume操作成功,將上報該事件。

    bufferingUpdate

    用于網(wǎng)絡(luò)播放,監(jiān)聽網(wǎng)絡(luò)播放緩沖信息,用于上報緩沖百分比以及緩存播放進度。

    audioInterrupt

    監(jiān)聽音頻焦點切換信息,搭配屬性audioInterruptMode使用。

    如果當前設(shè)備存在多個音頻正在播放,音頻焦點被切換(即播放其他媒體如通話等)時將上報該事件,應(yīng)用可以及時處理。

  3. 設(shè)置資源:設(shè)置屬性url,AVPlayer進入initialized狀態(tài)。
    說明

    下面代碼示例中的url僅作示意使用,開發(fā)者需根據(jù)實際情況,確認資源有效性并設(shè)置:

  4. 準備播放:調(diào)用prepare(),AVPlayer進入prepared狀態(tài),此時可以獲取duration,設(shè)置音量。
  5. 音頻播控:播放play(),暫停pause(),跳轉(zhuǎn)seek(),停止stop() 等操作。
  6. (可選)更換資源:調(diào)用reset()重置資源,AVPlayer重新進入idle狀態(tài),允許更換資源url。
  7. 退出播放:調(diào)用release()銷毀實例,AVPlayer進入released狀態(tài),退出播放。

完整示例

參考以下示例,完整地播放一首音樂。
  1. import media from '@ohos.multimedia.media';
  2. import fs from '@ohos.file.fs';
  3. import common from '@ohos.app.ability.common';
  4. export class AVPlayerDemo {
  5. private avPlayer;
  6. private count: number = 0;
  7. // 注冊avplayer回調(diào)函數(shù)
  8. setAVPlayerCallback() {
  9. // seek操作結(jié)果回調(diào)函數(shù)
  10. this.avPlayer.on('seekDone', (seekDoneTime) => {
  11. console.info(`AVPlayer seek succeeded, seek time is ${seekDoneTime}`);
  12. })
  13. // error回調(diào)監(jiān)聽函數(shù),當avPlayer在操作過程中出現(xiàn)錯誤時調(diào)用reset接口觸發(fā)重置流程
  14. this.avPlayer.on('error', (err) => {
  15. console.error(`Invoke avPlayer failed, code is ${err.code}, message is ${err.message}`);
  16. this.avPlayer.reset(); // 調(diào)用reset重置資源,觸發(fā)idle狀態(tài)
  17. })
  18. // 狀態(tài)機變化回調(diào)函數(shù)
  19. this.avPlayer.on('stateChange', async (state, reason) => {
  20. switch (state) {
  21. case 'idle': // 成功調(diào)用reset接口后觸發(fā)該狀態(tài)機上報
  22. console.info('AVPlayer state idle called.');
  23. this.avPlayer.release(); // 調(diào)用release接口銷毀實例對象
  24. break;
  25. case 'initialized': // avplayer 設(shè)置播放源后觸發(fā)該狀態(tài)上報
  26. console.info('AVPlayerstate initialized called.');
  27. this.avPlayer.prepare().then(() => {
  28. console.info('AVPlayer prepare succeeded.');
  29. }, (err) => {
  30. console.error(`Invoke prepare failed, code is ${err.code}, message is ${err.message}`);
  31. });
  32. break;
  33. case 'prepared': // prepare調(diào)用成功后上報該狀態(tài)機
  34. console.info('AVPlayer state prepared called.');
  35. this.avPlayer.play(); // 調(diào)用播放接口開始播放
  36. break;
  37. case 'playing': // play成功調(diào)用后觸發(fā)該狀態(tài)機上報
  38. console.info('AVPlayer state playing called.');
  39. if (this.count !== 0) {
  40. console.info('AVPlayer start to seek.');
  41. this.avPlayer.seek(this.avPlayer.duration); //seek到音頻末尾
  42. } else {
  43. this.avPlayer.pause(); // 調(diào)用暫停接口暫停播放
  44. }
  45. this.count++;
  46. break;
  47. case 'paused': // pause成功調(diào)用后觸發(fā)該狀態(tài)機上報
  48. console.info('AVPlayer state paused called.');
  49. this.avPlayer.play(); // 再次播放接口開始播放
  50. break;
  51. case 'completed': // 播放結(jié)束后觸發(fā)該狀態(tài)機上報
  52. console.info('AVPlayer state completed called.');
  53. this.avPlayer.stop(); //調(diào)用播放結(jié)束接口
  54. break;
  55. case 'stopped': // stop接口成功調(diào)用后觸發(fā)該狀態(tài)機上報
  56. console.info('AVPlayer state stopped called.');
  57. this.avPlayer.reset(); // 調(diào)用reset接口初始化avplayer狀態(tài)
  58. break;
  59. case 'released':
  60. console.info('AVPlayer state released called.');
  61. break;
  62. default:
  63. console.info('AVPlayer state unknown called.');
  64. break;
  65. }
  66. })
  67. }
  68. // 以下demo為使用fs文件系統(tǒng)打開沙箱地址獲取媒體文件地址并通過url屬性進行播放示例
  69. async avPlayerUrlDemo() {
  70. // 創(chuàng)建avPlayer實例對象
  71. this.avPlayer = await media.createAVPlayer();
  72. // 創(chuàng)建狀態(tài)機變化回調(diào)函數(shù)
  73. this.setAVPlayerCallback();
  74. let fdPath = 'fd://';
  75. // 通過UIAbilityContext獲取沙箱地址filesDir,以下為Stage模型獲方式,如需在FA模型上獲取請參考《訪問應(yīng)用沙箱》獲取地址
  76. let context = getContext(this) as common.UIAbilityContext;
  77. let pathDir = context.filesDir;
  78. let path = pathDir + '/01.mp3';
  79. // 打開相應(yīng)的資源文件地址獲取fd,并為url賦值觸發(fā)initialized狀態(tài)機上報
  80. let file = await fs.open(path);
  81. fdPath = fdPath + '' + file.fd;
  82. this.avPlayer.url = fdPath;
  83. }
  84. // 以下demo為使用資源管理接口獲取打包在HAP內(nèi)的媒體資源文件并通過fdSrc屬性進行播放示例
  85. async avPlayerFdSrcDemo() {
  86. // 創(chuàng)建avPlayer實例對象
  87. this.avPlayer = await media.createAVPlayer();
  88. // 創(chuàng)建狀態(tài)機變化回調(diào)函數(shù)
  89. this.setAVPlayerCallback();
  90. // 通過UIAbilityContext的resourceManager成員的getRawFd接口獲取媒體資源播放地址
  91. // 返回類型為{fd,offset,length},fd為HAP包fd地址,offset為媒體資源偏移量,length為播放長度
  92. let context = getContext(this) as common.UIAbilityContext;
  93. let fileDescriptor = await context.resourceManager.getRawFd('01.mp3');
  94. // 為fdSrc賦值觸發(fā)initialized狀態(tài)機上報
  95. this.avPlayer.fdSrc = fileDescriptor;
  96. this.isSeek = false; // 不支持seek操作
  97. }
  98. }
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號