HarmonyOS 鸿蒙Next中如何循环播放wav音频
HarmonyOS 鸿蒙Next中如何循环播放wav音频 如何点击按钮后,循环播放wav音频,5分钟自动关闭?
3 回复
使用 AVPlayer 去播放 wav 格式文件,它支持 m4a、aac、mp3、ogg、wav、flac、amr、ape。
具体如下,要么把 url 换成在线地址,或者在文件在沙箱目录下 demo 是文件在 rawfile 目录然后复制到沙箱在处理的
import { AudioPlayerUtil } from '../../utils/AudioPlayerUtil';
import common from '@ohos.app.ability.common';
import fs, { ListFileOptions, ReadOptions, ReadTextOptions, WriteOptions } from '@ohos.file.fs';
@Entry
@Component
struct AudioPlayerPage {
private audioPlayerUtil: AudioPlayerUtil | null = null;
private durationInput: string = '60';
private context = this.getUIContext().getHostContext() as common.UIAbilityContext;
private SEP = '/'
build() {
Column({ space: 20 }) {
Text('音频播放器')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({ top: 40 });
TextInput({ placeholder: '请输入自动关闭时长(秒)', text: this.durationInput })
.type(InputType.Number)
.width(280)
.height(48)
.fontSize(16)
.onChange((value: string) => {
this.durationInput = value;
});
Button('rawfile复制本地')
.width(280)
.height(48)
.backgroundColor('#007DFF')
.fontColor('#FFFFFF')
.fontSize(16)
.onClick(() => {
let resourceManager = this.context.resourceManager;
let uintArray: Uint8Array = resourceManager.getRawFileContentSync("video.wav");
let pathDir = this.context.filesDir
console.error("pathDir:" + pathDir)
//创建目录
this.createOrExistsDir(pathDir)
let path = pathDir + "/video.wav"
this.createOrExistsFile(path)
if (fs.accessSync(path)) {
let isSuccess = this.writeEasy(path, uintArray.buffer, false)
if (isSuccess) {
console.error("写入成功")
} else {
console.error("写入失败")
}
}
});
Button('开始循环播放')
.width(280)
.height(48)
.backgroundColor('#007DFF')
.fontColor('#FFFFFF')
.fontSize(16)
.onClick(() => {
if (!this.audioPlayerUtil) {
this.audioPlayerUtil = new AudioPlayerUtil(this.context);
}
const duration = parseInt(this.durationInput) || 60;
let path = this.context.filesDir + "/video.wav"
if (!fs.accessSync(path)) {
console.error("文件不存在")
return
}
let file = this.openSync(path, fs.OpenMode.READ_WRITE);
this.audioPlayerUtil.startPlay(file, duration * 1000);
});
Button('停止播放')
.width(280)
.height(48)
.backgroundColor('#FF6B6B')
.fontColor('#FFFFFF')
.fontSize(16)
.onClick(() => {
this.audioPlayerUtil?.stopPlay();
});
}
.width('100%')
.alignItems(HorizontalAlign.Center)
.padding(20);
}
createOrExistsDir(rootDir: string): void {
// 确保目录路径以路径分隔符结尾
rootDir = rootDir[rootDir.length - 1] !== this.SEP ? rootDir + this.SEP : rootDir;
// 检查目录是否已存在
if (!fs.accessSync(rootDir)) {
// 如果不存在,则创建目录
fs.mkdirSync(rootDir, true)
}
}
createOrExistsFile(filePath: string): void {
let file = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)
fs.closeSync(file)
}
writeEasy(path: string, content: ArrayBuffer | string, append: boolean = true): boolean {
try {
let file = this.openSync(path, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
let offset = append ? fs.statSync(file.fd).size : 0
let options: WriteOptions = { offset: offset, encoding: 'utf-8' };
fs.writeSync(file.fd, content, options)
fs.closeSync(file.fd); //关闭文件;
return true
} catch (err) {
return false;
}
}
openSync(path: string, mode: number = fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE): fs.File {
return fs.openSync(path, mode);
}
}
import { media } from '@kit.MediaKit';
import { BusinessError } from '@kit.BasicServicesKit';
import common from '@ohos.app.ability.common';
import fs from '@ohos.file.fs';
export class AudioPlayerUtil {
private avPlayer: media.AVPlayer | null = null;
private timerId: number = -1;
private context: common.UIAbilityContext;
constructor(context: common.UIAbilityContext) {
this.context = context;
}
private async createAVPlayer(): Promise<media.AVPlayer> {
return await media.createAVPlayer();
}
private setupPlayerListeners(): void {
if (!this.avPlayer) return;
this.avPlayer.on('stateChange', async (state: string) => {
console.info(`AudioPlayer state changed: ${state}`);
if (state === 'initialized') {
this.avPlayer?.prepare();
} else if (state === 'prepared') {
this.avPlayer!.loop = true;
this.avPlayer?.play();
}
});
this.avPlayer.on('error', (error: BusinessError) => {
console.error(`AudioPlayer error code: ${error.code}, message: ${error.message}`);
this.release();
});
}
async startPlay(path: fs.File, autoStopDurationMs: number = 300000): Promise<void> {
this.stopPlay();
try {
this.avPlayer = await this.createAVPlayer();
this.setupPlayerListeners();
let avFile: media.AVFileDescriptor = {
fd: path.fd
}
this.avPlayer.fdSrc = avFile;
if (autoStopDurationMs > 0) {
this.timerId = setTimeout(() => {
this.stopPlay();
}, autoStopDurationMs);
}
} catch (error) {
console.error(`Failed to start audio playback: ${error}`);
}
}
stopPlay(): void {
if (this.avPlayer) {
try {
this.avPlayer.stop();
this.avPlayer.release();
} catch (error) {
console.error(`Error stopping player: ${error}`);
}
this.avPlayer = null;
}
if (this.timerId !== -1) {
clearTimeout(this.timerId);
this.timerId = -1;
}
}
release(): void {
this.stopPlay();
}
isPlaying(): boolean {
return this.avPlayer !== null;
}
}
更多关于HarmonyOS 鸿蒙Next中如何循环播放wav音频的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在鸿蒙Next中,使用 @ohos.multimedia.audio 模块的 createAudioPlayer() 创建播放器,设置 loop 属性为 true 即可循环播放wav音频。示例:audioPlayer.loop = true;。播放前需确保音频资源路径正确,并添加相应权限。
在HarmonyOS Next中实现点击按钮循环播放wav音频,并在5分钟后自动关闭,可以使用 AVPlayer 配合循环模式与延时任务来完成。示例代码如下:
import media from '@ohos.multimedia.media';
import common from '@ohos.app.ability.common';
// 创建AVPlayer实例
let avPlayer: media.AVPlayer = await media.createAVPlayer();
let context = getContext(this) as common.UIAbilityContext;
let fd = await context.resourceManager.getRawFileDescriptor('test.wav');
// 设置播放源
avPlayer.fdSrc = { fd: fd.fd, offset: fd.offset, length: fd.length };
// 设置为循环播放
avPlayer.loop = true;
// 播放
await avPlayer.play();
// 5分钟(300000毫秒)后停止并释放
setTimeout(() => {
avPlayer.stop();
avPlayer.release();
}, 300000);
- 关键点:
- 循环播放:直接将
loop属性设为true,播放结束后会自动重新开始。 - 资源加载:若 wav 文件在
rawfile目录下,使用getRawFileDescriptor获取文件描述符,然后以fdSrc方式设置。 - 自动关闭:利用
setTimeout在指定时间后调用stop()停止播放,并调用release()释放资源。
- 循环播放:直接将
若需要在按钮点击时触发播放,将上述代码放入按钮的 onClick 回调中即可。注意每次播放前最好先重置或释放旧的 AVPlayer 实例,避免资源冲突。

