鴻蒙-AVPlayer

compileVersion 5.0.2(14)

音頻播放

import media from '@ohos.multimedia.media';
import common from '@ohos.app.ability.common';
import { BusinessError } from '@ohos.base';@Entry
@Component
struct AudioPlayer {private avPlayer: media.AVPlayer | null = null;@State isPlaying: boolean = false;@State playProgress: number = 0;private timerId: number | null = null; // 存儲定時器IDprivate readonly audioPath: string = 'qingtian.mp3';//頁面初始化aboutToAppear() {this.initAudioPlayer();}//頁面銷毀aboutToDisappear(): void {this.releasePlayer();}// 修改為異步函數private async initAudioPlayer() {console.log('initAudioPlayer=====');const context = getContext(this) as common.UIAbilityContext;const resourceManager = context.resourceManager;try {// 添加await處理Promiseconst fdObj = await resourceManager.getRawFd(this.audioPath);const avFileDescriptor: media.AVFileDescriptor = {fd: fdObj.fd,offset: fdObj.offset, // 已正確處理offset屬性length: fdObj.length};media.createAVPlayer((err: BusinessError, player: media.AVPlayer) => {if (err) {console.error('創建播放器失敗: ' + JSON.stringify(err));return;}console.info('創建播放器success');this.avPlayer = player;this.setupPlayerEvents();this.avPlayer.fdSrc = avFileDescriptor;});} catch (error) {console.error('文件加載失敗: ' + JSON.stringify(error));}}private setupPlayerEvents() {if (!this.avPlayer) {return;}// 修改為字符串狀態匹配this.avPlayer.on('stateChange', (state: string) => {console.log('stateChange:' + state);switch (state) {case 'initialized': // 原media.AVPlayerState.PREPAREDthis.avPlayer?.prepare();break;case 'prepared': // 原media.AVPlayerState.PREPAREDconsole.log('準備完成');break;case 'playing': // 原media.AVPlayerState.PLAYINGthis.isPlaying = true;this.startProgressTracking();break;case 'paused': // 原media.AVPlayerState.PAUSEDthis.isPlaying = false;this.stopProgressUpdate();break;case 'completed': // 原media.AVPlayerState.COMPLETEDthis.isPlaying = false;this.playProgress = 100;this.stopProgressUpdate();break;}});this.avPlayer.on('error', (err: BusinessError) => {console.error('播放錯誤: ' + JSON.stringify(err));this.releasePlayer();this.initAudioPlayer();});}// 開始播放進度跟蹤private startProgressTracking() {console.log('startProgressTracking=====');this.timerId = setInterval(() => {if (this.avPlayer && this.avPlayer.duration > 0) {console.log('setInterval currentTime=' + this.avPlayer.currentTime + ' duration=' + this.avPlayer.duration);this.playProgress = (this.avPlayer.currentTime / this.avPlayer.duration) * 100;}}, 1000);console.log('this.timerId=' + this.timerId);}// 停止進度更新private stopProgressUpdate() {console.log('stopProgressUpdate=====');if (this.timerId !== null) {clearInterval(this.timerId);this.timerId = null;}}// 釋放播放器資源private releasePlayer() {console.log('releasePlayer=====');if (this.avPlayer) {this.avPlayer.release();this.avPlayer = null;}}// 播放/暫停控制private togglePlayback() {if (!this.avPlayer) {return;}if (this.isPlaying) {this.avPlayer.pause();} else {if (this.avPlayer.currentTime >= this.avPlayer.duration) {this.avPlayer.seek(0);}this.avPlayer.play();}}build() {Column() {// 播放控制區域Row({ space: 20 }) {Button(this.isPlaying ? '暫停' : '播放').onClick(() => this.togglePlayback()).width(100).height(40)Progress({ value: this.playProgress, total: 100 }).width('60%').height(10).color('#409EFF')}.padding(20).width('100%')// 音頻信息顯示Text('當前播放:' + this.audioPath.split('/').pop()).fontSize(16).margin({ top: 20 })}.width('100%').height('100%').padding(20).backgroundColor('#F5F5F5')}
}

media.AVFileDescriptor

fd:文件描述符

  • ?含義:操作系統分配的唯一標識符,代表已打開的文件句柄(file descriptor)。
  • ?作用:
    • 系統通過該標識符定位具體的媒體文件(如存儲在rawfile目錄下的音頻文件或HAP包內嵌資源)
    • 用于跨進程文件訪問時傳遞文件引用(如播放器服務與UI界面的數據交互)
    • 示例:通過resourceManager.getRawFd('music.mp3')獲取打包資源文件的描述符

?offset:文件偏移量

  • ?含義:從文件起始位置到目標數據的字節偏移量(單位:字節)。
  • ?技術細節:
    • 當媒體文件被壓縮或打包時(如HAP資源文件),需跳過文件頭等非音頻數據部分
    • 支持精確指定播放起始點(如從視頻第10秒開始播放,需計算對應的字節偏移)
    • 示例:若資源文件在HAP包中的物理偏移為1024字節,則offset需設為1024

?length:數據長度

  • ?含義:需要讀取的媒體數據總長度(單位:字節)。
  • ?關鍵作用:
    • 限制播放器讀取范圍,避免處理無關數據(如僅播放某段音頻或視頻片段)
    • 防止越界讀取導致的崩潰(如文件實際大小小于聲明長度時觸發錯誤碼5400102)
    • 示例:從HAP包中讀取一個30秒的MP3片段時,需通過fs.statSync獲取精確文件長度

參數關系與開發規范

參數典型取值范圍異常處理建議
fd≥0(0表示無效句柄)檢查fs.open()返回值是否有效
offset0 ≤ offset ≤ 文件大小-1配合fs.stat驗證偏移有效性
length1 ≤ length ≤ 剩余字節數動態計算:length = 文件大小 - offset

示例

播放HAP內嵌資源
typescriptconst fdObj = await resourceManager.getRawFd('music.mp3');
const avFileDescriptor = {fd: fdObj.fd,offset: fdObj.offset, // 自動處理HAP打包偏移length: fdObj.length   // 精確獲取資源實際長度
};
avPlayer.fdSrc = avFileDescriptor;  // 直接綁定播放源[3](@ref)
分段播放大型文件?
typescript// 播放視頻第60-120秒的內容
const startOffset = 60 * bitrate;   // 根據碼率計算字節偏移
const playLength = 60 * bitrate;
avPlayer.fdSrc = { fd, offset: startOffset, length: playLength };
開發注意事項:
  • offset + length超過實際文件大小,將觸發BusinessError 5400102(參數非法)
  • 使用fs.close(fd)aboutToDisappear生命周期關閉文件描述符,避免資源泄漏
  • on('error')回調中處理文件訪問異常(如權限不足或文件損壞)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/72037.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/72037.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/72037.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

機器學習數學通關指南——泰勒公式

前言 本文隸屬于專欄《機器學習數學通關指南》,該專欄為筆者原創,引用請注明來源,不足和錯誤之處請在評論區幫忙指出,謝謝! 本專欄目錄結構和參考文獻請見《機器學習數學通關指南》 正文 一句話總結 泰勒公式是用多…

游戲引擎學習第124天

倉庫:https://gitee.com/mrxiao_com/2d_game_3 回顧/復習 今天是繼續完善和調試多線程的任務隊列。之前的幾天,我們已經介紹了多線程的一些基礎知識,包括如何創建工作隊列以及如何在線程中處理任務。今天,重點是解決那些我們之前沒有注意到…

在MacOS上打造本地部署的大模型知識庫(一)

一、在MacOS上安裝Ollama docker run -d -p 3000:8080 --add-hosthost.docker.internal:host-gateway -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:main 最后停掉Docker的ollama,就能在webui中加載llama模…

(八)Java-Collection

一、Collection接口 1.特點 Collection實現子類可以存放多個元素,每個元素可以是Object; 有些Collection的實現類,可以存放重復的元素,有些不可以; 有些Collection的實現類,有些是有序的(Li…

大模型RAG(檢索增強)創新--SELF-RAG

檢索增強生成 (RAG) 提供了一種將 ChatGPT/GPT-4 等大型語言模型與自定義數據集成的途徑,但存在局限性。讓我們看看 RAG 最近的研究是如何解決一些問題。 大語言模型(LLM)將改變整個金融領域。其中一個場景是大語言模型可以學習大量文檔,并在很短的時間內…

《AI和人工智能和編程日報》

OpenAI:將深度研究擴展到 ChatGPT Plus、Team、Edu 和 Enterprise 用戶,每月 10 次查詢;Pro 用戶每月有 120 次查詢,ChatGPT 語音模式向免費用戶開放。DeepSeek:R1 大模型宣布降價,調用價格將至四分之一&am…

【音視頻】編解碼相關概念總結

NALU RTP PS流 三者總體關系 NALU在RTP中的應用:視頻流的RTP傳輸通常將NALU作為基本的單元進行傳輸。每個RTP包攜帶一個或多個NALU,這些NALU包含了視頻編碼數據。RTP協議通過其頭部信息(如時間戳、序列號等)幫助接收端重新排列和…

端口映射/內網穿透方式及問題解決:warning: remote port forwarding failed for listen port

文章目錄 需求:A機器是內網機器,B機器是公網服務器,想要從公網,訪問A機器的端口方式:端口映射,內網穿透,使用ssh打洞端口:遇到問題:命令執行成功,但是端口轉發…

11特殊函數

一、遞歸函數 遞歸概念:如果一個函數內部,包含了對自身的調用,則該函數稱為遞歸函數。要點: 只有能被表達為遞歸的問題,才能用遞歸函數解決。遞歸函數必須有一個可直接退出的條件,否則會進入無限遞歸。遞歸…

如何使用useContext進行全局狀態管理?

在 React 中,使用 useContext 進行全局狀態管理是一種有效的方法,尤其在需要在多個組件之間共享狀態時。useContext 允許你在組件樹中傳遞數據,而無需通過每個組件的 props 逐層傳遞。以下是關于如何使用 useContext 進行全局狀態管理的詳細指…

鴻蒙 ArkUI 實現敲木魚小游戲

敲木魚是一款具有禪意的趣味小游戲,本文將通過鴻蒙 ArkUI 框架的實現代碼,逐步解析其核心技術點,包括動畫驅動、狀態管理、音效震動反饋等。 一、架構設計與工程搭建 1.1 項目結構解析 完整項目包含以下核心模塊: ├── entry…

神經性肺纖維的預防方法

神經性肺纖維的預防方法 一、引言 神經性肺纖維化是一種慢性進行性肺部疾病,其病因復雜,包括遺傳、環境等多種因素。該病不僅影響患者的呼吸功能,還可能對神經系統造成損害。因此,預防神經性肺纖維化顯得尤為重要。本文將詳細介…

azure sql 網絡安全組 網絡安全sql注入

🍅 點擊文末小卡片 ,免費獲取網絡安全全套資料,資料在手,漲薪更快 SQL注入 1、原理 針對注入的攻擊行為可描述為通過用戶可控參數中注入SQL語法,破壞原有SQL結構,達到編寫程序意料之外結果的攻擊行為。 其…

【Day50 LeetCode】圖論問題 Ⅷ

一、圖論問題 Ⅷ 1、dijkstra算法 堆優化 采用堆來優化&#xff0c;適合節點多的稀疏圖。代碼如下&#xff1a; # include<iostream> # include<vector> # include<list> # include<queue> # include<climits>using namespace std;class myco…

利用node.js搭配express框架寫后端接口(一)

Node.js 憑借其高效的非阻塞 I/O 操作、事件驅動架構以及輕量級的特點&#xff0c;成為了開發高性能服務器應用的熱門選擇。Express 框架作為 Node.js 上最流行的 Web 應用框架之一&#xff0c;以其簡潔的 API 和豐富的中間件生態系統&#xff0c;極大地簡化了 Web 后端開發流程…

【小白數學】為什么可以用拉格朗日乘子法求函數的極值【二】

我們在上一篇【小白數學】- 為什么可以用拉格朗日乘子法求函數的極值【一】已經介紹了一種較為“嚴謹“的方法來說明為什么拉格朗日乘子法可以幫助我們求具有等式約束條件下的函數的極值。雖然在我們的例子中”等式約束“中只有一個等式。但其實很容易推廣到多個等式約束的情況…

JAVA面試_進階部分_netty面試題

1.BIO、NIO 和 AIO 的區別&#xff1f; BIO&#xff1a;一個連接一個線程&#xff0c;客戶端有連接請求時服務器端就需要啟動一個線程進行處理。線程開銷大。 偽異步 IO&#xff1a;將請求連接放入線程池&#xff0c;一對多&#xff0c;但線程還是很寶貴的資源。 NIO&#x…

考研出分24小時,人類精神狀態圖鑒

2月24日&#xff0c;上午10點起&#xff0c;各省考研初試成績陸續公布&#xff0c;考生們或緊張的輸入準考證號&#xff0c;或抱團等待“審判”。然而更魔幻的還在后頭——下午4點&#xff0c;教育部竟在同一天直接發布了《2025年研考國家分數線》。 不少網友表示&#xff1a;…

川翔云電腦優勢總結

在數字化時代&#xff0c;川翔云電腦依托云計算技術&#xff0c;為用戶解決硬件性能瓶頸問題。川翔云電腦使用云渲碼&#xff1a;【2355】 卓越硬件配置&#xff1a;配備 RTX 3090、48G 顯存的 RTX 4090plus&#xff0c;支持 1 - 8 卡機配置&#xff0c;多卡并行計算能力強&am…

DeepSeek開源周Day4:三連發!突破 AI 訓練瓶頸的立體解決方案,并行計算三劍客DualPipe、EPLB與Profile-data

項目地址&#xff1a; https://github.com/deepseek-ai/DualPipehttps://github.com/deepseek-ai/eplbhttps://github.com/deepseek-ai/profile-data 開源日歷&#xff1a;2025-02-24起 每日9AM(北京時間)更新&#xff0c;持續五天 (4/5)&#xff01; ? ? 一、背景概述 …