222 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			222 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| 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<mediaLibrary.FileAsset> {
 | |
|     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;
 | |
|       }
 | |
|     })
 | |
|   }
 | |
| } |