HarmonyOS 鸿蒙Next 请问音频第一次可以正常播放 第二次播放没有声音
HarmonyOS 鸿蒙Next 请问音频第一次可以正常播放 第二次播放没有声音
请问音频第一次可以正常播放,第二次播放没有声音,是什么原因
2 回复
因为setAVPlayerCallback方法在监听到状态切换时会执行相应的播放状态参考代码:
soundUtil.ets
import media from '@ohos.multimedia.media';
import common from '@ohos.app.ability.common';
import { BusinessError } from '@ohos.base';
import fs from '@ohos.file.fs';
import fileIo from '@ohos.file.fs';
import { fileUri } from '@kit.CoreFileKit';
export class AVPlayerDemo {
private avPlayer: media.AVPlayer | undefined
private count: number = 0;
private isSeek: boolean = true; // 用于区分模式是否支持seek操作
private fileSize: number = -1;
private fd: number = 0;
private state: string = ''
constructor() {
media.createAVPlayer((error: BusinessError, video: media.AVPlayer) => {
if (video != null) {
this.avPlayer = video;
console.info('Succeeded666 in creating AVPlayer');
} else {
console.error(`Failed to create AVPlayer, error message:${error.message}`);
}
})
}
// 注册avplayer回调函数
setAVPlayerCallback(avPlayer: media.AVPlayer) {
// seek操作结果回调函数
avPlayer.on('seekDone', (seekDoneTime: number) => {
console.info(`AVPlayer seek succeeded, seek time is ${seekDoneTime}`);
})
// error回调监听函数,当avPlayer在操作过程中出现错误时调用 reset接口触发重置流程
avPlayer.on('error', (err: BusinessError) => {
console.error(`Invoke avPlayer failed, code is ${err.code}, message is ${err.message}`);
avPlayer.reset(); // 调用reset重置资源,触发idle状态
})
// 状态机变化回调函数
avPlayer.on('stateChange', async (state: string, reason: media.StateChangeReason) => {
switch (state) {
case 'idle': // 成功调用reset接口后触发该状态机上报
console.info('AVPlayer state idle called.');
avPlayer.release(); // 调用release接口销毁实例对象
break;
case 'initialized': // avplayer 设置播放源后触发该状态上报
console.info('AVPlayer state initialized called.');
avPlayer.prepare();
break;
case 'prepared': // prepare调用成功后上报该状态机
console.info('AVPlayer state prepared called.');
avPlayer.play(); // 调用播放接口开始播放
break;
case 'playing': // play成功调用后触发该状态机上报
console.info('AVPlayer state playing called.');
if (this.count !== 0) {
if (this.isSeek) {
console.info('AVPlayer start to seek.');
avPlayer.seek(avPlayer.duration); //seek到音频末尾
} else {
// 当播放模式不支持seek操作时继续播放到结尾
console.info('AVPlayer wait to play end.');
}
} else {
// avPlayer.pause(); // 调用暂停接口暂停播放
}
this.count++;
break;
case 'paused': // pause成功调用后触发该状态机上报
console.info('AVPlayer state paused called.');
// avPlayer.play(); // 再次播放接口开始播放
break;
case 'completed': // 播放结束后触发该状态机上报
console.info('AVPlayer state completed called.');
// avPlayer.stop(); //调用播放结束接口
break;
case 'stopped': // stop接口成功调用后触发该状态机上报
console.info('AVPlayer state stopped called.');
// avPlayer.reset(); // 调用reset接口初始化avplayer状态
break;
case 'released':
console.info('AVPlayer state released called.');
this.avPlayer = await media.createAVPlayer()
this.avPlayer.prepare()
break;
default:
console.info('AVPlayer state unknown called.');
break;
}
})
}
// 以下demo为使用资源管理接口获取打包在HAP内的媒体资源文件并通过fdSrc属性进行播放示例
async avPlayerFdSrcDemo() {
// 创建状态机变化回调函数
this.setAVPlayerCallback(this.avPlayer!);
// 通过UIAbilityContext的resourceManager成员的getRawFd接口获取媒体资源播放地址
// 返回类型为{fd,offset,length},fd为HAP包fd地址,offset为媒体资源偏移量,length为播放长度
let context = getContext(this) as common.UIAbilityContext;
let fileDescriptor = await context.resourceManager.getRawFd('11582.mp3');
// let fileDescriptor = await context.resourceManager.getRawFd('1.wav');
let avFileDescriptor: media.AVFileDescriptor =
{ fd: fileDescriptor.fd, offset: fileDescriptor.offset, length: fileDescriptor.length };
this.isSeek = false; // 支持seek操作
// 为fdSrc赋值触发initialized状态机上报
this.avPlayer!.fdSrc = avFileDescriptor;
}
// 以下demo为使用fs文件系统打开沙箱地址获取媒体文件地址并通过url属性进行播放示例
async avPlayerUrlDemo() {
// 创建avPlayer实例对象
let avPlayer: media.AVPlayer = await media.createAVPlayer();
// 创建状态机变化回调函数
this.setAVPlayerCallback(avPlayer);
let fdPath = 'fd://';
// 通过UIAbilityContext获取沙箱地址filesDir,以Stage模型为例
let context = getContext(this) as common.UIAbilityContext;
let pathDir = context.filesDir;
let path = pathDir + '/pCdJNp/1.wav';
console.log(`path123456: ${path}`);
// 打开相应的资源文件地址获取fd,并为url赋值触发initialized状态机上报
let file = await fs.open(path);
fdPath = fdPath + '' + file.fd;
this.isSeek = true; // 支持seek操作
avPlayer.url = fdPath;
}
myRawfileCopy() {
let context = getContext(this) as common.UIAbilityContext;
context.resourceManager.getRawFileContent("1.wav", (err: BusinessError, data: Uint8Array) => {
if (err != null) {
console.error(`open 1.wav failed: ${err.message}`)
} else {
let buffer = data.buffer
let sanboxPath = context.filesDir
console.log('myRawfileCopy path' + sanboxPath)
fs.mkdtemp(sanboxPath, async (err, res) => {
if (err != null) {
console.error(err?.message)
return
}
console.log("res::" + res)
let filePath = res + "/1.wav"
let file = fs.openSync(filePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE)
try {
fs.writeSync(file.fd, buffer)
// 拷贝文件到沙箱,为了简便,这里是直接getrawfilecontent然后写入,当文件过大时内存压力会很大,如需优化,可通过buffer进行读取
fs.close(file.fd)
// 把沙箱中的文件第一行读出来,验证是否拷贝成功;(fs.readFileSync 方法读取整个文件)
let data = fileIo.readTextSync(filePath);
this.avPlayerUrlDemo()
console.log('myRawfileCopy success ' + data)
} catch (err) {
console.log('myRawfileCopy error')
}
})
}
})
}
async stop() {
this.avPlayer?.stop()
}
async play() {
this.avPlayer?.play()
}
async reset() {
this.avPlayer?.reset()
}
async pause() {
this.avPlayer?.pause()
}
// getState() {
// this.avPlayer!.on('stateChange', async (state: string, reason: media.StateChangeReason) => {
// return state;
// })
// }
}
Index.ets代码
import { AVPlayerDemo } from '../pages/soundUtil'
[@Entry](/user/Entry)
[@Component](/user/Component)
struct Index2 {
[@State](/user/State) message: string = '播放音频文件';
private avplayer = new AVPlayerDemo();
build() {
Column({ space: 10 }) {
Button('初始化播放').onClick(() => {
console.log("开始播放音频文件")
this.avplayer.avPlayerFdSrcDemo()
})
Button('暂停播放').onClick(async () => {
console.log("暂停播放音频文件")
this.avplayer.pause()
})
Button('恢复播放').onClick(async () => {
console.log("恢复播放音频文件")
this.avplayer.play()
})
Button('停止播放').onClick(async () => {
console.log("停止播放音频文件")
this.avplayer.stop()
})
Button('重置播放').onClick(async () => {
console.log("重置播放音频文件")
this.avplayer.reset()
})
}.width('100%').height('100%').justifyContent(FlexAlign.Center)
}
}
修改如下:
Index.ets代码
Button('初始化播放').onClick(() => {
console.log("开始播放音频文件")
// this.avplayer.avPlayerFdSrcDemo()
this.avplayer.avPlayerUrlDemo()
// this.avplayer.myRawfileCopy()
// this.avplayer.avPlayerDataSrcSeekDemo()
})
soundUtil.ets代码
// 以下demo为使用fs文件系统打开沙箱地址获取媒体文件地址并通过url属性进行播放示例
async avPlayerUrlDemo() {
// 创建avPlayer实例对象
// let avPlayer: media.AVPlayer = await media.createAVPlayer();
// 创建状态机变化回调函数
this.setAVPlayerCallback(this.avPlayer!);
let fdPath = 'fd://';
// 通过UIAbilityContext获取沙箱地址filesDir,以Stage模型为例
let context = getContext(this) as common.UIAbilityContext;
let pathDir = context.filesDir;
// let path = pathDir + '/pCdJNp/1.wav';
//这里是写死了沙箱路径,可自行调整
let path = '/data/storage/el2/base/haps/entry/cache/1.wav';
console.log(`path123456: ${path}`);
// 打开相应的资源文件地址获取fd,并为url赋值触发initialized状态机上报
let file = await fs.open(path);
fdPath = fdPath + '' + file.fd;
let avFileDescriptor: media.AVFileDescriptor =
{ fd: file.fd };
this.isSeek = false; // 支持seek操作
// 为fdSrc赋值触发initialized状态机上报
this.avPlayer!.fdSrc = avFileDescriptor;
// this.isSeek = true; // 支持seek操作
// this.avPlayer!.url = fdPath;
}
更多关于HarmonyOS 鸿蒙Next 请问音频第一次可以正常播放 第二次播放没有声音的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙Next系统中,针对音频第一次可以正常播放而第二次播放没有声音的问题,可能的原因包括以下几点:
-
音频资源未正确释放:首次播放后,音频资源可能未被正确释放或重置,导致第二次播放时资源冲突或状态异常。
-
播放状态未重置:音频播放器对象在首次播放后可能未恢复到初始状态,影响后续播放。
-
后台权限或策略限制:系统可能对后台音频播放有特定策略,如限制后台音频同时播放的数量或时间。
-
系统资源占用:系统资源紧张时,可能无法为第二次播放分配足够的资源。
-
音频文件损坏或路径错误:确保第二次播放的音频文件未损坏且路径正确。
-
播放接口异常:使用的播放接口在第二次调用时可能出现异常,导致无声。
针对上述问题,可以尝试以下操作(注意,这里不给出具体代码或建议,仅描述可能的方向):
- 确保每次播放后正确释放和重置音频资源。
- 检查并更新音频播放器的状态管理。
- 审查应用的后台权限设置,确保符合系统要求。
- 优化资源使用,避免系统资源紧张。
- 验证音频文件的完整性和路径正确性。
- 调用播放接口时,注意异常处理。
如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html