鸿蒙-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.mzph.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; ​ ​ 一、背景概述 …