import media from '@ohos.multimedia.media'; import Prompt from '@system.prompt'; import url from '@ohos.url'; import fileuri from "@ohos.file.fileuri"; import mediaLibrary from '@ohos.multimedia.mediaLibrary'; const TAG = 'VoiceAnnounce' export default class VoiceAnnounce{ //队列时候立马终止 private isStopped:Boolean private queue:{ url:string, callback?:Function }[] private newQueue:{ url:string, callback?:Function }[] private pendingQueue:String[] private callback:Function; constructor() { this.isStopped = false; this.queue = [] } async playAudio(urls:string[],shit?:boolean,callback?:Function){ const {isStopped,queue} = this; const tempUrls = urls.map((url,index)=>{ return { url, callback:(index === urls.length - 1)?callback:undefined } }); if(shit){ //队列清空,重新初始化 this.isStopped = true; this.newQueue = tempUrls } if(queue.length){ //队列续上 this.queue = this.queue.concat(tempUrls) // console.info(TAG,'语音队列开始'+shit + JSON.stringify( this.queue)) }else{ this.queue = tempUrls // console.info(TAG,'语音队列开始' + shit+JSON.stringify( this.queue)) await this.executeQueue() } } async executeQueue(){ const go = async () => { const {queue,isStopped,newQueue} = this; const avPlayer = new AVPlayer(); if(isStopped){ //清空原来队列 this.queue = newQueue this.isStopped = false; await go() return } console.info(TAG,'当前播放队列' + JSON.stringify( queue)) await avPlayer.play(queue[0].url,queue[0].callback); this.queue.shift(); console.info(TAG,'当前播放队列播放完成退出'); avPlayer.avPlayerStop(); if(this.queue.length){ await go() } } await go() } } class AVPlayer { public avPlayer:any = null; private voiceUrl: string[]; private voiceStatus: 'completed' | 'playing' private endCallback:Function constructor() {} // 以下为使用资源管理接口获取打包在HAP内的媒体资源文件并通过fdSrc属性进行播放示例 async play(name,callback) { try { //检查SD中的语音 // console.info('surenjun name',name) // console.info('surenjun name',name.split('/')[1]) let playSrc = await this.queryFile(name.split('/')[1]); let fdPath = await playSrc.open('r') let audioPlayer = media.createAudioPlayer() // console.info('surenjun fdPath=>',fdPath) console.info(TAG,'audioPlayer => 准备加载资源播放') audioPlayer.on('dataLoad', () => { this.voiceStatus = 'playing' console.info(TAG,'audioPlayer => 播放资源开始') audioPlayer.play() }) return new Promise(async (resolve)=>{ audioPlayer.on('finish', () => { console.info(TAG,'audioPlayer => 播放资源播放') //@ts-ignore this.voiceStatus = 'completed' if(callback){ callback() } audioPlayer.stop(); audioPlayer.reset() audioPlayer.release() resolve(true) }) audioPlayer.reset() audioPlayer.src = `fd://${fdPath}` }) }catch (e){ //检查SD中的语音 this.endCallback = callback this.avPlayer = await media.createAVPlayer(); return new Promise(async (resolve,reject) => { await this.setAVPlayerCallback(()=>{ //@ts-ignore resolve() }); try { this.avPlayer.fdSrc = await globalThis.context.resourceManager.getRawFd(name); } catch (e) { Prompt.showToast({ message: `${name}语音文件不存在`, duration: 4000 }); resolve(1) } }) } } async queryFile(displayName): Promise { return new Promise(async (resolve,reject)=>{ const mediaLib = mediaLibrary.getMediaLibrary(globalThis.context); let ret let fetchOp = { selections: `media_type=? AND display_name = ?`, selectionArgs: [`${mediaLibrary.MediaType.AUDIO}`,displayName], }; let fileResult = await mediaLib.getFileAssets(fetchOp); let retCount = fileResult.getCount(); if (retCount > 0) { ret = fileResult.getFirstObject(); return resolve(ret); }else{ return reject(false); } }) } //音频播放队列 public releasePlayer() { this.avPlayer.release(); } avPlayerStop = ()=> { this.avPlayer && this.avPlayer.stop() this.avPlayer && this.avPlayer.reset() this.avPlayer && this.avPlayer.release() } // 注册avplayer回调函数 setAVPlayerCallback(callBack) { this.avPlayer.on('error', (err) => { this.avPlayer && this.avPlayer.stop() this.avPlayer && this.avPlayer.reset() this.avPlayer && this.avPlayer.release() }) let num = 0; // 状态机变化回调函数 this.avPlayer.on('stateChange', async (state, reason) => { const {endCallback} = this; switch (state) { case 'idle': // 成功调用reset接口后触发该状态机上报 break; case 'initialized': // avplayer 设置播放源后触发该状态上报 this.avPlayer.prepare() break; case 'prepared': // prepare调用成功后上报该状态机 console.info(TAG,'播放资源播放') this.avPlayer.play(); this.voiceStatus = 'playing' break; case 'playing': // play成功调用后触发该状态机上报 break; case 'paused': // pause成功调用后触发该状态机上报 break; case 'completed': // 播放结束后触发该状态机上报 this.voiceStatus = 'completed' this.avPlayer.stop(); //调用播放结束接口 break; case 'stopped': // stop接口成功调用后触发该状态机上报 this.avPlayer.reset(); // 调用reset接口初始化avplayer状态 console.info(TAG,'播放资源释放') if(endCallback){ endCallback() } callBack() break; case 'released': break; default: break; } }) } }