fmode-ng 0.0.19 → 0.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2020/lib/aigc/avatar/comp-avatar-talk/comp-avatar-talk.component.mjs +1 -1
- package/esm2020/lib/aigc/avatar/modal-chat-voice-input/modal-chat-voice-input.component.mjs +1 -1
- package/fesm2015/fmode-ng.mjs +1 -1
- package/fesm2015/fmode-ng.mjs.map +1 -1
- package/fesm2020/fmode-ng.mjs +1 -1
- package/fesm2020/fmode-ng.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
* 保留所有权利 All Rights Reserved.
|
|
6
6
|
* /home/ryan/workspace/nova/nova-admin/dist/fmode-ng/esm2020/lib/aigc/avatar/comp-avatar-talk/comp-avatar-talk.component.mjs
|
|
7
7
|
*/
|
|
8
|
-
import{Component,ElementRef,ViewChild}from"@angular/core";import{FmodeVoiceService}from"../../voice";import{ChatService}from"../../service-fmai/service-chat";import{IonicModule,NavController,Platform}from"@ionic/angular";import{CommonModule}from"@angular/common";import{CompAvatarParticleComponent}from"../comp-avatar-particle/comp-avatar-particle.component";import{CompAvatarRoleImageComponent}from"../comp-avatar-role-image/comp-avatar-role-image.component";import{FormsModule}from"@angular/forms";import{ActivatedRoute,Router,RouterModule}from"@angular/router";import*as Parse from"parse";import{NovaCloudService}from"../../../nova-cloud/nova-cloud.service";import{HidexmlPipe}from"../../service-fmai/service-chat";import{ModalChatVoiceInputComponent}from"../modal-chat-voice-input/modal-chat-voice-input.component";import*as i0 from"@angular/core";import*as i1 from"../../voice";import*as i2 from"@ionic/angular";import*as i3 from"@angular/router";import*as i4 from"../../service-fmai/service-chat";import*as i5 from"../../../nova-cloud/nova-cloud.service";import*as i6 from"@angular/common";export class CompAvatarTalkComponent{constructor(e,o,n,t,i,a,r){this.voiceServ=e,this.platform=o,this.router=n,this.navCtrl=t,this.route=i,this.chatServ=a,this.ncloud=r,this.route.paramMap.subscribe((e=>{this.roleId=e.get("roleId"),this.loadAvatarRole(this.roleId)})),document.body.classList.add("dark")}ngOnInit(){}ngOnDestroy(){document.body.classList.remove("dark"),this.voiceServ.resultText=null,this.fmodeChat&&(this.fmodeChat.latestAIResponse=null)}goBack(){document.body.classList.remove("dark"),this.navCtrl.navigateRoot("/chat/pro/role/"+this.roleId)}async loadAvatarRole(e){let o=new Parse.Query("AvatarRole");this.avatarRole=await o.get(e);let n=await this.chatServ.createNewRoleChat(this.roleId);n.isTalkMode=!0,this.fmodeChat=n}ngAfterViewInit(){this.listenDivChange()}listenDivChange(){new MutationObserver((()=>{this.scrollToBottom(this.aiRespComp)})).observe(this.aiRespComp.nativeElement,{childList:!0,subtree:!0,attributes:!0})}scrollToBottom(e){e?.nativeElement?.scrollHeight&&(e.nativeElement.scrollTop=e.nativeElement.scrollHeight)}}CompAvatarTalkComponent.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.1.0",ngImport:i0,type:CompAvatarTalkComponent,deps:[{token:i1.FmodeVoiceService},{token:i2.Platform},{token:i3.Router},{token:i2.NavController},{token:i3.ActivatedRoute},{token:i4.ChatService},{token:i5.NovaCloudService}],target:i0.ɵɵFactoryTarget.Component}),CompAvatarTalkComponent.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.1.0",type:CompAvatarTalkComponent,isStandalone:!0,selector:"app-comp-avatar-talk",providers:[FmodeVoiceService,NovaCloudService,ChatService],viewQueries:[{propertyName:"avatarComp",first:!0,predicate:["avatar"],descendants:!0},{propertyName:"aiRespComp",first:!0,predicate:["aiRespComp"],descendants:!0}],ngImport:i0,template:'<ion-menu #menu contentId="main-content" side="end">\n <ion-header>\n <ion-toolbar>\n <ion-title>资料</ion-title>\n </ion-toolbar>\n </ion-header>\n <ion-content class="ion-padding">\n\n <ion-card style="margin: 0px;">\n <img [src]="avatarRole?.get(\'thumb\')" alt="">\n <ion-card-header>\n <ion-card-subtitle>{{avatarRole?.get(\'tags\')}}</ion-card-subtitle>\n <ion-card-title>{{avatarRole?.get("name")}}</ion-card-title>\n </ion-card-header>\n \n <ion-card-content>\n {{avatarRole?.get("desc")}}\n\n <ion-list [inset]="true" style="margin:0px;">\n \x3c!-- <ion-item>\n <ion-avatar *ngIf="avatarRole?.get(\'thumb\')" aria-hidden="true" slot="start">\n <img [src]="avatarRole?.get(\'thumb\')" />\n </ion-avatar>\n <ion-label>{{avatarRole?.get("name")}}</ion-label>\n </ion-item> --\x3e\n <ion-item lines="none" *ngIf="avatarRole?.get(\'age\')">\n <ion-note slot="start">年龄</ion-note>\n <ion-label>{{avatarRole?.get("age")}}</ion-label>\n </ion-item>\n <ion-item lines="none" *ngIf="avatarRole?.get(\'gender\')">\n <ion-note slot="start">性别</ion-note>\n <ion-label>{{avatarRole?.get("gender")}}</ion-label>\n </ion-item>\n <ion-item lines="none">\n <ion-note slot="start">称号</ion-note>\n <ion-label>{{avatarRole?.get("title")}}</ion-label>\n </ion-item>\n \n <ion-item lines="none">\n <ion-note slot="start">擅长</ion-note>\n <ion-label>{{avatarRole?.get("tags")?.join(\',\')}}</ion-label>\n </ion-item>\n\n </ion-list>\n </ion-card-content>\n </ion-card>\n \n \n \n </ion-content>\n</ion-menu>\n\n<div class="ion-page" id="main-content">\n <ion-header class="ion-no-border">\n <ion-toolbar>\n <ion-buttons slot="start">\n <ion-button (click)="goBack()"> <ion-icon name="chevron-back-outline"></ion-icon> </ion-button>\n </ion-buttons>\n <ion-title>\n <ion-chip *ngIf="avatarRole?.get(\'title\')">{{avatarRole?.get("title")}}</ion-chip>\n </ion-title>\n <ion-buttons slot="end">\n \x3c!-- <ion-button (click)="playTTSTeting()">TTS测试</ion-button> --\x3e\n {{avatarRole?.get("name")}}\n <ion-button (click)="menu.toggle()"> <ion-icon name="ellipsis-horizontal-outline"></ion-icon> </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n\n <ion-segment value="voice">\n <ion-segment-button (click)="chatServ.createChatPanel(avatarRole)" value="chat">\n <ion-label>聊天</ion-label>\n </ion-segment-button>\n <ion-segment-button routerLink="{{\'/avatar/role/\'+avatarRole?.id}}" value="voice">\n <ion-label>语音</ion-label>\n </ion-segment-button>\n </ion-segment>\n\n \x3c!-- 数字形象:动画效果 --\x3e\n <fm-avatar-role-image *ngIf="avatarRole&&fmodeChat" [fmodeChat]="fmodeChat" [role]="avatarRole" #avatar class="avatar"></fm-avatar-role-image>\n \x3c!-- <fm-avatar-role-particle #avatar class="avatar"></fm-avatar-role-particle> --\x3e\n\n \x3c!-- AI回复的最新消息 --\x3e\n <div class="ai-resp-input" #aiRespComp>{{fmodeChat?.latestAIResponse | hidexml}}</div>\n\n <fm-modal-chat-voice-input *ngIf="fmodeChat" [fmodeChat]="fmodeChat"></fm-modal-chat-voice-input>\n\n</div>\n\n',styles:["ion-menu ion-note{color:#ccc;font-weight:700}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.avatar{display:block;width:100%;height:100%}.ai-resp-input{font-size:1rem;color:#fff;position:fixed;top:5vh;max-height:15vh;overflow-y:scroll;padding:0 10px}.user-asr-input{font-size:1rem;color:#fff;position:fixed;bottom:6vh;padding:0 10px}.test-button-group{color:#00f;position:fixed;bottom:20vh}.test-button-group button{padding:10px;margin:10px}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i6.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:RouterModule},{kind:"directive",type:i3.RouterLink,selector:"[routerLink]",inputs:["target","queryParams","fragment","queryParamsHandling","state","relativeTo","preserveFragment","skipLocationChange","replaceUrl","routerLink"]},{kind:"ngmodule",type:FormsModule},{kind:"ngmodule",type:IonicModule},{kind:"component",type:i2.IonButton,selector:"ion-button",inputs:["buttonType","color","disabled","download","expand","fill","form","href","mode","rel","routerAnimation","routerDirection","shape","size","strong","target","type"]},{kind:"component",type:i2.IonButtons,selector:"ion-buttons",inputs:["collapse"]},{kind:"component",type:i2.IonCard,selector:"ion-card",inputs:["button","color","disabled","download","href","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:i2.IonCardContent,selector:"ion-card-content",inputs:["mode"]},{kind:"component",type:i2.IonCardHeader,selector:"ion-card-header",inputs:["color","mode","translucent"]},{kind:"component",type:i2.IonCardSubtitle,selector:"ion-card-subtitle",inputs:["color","mode"]},{kind:"component",type:i2.IonCardTitle,selector:"ion-card-title",inputs:["color","mode"]},{kind:"component",type:i2.IonChip,selector:"ion-chip",inputs:["color","disabled","mode","outline"]},{kind:"component",type:i2.IonContent,selector:"ion-content",inputs:["color","forceOverscroll","fullscreen","scrollEvents","scrollX","scrollY"]},{kind:"component",type:i2.IonHeader,selector:"ion-header",inputs:["collapse","mode","translucent"]},{kind:"component",type:i2.IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:i2.IonItem,selector:"ion-item",inputs:["button","color","counter","counterFormatter","detail","detailIcon","disabled","download","fill","href","lines","mode","rel","routerAnimation","routerDirection","shape","target","type"]},{kind:"component",type:i2.IonLabel,selector:"ion-label",inputs:["color","mode","position"]},{kind:"component",type:i2.IonList,selector:"ion-list",inputs:["inset","lines","mode"]},{kind:"component",type:i2.IonMenu,selector:"ion-menu",inputs:["contentId","disabled","maxEdgeStart","menuId","side","swipeGesture","type"]},{kind:"component",type:i2.IonNote,selector:"ion-note",inputs:["color","mode"]},{kind:"component",type:i2.IonSegment,selector:"ion-segment",inputs:["color","disabled","mode","scrollable","selectOnFocus","swipeGesture","value"]},{kind:"component",type:i2.IonSegmentButton,selector:"ion-segment-button",inputs:["disabled","layout","mode","type","value"]},{kind:"component",type:i2.IonTitle,selector:"ion-title",inputs:["color","size"]},{kind:"component",type:i2.IonToolbar,selector:"ion-toolbar",inputs:["color","mode"]},{kind:"directive",type:i2.SelectValueAccessor,selector:"ion-range, ion-select, ion-radio-group, ion-segment, ion-datetime"},{kind:"directive",type:i2.RouterLinkDelegate,selector:":not(a):not(area)[routerLink]",inputs:["routerDirection","routerAnimation"]},{kind:"component",type:CompAvatarRoleImageComponent,selector:"fm-avatar-role-image",inputs:["fmodeChat","role"]},{kind:"component",type:ModalChatVoiceInputComponent,selector:"fm-modal-chat-voice-input",inputs:["fmodeChat","talkMode"]},{kind:"pipe",type:HidexmlPipe,name:"hidexml"}]}),i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.1.0",ngImport:i0,type:CompAvatarTalkComponent,decorators:[{type:Component,args:[{selector:"app-comp-avatar-talk",standalone:!0,imports:[CommonModule,RouterModule,FormsModule,IonicModule,CompAvatarParticleComponent,CompAvatarRoleImageComponent,ModalChatVoiceInputComponent,HidexmlPipe],providers:[FmodeVoiceService,NovaCloudService,ChatService],template:'<ion-menu #menu contentId="main-content" side="end">\n <ion-header>\n <ion-toolbar>\n <ion-title>资料</ion-title>\n </ion-toolbar>\n </ion-header>\n <ion-content class="ion-padding">\n\n <ion-card style="margin: 0px;">\n <img [src]="avatarRole?.get(\'thumb\')" alt="">\n <ion-card-header>\n <ion-card-subtitle>{{avatarRole?.get(\'tags\')}}</ion-card-subtitle>\n <ion-card-title>{{avatarRole?.get("name")}}</ion-card-title>\n </ion-card-header>\n \n <ion-card-content>\n {{avatarRole?.get("desc")}}\n\n <ion-list [inset]="true" style="margin:0px;">\n \x3c!-- <ion-item>\n <ion-avatar *ngIf="avatarRole?.get(\'thumb\')" aria-hidden="true" slot="start">\n <img [src]="avatarRole?.get(\'thumb\')" />\n </ion-avatar>\n <ion-label>{{avatarRole?.get("name")}}</ion-label>\n </ion-item> --\x3e\n <ion-item lines="none" *ngIf="avatarRole?.get(\'age\')">\n <ion-note slot="start">年龄</ion-note>\n <ion-label>{{avatarRole?.get("age")}}</ion-label>\n </ion-item>\n <ion-item lines="none" *ngIf="avatarRole?.get(\'gender\')">\n <ion-note slot="start">性别</ion-note>\n <ion-label>{{avatarRole?.get("gender")}}</ion-label>\n </ion-item>\n <ion-item lines="none">\n <ion-note slot="start">称号</ion-note>\n <ion-label>{{avatarRole?.get("title")}}</ion-label>\n </ion-item>\n \n <ion-item lines="none">\n <ion-note slot="start">擅长</ion-note>\n <ion-label>{{avatarRole?.get("tags")?.join(\',\')}}</ion-label>\n </ion-item>\n\n </ion-list>\n </ion-card-content>\n </ion-card>\n \n \n \n </ion-content>\n</ion-menu>\n\n<div class="ion-page" id="main-content">\n <ion-header class="ion-no-border">\n <ion-toolbar>\n <ion-buttons slot="start">\n <ion-button (click)="goBack()"> <ion-icon name="chevron-back-outline"></ion-icon> </ion-button>\n </ion-buttons>\n <ion-title>\n <ion-chip *ngIf="avatarRole?.get(\'title\')">{{avatarRole?.get("title")}}</ion-chip>\n </ion-title>\n <ion-buttons slot="end">\n \x3c!-- <ion-button (click)="playTTSTeting()">TTS测试</ion-button> --\x3e\n {{avatarRole?.get("name")}}\n <ion-button (click)="menu.toggle()"> <ion-icon name="ellipsis-horizontal-outline"></ion-icon> </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n\n <ion-segment value="voice">\n <ion-segment-button (click)="chatServ.createChatPanel(avatarRole)" value="chat">\n <ion-label>聊天</ion-label>\n </ion-segment-button>\n <ion-segment-button routerLink="{{\'/avatar/role/\'+avatarRole?.id}}" value="voice">\n <ion-label>语音</ion-label>\n </ion-segment-button>\n </ion-segment>\n\n \x3c!-- 数字形象:动画效果 --\x3e\n <fm-avatar-role-image *ngIf="avatarRole&&fmodeChat" [fmodeChat]="fmodeChat" [role]="avatarRole" #avatar class="avatar"></fm-avatar-role-image>\n \x3c!-- <fm-avatar-role-particle #avatar class="avatar"></fm-avatar-role-particle> --\x3e\n\n \x3c!-- AI回复的最新消息 --\x3e\n <div class="ai-resp-input" #aiRespComp>{{fmodeChat?.latestAIResponse | hidexml}}</div>\n\n <fm-modal-chat-voice-input *ngIf="fmodeChat" [fmodeChat]="fmodeChat"></fm-modal-chat-voice-input>\n\n</div>\n\n',styles:["ion-menu ion-note{color:#ccc;font-weight:700}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.avatar{display:block;width:100%;height:100%}.ai-resp-input{font-size:1rem;color:#fff;position:fixed;top:5vh;max-height:15vh;overflow-y:scroll;padding:0 10px}.user-asr-input{font-size:1rem;color:#fff;position:fixed;bottom:6vh;padding:0 10px}.test-button-group{color:#00f;position:fixed;bottom:20vh}.test-button-group button{padding:10px;margin:10px}\n"]}]}],ctorParameters:function(){return[{type:i1.FmodeVoiceService},{type:i2.Platform},{type:i3.Router},{type:i2.NavController},{type:i3.ActivatedRoute},{type:i4.ChatService},{type:i5.NovaCloudService}]},propDecorators:{avatarComp:[{type:ViewChild,args:["avatar"]}],aiRespComp:[{type:ViewChild,args:["aiRespComp"]}]}});
|
|
8
|
+
import{Component,ElementRef,ViewChild}from"@angular/core";import{FmodeVoiceService}from"../../voice";import{ChatService}from"../../service-fmai/service-chat";import{IonicModule,NavController,Platform}from"@ionic/angular";import{CommonModule}from"@angular/common";import{CompAvatarParticleComponent}from"../comp-avatar-particle/comp-avatar-particle.component";import{CompAvatarRoleImageComponent}from"../comp-avatar-role-image/comp-avatar-role-image.component";import{FormsModule}from"@angular/forms";import{ActivatedRoute,Router,RouterModule}from"@angular/router";import*as Parse from"parse";import{NovaCloudService}from"../../../nova-cloud/nova-cloud.service";import{HidexmlPipe}from"../../service-fmai/service-chat";import{ModalChatVoiceInputComponent}from"../modal-chat-voice-input/modal-chat-voice-input.component";import{Diagnostic}from"@awesome-cordova-plugins/diagnostic/ngx";import*as i0 from"@angular/core";import*as i1 from"../../voice";import*as i2 from"@ionic/angular";import*as i3 from"@angular/router";import*as i4 from"../../service-fmai/service-chat";import*as i5 from"../../../nova-cloud/nova-cloud.service";import*as i6 from"@angular/common";export class CompAvatarTalkComponent{constructor(e,o,n,t,i,a,r){this.voiceServ=e,this.platform=o,this.router=n,this.navCtrl=t,this.route=i,this.chatServ=a,this.ncloud=r,this.route.paramMap.subscribe((e=>{this.roleId=e.get("roleId"),this.loadAvatarRole(this.roleId)})),document.body.classList.add("dark")}ngOnInit(){}ngOnDestroy(){document.body.classList.remove("dark"),this.voiceServ.resultText=null,this.fmodeChat&&(this.fmodeChat.latestAIResponse=null)}goBack(){document.body.classList.remove("dark"),this.navCtrl.navigateRoot("/chat/pro/role/"+this.roleId)}async loadAvatarRole(e){let o=new Parse.Query("AvatarRole");this.avatarRole=await o.get(e);let n=await this.chatServ.createNewRoleChat(this.roleId);n.isTalkMode=!0,this.fmodeChat=n}ngAfterViewInit(){this.listenDivChange()}listenDivChange(){new MutationObserver((()=>{this.scrollToBottom(this.aiRespComp)})).observe(this.aiRespComp.nativeElement,{childList:!0,subtree:!0,attributes:!0})}scrollToBottom(e){e?.nativeElement?.scrollHeight&&(e.nativeElement.scrollTop=e.nativeElement.scrollHeight)}}CompAvatarTalkComponent.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.1.0",ngImport:i0,type:CompAvatarTalkComponent,deps:[{token:i1.FmodeVoiceService},{token:i2.Platform},{token:i3.Router},{token:i2.NavController},{token:i3.ActivatedRoute},{token:i4.ChatService},{token:i5.NovaCloudService}],target:i0.ɵɵFactoryTarget.Component}),CompAvatarTalkComponent.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.1.0",type:CompAvatarTalkComponent,isStandalone:!0,selector:"app-comp-avatar-talk",providers:[FmodeVoiceService,NovaCloudService,ChatService,Diagnostic],viewQueries:[{propertyName:"avatarComp",first:!0,predicate:["avatar"],descendants:!0},{propertyName:"aiRespComp",first:!0,predicate:["aiRespComp"],descendants:!0}],ngImport:i0,template:'<ion-menu #menu contentId="main-content" side="end">\n <ion-header>\n <ion-toolbar>\n <ion-title>资料</ion-title>\n </ion-toolbar>\n </ion-header>\n <ion-content class="ion-padding">\n\n <ion-card style="margin: 0px;">\n <img [src]="avatarRole?.get(\'thumb\')" alt="">\n <ion-card-header>\n <ion-card-subtitle>{{avatarRole?.get(\'tags\')}}</ion-card-subtitle>\n <ion-card-title>{{avatarRole?.get("name")}}</ion-card-title>\n </ion-card-header>\n \n <ion-card-content>\n {{avatarRole?.get("desc")}}\n\n <ion-list [inset]="true" style="margin:0px;">\n \x3c!-- <ion-item>\n <ion-avatar *ngIf="avatarRole?.get(\'thumb\')" aria-hidden="true" slot="start">\n <img [src]="avatarRole?.get(\'thumb\')" />\n </ion-avatar>\n <ion-label>{{avatarRole?.get("name")}}</ion-label>\n </ion-item> --\x3e\n <ion-item lines="none" *ngIf="avatarRole?.get(\'age\')">\n <ion-note slot="start">年龄</ion-note>\n <ion-label>{{avatarRole?.get("age")}}</ion-label>\n </ion-item>\n <ion-item lines="none" *ngIf="avatarRole?.get(\'gender\')">\n <ion-note slot="start">性别</ion-note>\n <ion-label>{{avatarRole?.get("gender")}}</ion-label>\n </ion-item>\n <ion-item lines="none">\n <ion-note slot="start">称号</ion-note>\n <ion-label>{{avatarRole?.get("title")}}</ion-label>\n </ion-item>\n \n <ion-item lines="none">\n <ion-note slot="start">擅长</ion-note>\n <ion-label>{{avatarRole?.get("tags")?.join(\',\')}}</ion-label>\n </ion-item>\n\n </ion-list>\n </ion-card-content>\n </ion-card>\n \n \n \n </ion-content>\n</ion-menu>\n\n<div class="ion-page" id="main-content">\n <ion-header class="ion-no-border">\n <ion-toolbar>\n <ion-buttons slot="start">\n <ion-button (click)="goBack()"> <ion-icon name="chevron-back-outline"></ion-icon> </ion-button>\n </ion-buttons>\n <ion-title>\n <ion-chip *ngIf="avatarRole?.get(\'title\')">{{avatarRole?.get("title")}}</ion-chip>\n </ion-title>\n <ion-buttons slot="end">\n \x3c!-- <ion-button (click)="playTTSTeting()">TTS测试</ion-button> --\x3e\n {{avatarRole?.get("name")}}\n <ion-button (click)="menu.toggle()"> <ion-icon name="ellipsis-horizontal-outline"></ion-icon> </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n\n <ion-segment value="voice">\n <ion-segment-button (click)="chatServ.createChatPanel(avatarRole)" value="chat">\n <ion-label>聊天</ion-label>\n </ion-segment-button>\n <ion-segment-button routerLink="{{\'/avatar/role/\'+avatarRole?.id}}" value="voice">\n <ion-label>语音</ion-label>\n </ion-segment-button>\n </ion-segment>\n\n \x3c!-- 数字形象:动画效果 --\x3e\n <fm-avatar-role-image *ngIf="avatarRole&&fmodeChat" [fmodeChat]="fmodeChat" [role]="avatarRole" #avatar class="avatar"></fm-avatar-role-image>\n \x3c!-- <fm-avatar-role-particle #avatar class="avatar"></fm-avatar-role-particle> --\x3e\n\n \x3c!-- AI回复的最新消息 --\x3e\n <div class="ai-resp-input" #aiRespComp>{{fmodeChat?.latestAIResponse | hidexml}}</div>\n\n <fm-modal-chat-voice-input *ngIf="fmodeChat" [fmodeChat]="fmodeChat"></fm-modal-chat-voice-input>\n\n</div>\n\n',styles:["ion-menu ion-note{color:#ccc;font-weight:700}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.avatar{display:block;width:100%;height:100%}.ai-resp-input{font-size:1rem;color:#fff;position:fixed;top:5vh;max-height:15vh;overflow-y:scroll;padding:0 10px}.user-asr-input{font-size:1rem;color:#fff;position:fixed;bottom:6vh;padding:0 10px}.test-button-group{color:#00f;position:fixed;bottom:20vh}.test-button-group button{padding:10px;margin:10px}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i6.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:RouterModule},{kind:"directive",type:i3.RouterLink,selector:"[routerLink]",inputs:["target","queryParams","fragment","queryParamsHandling","state","relativeTo","preserveFragment","skipLocationChange","replaceUrl","routerLink"]},{kind:"ngmodule",type:FormsModule},{kind:"ngmodule",type:IonicModule},{kind:"component",type:i2.IonButton,selector:"ion-button",inputs:["buttonType","color","disabled","download","expand","fill","form","href","mode","rel","routerAnimation","routerDirection","shape","size","strong","target","type"]},{kind:"component",type:i2.IonButtons,selector:"ion-buttons",inputs:["collapse"]},{kind:"component",type:i2.IonCard,selector:"ion-card",inputs:["button","color","disabled","download","href","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:i2.IonCardContent,selector:"ion-card-content",inputs:["mode"]},{kind:"component",type:i2.IonCardHeader,selector:"ion-card-header",inputs:["color","mode","translucent"]},{kind:"component",type:i2.IonCardSubtitle,selector:"ion-card-subtitle",inputs:["color","mode"]},{kind:"component",type:i2.IonCardTitle,selector:"ion-card-title",inputs:["color","mode"]},{kind:"component",type:i2.IonChip,selector:"ion-chip",inputs:["color","disabled","mode","outline"]},{kind:"component",type:i2.IonContent,selector:"ion-content",inputs:["color","forceOverscroll","fullscreen","scrollEvents","scrollX","scrollY"]},{kind:"component",type:i2.IonHeader,selector:"ion-header",inputs:["collapse","mode","translucent"]},{kind:"component",type:i2.IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:i2.IonItem,selector:"ion-item",inputs:["button","color","counter","counterFormatter","detail","detailIcon","disabled","download","fill","href","lines","mode","rel","routerAnimation","routerDirection","shape","target","type"]},{kind:"component",type:i2.IonLabel,selector:"ion-label",inputs:["color","mode","position"]},{kind:"component",type:i2.IonList,selector:"ion-list",inputs:["inset","lines","mode"]},{kind:"component",type:i2.IonMenu,selector:"ion-menu",inputs:["contentId","disabled","maxEdgeStart","menuId","side","swipeGesture","type"]},{kind:"component",type:i2.IonNote,selector:"ion-note",inputs:["color","mode"]},{kind:"component",type:i2.IonSegment,selector:"ion-segment",inputs:["color","disabled","mode","scrollable","selectOnFocus","swipeGesture","value"]},{kind:"component",type:i2.IonSegmentButton,selector:"ion-segment-button",inputs:["disabled","layout","mode","type","value"]},{kind:"component",type:i2.IonTitle,selector:"ion-title",inputs:["color","size"]},{kind:"component",type:i2.IonToolbar,selector:"ion-toolbar",inputs:["color","mode"]},{kind:"directive",type:i2.SelectValueAccessor,selector:"ion-range, ion-select, ion-radio-group, ion-segment, ion-datetime"},{kind:"directive",type:i2.RouterLinkDelegate,selector:":not(a):not(area)[routerLink]",inputs:["routerDirection","routerAnimation"]},{kind:"component",type:CompAvatarRoleImageComponent,selector:"fm-avatar-role-image",inputs:["fmodeChat","role"]},{kind:"component",type:ModalChatVoiceInputComponent,selector:"fm-modal-chat-voice-input",inputs:["fmodeChat","talkMode"]},{kind:"pipe",type:HidexmlPipe,name:"hidexml"}]}),i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.1.0",ngImport:i0,type:CompAvatarTalkComponent,decorators:[{type:Component,args:[{selector:"app-comp-avatar-talk",standalone:!0,imports:[CommonModule,RouterModule,FormsModule,IonicModule,CompAvatarParticleComponent,CompAvatarRoleImageComponent,ModalChatVoiceInputComponent,HidexmlPipe],providers:[FmodeVoiceService,NovaCloudService,ChatService,Diagnostic],template:'<ion-menu #menu contentId="main-content" side="end">\n <ion-header>\n <ion-toolbar>\n <ion-title>资料</ion-title>\n </ion-toolbar>\n </ion-header>\n <ion-content class="ion-padding">\n\n <ion-card style="margin: 0px;">\n <img [src]="avatarRole?.get(\'thumb\')" alt="">\n <ion-card-header>\n <ion-card-subtitle>{{avatarRole?.get(\'tags\')}}</ion-card-subtitle>\n <ion-card-title>{{avatarRole?.get("name")}}</ion-card-title>\n </ion-card-header>\n \n <ion-card-content>\n {{avatarRole?.get("desc")}}\n\n <ion-list [inset]="true" style="margin:0px;">\n \x3c!-- <ion-item>\n <ion-avatar *ngIf="avatarRole?.get(\'thumb\')" aria-hidden="true" slot="start">\n <img [src]="avatarRole?.get(\'thumb\')" />\n </ion-avatar>\n <ion-label>{{avatarRole?.get("name")}}</ion-label>\n </ion-item> --\x3e\n <ion-item lines="none" *ngIf="avatarRole?.get(\'age\')">\n <ion-note slot="start">年龄</ion-note>\n <ion-label>{{avatarRole?.get("age")}}</ion-label>\n </ion-item>\n <ion-item lines="none" *ngIf="avatarRole?.get(\'gender\')">\n <ion-note slot="start">性别</ion-note>\n <ion-label>{{avatarRole?.get("gender")}}</ion-label>\n </ion-item>\n <ion-item lines="none">\n <ion-note slot="start">称号</ion-note>\n <ion-label>{{avatarRole?.get("title")}}</ion-label>\n </ion-item>\n \n <ion-item lines="none">\n <ion-note slot="start">擅长</ion-note>\n <ion-label>{{avatarRole?.get("tags")?.join(\',\')}}</ion-label>\n </ion-item>\n\n </ion-list>\n </ion-card-content>\n </ion-card>\n \n \n \n </ion-content>\n</ion-menu>\n\n<div class="ion-page" id="main-content">\n <ion-header class="ion-no-border">\n <ion-toolbar>\n <ion-buttons slot="start">\n <ion-button (click)="goBack()"> <ion-icon name="chevron-back-outline"></ion-icon> </ion-button>\n </ion-buttons>\n <ion-title>\n <ion-chip *ngIf="avatarRole?.get(\'title\')">{{avatarRole?.get("title")}}</ion-chip>\n </ion-title>\n <ion-buttons slot="end">\n \x3c!-- <ion-button (click)="playTTSTeting()">TTS测试</ion-button> --\x3e\n {{avatarRole?.get("name")}}\n <ion-button (click)="menu.toggle()"> <ion-icon name="ellipsis-horizontal-outline"></ion-icon> </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n\n <ion-segment value="voice">\n <ion-segment-button (click)="chatServ.createChatPanel(avatarRole)" value="chat">\n <ion-label>聊天</ion-label>\n </ion-segment-button>\n <ion-segment-button routerLink="{{\'/avatar/role/\'+avatarRole?.id}}" value="voice">\n <ion-label>语音</ion-label>\n </ion-segment-button>\n </ion-segment>\n\n \x3c!-- 数字形象:动画效果 --\x3e\n <fm-avatar-role-image *ngIf="avatarRole&&fmodeChat" [fmodeChat]="fmodeChat" [role]="avatarRole" #avatar class="avatar"></fm-avatar-role-image>\n \x3c!-- <fm-avatar-role-particle #avatar class="avatar"></fm-avatar-role-particle> --\x3e\n\n \x3c!-- AI回复的最新消息 --\x3e\n <div class="ai-resp-input" #aiRespComp>{{fmodeChat?.latestAIResponse | hidexml}}</div>\n\n <fm-modal-chat-voice-input *ngIf="fmodeChat" [fmodeChat]="fmodeChat"></fm-modal-chat-voice-input>\n\n</div>\n\n',styles:["ion-menu ion-note{color:#ccc;font-weight:700}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.avatar{display:block;width:100%;height:100%}.ai-resp-input{font-size:1rem;color:#fff;position:fixed;top:5vh;max-height:15vh;overflow-y:scroll;padding:0 10px}.user-asr-input{font-size:1rem;color:#fff;position:fixed;bottom:6vh;padding:0 10px}.test-button-group{color:#00f;position:fixed;bottom:20vh}.test-button-group button{padding:10px;margin:10px}\n"]}]}],ctorParameters:function(){return[{type:i1.FmodeVoiceService},{type:i2.Platform},{type:i3.Router},{type:i2.NavController},{type:i3.ActivatedRoute},{type:i4.ChatService},{type:i5.NovaCloudService}]},propDecorators:{avatarComp:[{type:ViewChild,args:["avatar"]}],aiRespComp:[{type:ViewChild,args:["aiRespComp"]}]}});
|
|
9
9
|
var MODULE_PATH_NEED = `6K+l5paH5Lu25piv5pys6aG555uu55qE5LiA6YOo5YiGIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHRoZSBDb21wb25lbnRzIGluIEZtb2RlIEluYy4KICAgIOeJiOadg+aJgOaciSDCqSDmnKrmnaXpo57pqawgwqkg5rGf6KW/6ISR5o6n56eR5oqA5pyJ6ZmQ5YWs5Y+4IENvcHlyaWdodCDCqSBGbW9kZSBUZWNobm9sb2d5IENvLiwgTHRkLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCBSaWdodHMgUmVzZXJ2ZWQuCiAgICDkuKXnpoHlnKjmnKrnu4/mjojmnYPnmoTmg4XlhrXkuIvvvIzpgJrov4fku7vkvZXlqpLku4vlpI3liLbmraTmlofku7YgVW5hdXRob3JpemVkIGNvcHlpbmcgb2YgdGhpcyBmaWxlLCB2aWEgYW55IG1lZGl1bSBpcyBzdHJpY3RseSBwcm9oaWJpdGVkCiAgICDor6Xmlofku7bmmK/kuJPmnInnmoTmnLrlr4bmlofku7YgUHJvcHJpZXRhcnkgYW5kIGNvbmZpZGVudGlhbAogICAKICAgIENvcHlyaWdodCAyMDIxLW5vdyBGbW9kZSBJbmMuIHN1cHBvcnRAZm1vZGUuY24uIDE4NjA3MDA3MDczLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgUEFUSDovaG9tZS9yeWFuL3dvcmtzcGFjZS9ub3ZhL25vdmEtYWRtaW4vZGlzdC9mbW9kZS1uZy9lc20yMDIwL2xpYi9haWdjL2F2YXRhci9jb21wLWF2YXRhci10YWxrL2NvbXAtYXZhdGFyLXRhbGsuY29tcG9uZW50Lm1qcw==`
|
|
10
10
|
|
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
* 保留所有权利 All Rights Reserved.
|
|
6
6
|
* /home/ryan/workspace/nova/nova-admin/dist/fmode-ng/esm2020/lib/aigc/avatar/modal-chat-voice-input/modal-chat-voice-input.component.mjs
|
|
7
7
|
*/
|
|
8
|
-
import{Component,Input}from"@angular/core";import{CommonModule}from"@angular/common";import{ToastController}from"@ionic/angular";import{Router,RouterModule}from"@angular/router";import{IonicModule,Platform}from"@ionic/angular";import{FmodeVoiceService}from"../../voice";import{FmodeChat,ChatService}from"../../service-fmai/service-chat";import{FmodeTTS}from"../../voice/tts";import{NovaCloudService}from"../../../nova-cloud/nova-cloud.service";import*as i0 from"@angular/core";import*as i1 from"@ionic/angular";import*as i2 from"@angular/router";import*as i3 from"../../voice";import*as i4 from"../../../nova-cloud/nova-cloud.service";import*as i5 from"../../service-fmai/service-chat";import*as i6 from"@angular/common";export class ModalChatVoiceInputComponent{constructor(t,o,e,n,i,a){this.platform=t,this.router=o,this.voiceServ=e,this.toastCtrl=n,this.ncloud=i,this.chatServ=a,this.talkMode="click",this.talkTips="点击话筒开始讲话",this.errorText="",this.player=new Audio}ngOnInit(){"press"==this.talkMode&&(this.talkTips="轻触底部开始讲话"),setTimeout((()=>{this.initVoiceSevice(),this.initVoiceASR()}),500)}async initVoiceASR(){this.voiceServ.requestPermission().then((()=>{this.voiceServ.openWithPriviledge(),this.startASRAwake()}))}async startASRAwake(){await this.voiceServ.openWithPriviledge(),new this.voiceServ.webSpeech(this.platform).startRecognition("Nihao | Hello")}playMusic(t){this.player.src=`/assets/avatar/voice/${t}.mp3`,this.player.play()}initVoiceSevice(){this.fmodeChat.userInput=this.voiceServ.resultText,this.voiceServ.requestPermission().then((()=>{this.voiceServ.openWithPriviledge()})),this.voiceServ.onBeforeStartTalk=()=>{this.fmodeChat.playAnimation("listening"),this.playMusic("start-talk")},this.voiceServ.onBeforeCancelTalk=()=>{this.playMusic("interupt-talk"),this.fmodeChat.playAnimation("waiting")},this.voiceServ.onAfterCancelTalk=()=>{this.startASRAwake()},this.voiceServ.onBeforeFinishTalk=()=>{this.fmodeChat.playAnimation("thinking"),this.playMusic("stop-talk")},this.voiceServ.onAfterFinishTalk=()=>{console.log("onAfterFinishTalk"),this.fmodeChat.userInput=this.voiceServ?.resultText,this.sendMessage(),this.startASRAwake()}}async sendMessage(){if(!this.fmodeChat.userInput){return this.errorText="内容不能为空",void(await this.toastCtrl.create({message:this.errorText,position:"top",icon:"alert",color:"warning-circle",duration:1e3})).present()}this.fmodeChat?.sendMessage(this.voiceServ.resultText,null,(t=>{let o=t.content;this.playTTS(o),this.fmodeChat.playAnimation("talking"),setTimeout((()=>{this.fmodeChat.playAnimation("waiting")}),6e3)})),this.fmodeChat.userInput="",this.fmodeChat.userImage=""}async initTTS(){let t=await this.ncloud.apig("voice/voice/tts/token",{company:localStorage.getItem("company")});if(console.log(t),t?.token){let o=new FmodeTTS(t);this.tts=o}}async playTTS(t){if(await this.initTTS(),console.log(this.tts),this.tts)try{await this.tts.speakAsync(t)}catch(t){console.error(t)}}playTTSTeting(){this.playTTS('<speak xmlns="http://www.w3.org/2001/10/synthesis" xmlns:mstts="http://www.w3.org/2001/mstts" xmlns:emo="http://www.w3.org/2009/10/emotionml" version="1.0" xml:lang="zh-CN">\n <voice name="zh-CN-XiaoxiaoNeural"><mstts:express-as style="angry">”好没意思的话!去不去,关我什么事儿?又没叫你替我解闷儿,还许你<mstts:ttsbreak strength="none" />从此<prosody contour="(24%, +49%) (59%, -2%)">不</prosody><prosody rate="-15.00%" contour="(24%, +49%) (59%, -2%)">理</prosody><prosody contour="(24%, +49%) (59%, -2%)">我呢</prosody>!”</mstts:express-as></voice>\n </speak>')}testTTS(t){console.log(t),t=t||"你好呀,我是飞马小智!很高兴为您介绍脑控科技的发展历程。我们成立于2019年",new this.voiceServ.webSpeech(this.platform).speak(t)}testXunfeiTTS(){}}ModalChatVoiceInputComponent.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.1.0",ngImport:i0,type:ModalChatVoiceInputComponent,deps:[{token:i1.Platform},{token:i2.Router},{token:i3.FmodeVoiceService},{token:i1.ToastController},{token:i4.NovaCloudService},{token:i5.ChatService}],target:i0.ɵɵFactoryTarget.Component}),ModalChatVoiceInputComponent.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.1.0",type:ModalChatVoiceInputComponent,isStandalone:!0,selector:"fm-modal-chat-voice-input",inputs:{fmodeChat:"fmodeChat",talkMode:"talkMode"},ngImport:i0,template:' \n <ng-container *ngIf="fmodeChat">\n\n \x3c!-- 用户输入 提示区域 --\x3e\n <div class="user-asr-input" style="text-align: center;" *ngIf="!fmodeChat?.userInput && voiceServ.btnStatus!=\'OPEN\'">{{talkTips}}</div>\n <div class="user-asr-input">{{fmodeChat?.userInput}}</div>\n \n \x3c!-- 测试按钮 --\x3e\n <div class="test-button-group" *ngIf="false">\n <button class="button-record" (click)="voiceServ.toggleRecord()">开始录制 {{voiceServ.connStatus}} {{voiceServ.btnStatus}}</button>\n <br>\n <button class="button-record" (click)="voiceServ.playRecord()">播放录制结果</button>\n <br>\n <button class="button-record" (click)="voiceServ.playBuffers()">播放Buffers结果</button>\n <button (click)="testTTS()">测试TTS纯WEB</button>\n <button (click)="startASR()">测试ASR</button> \n <button (click)="testXunfeiTTS()">测试合成</button> \n </div>\n\n \n \n \x3c!-- 交互按钮 --\x3e\n <ion-fab slot="fixed" horizontal="center" vertical="bottom">\n <ng-container *ngIf="talkMode==\'click\'">\n \x3c!-- 默认按钮:开始讲话 --\x3e\n <ion-fab-button color="primary" closeIcon="checkmark" (click)="voiceServ.toggleRecord()">\n <ion-icon name="mic-outline"></ion-icon>\n </ion-fab-button>\n\n \x3c!-- 讲话中:取消发送 --\x3e\n <ion-fab-list side="end">\n <ion-fab-button [class]="\'loading\'" (click)="voiceServ.cancelTalk()">\n <ion-icon name="pause-outline"></ion-icon>\n </ion-fab-button>\n </ion-fab-list>\n </ng-container>\n \n <ng-container *ngIf="talkMode==\'press\'">\n <ion-fab-button color="primary" closeIcon="mic-outline" (touchstart)="voiceServ.toggleRecord()" (touchend)="voiceServ.cancelTalk()">\n <ion-icon name="mic-outline"></ion-icon>\n </ion-fab-button>\n </ng-container>\n </ion-fab>\n\n\n \x3c!-- 音频波动 --\x3e\n <div class="record-wave">\n </div>\n</ng-container>\n',styles:['ion-fab{margin-bottom:15vh}.fab-button-close-active:before{content:"";position:absolute;top:-5px;left:-5px;width:66px;height:66px;border-radius:50%;border:5px solid #fff;border-top-color:transparent;animation:spin 2s ease-in-out infinite;animation-fill-mode:both;animation-play-state:running}.record-wave{position:fixed;bottom:0;width:100vw;height:6vh}\n'],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i6.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:IonicModule},{kind:"component",type:i1.IonFab,selector:"ion-fab",inputs:["activated","edge","horizontal","vertical"]},{kind:"component",type:i1.IonFabButton,selector:"ion-fab-button",inputs:["activated","closeIcon","color","disabled","download","href","mode","rel","routerAnimation","routerDirection","show","size","target","translucent","type"]},{kind:"component",type:i1.IonFabList,selector:"ion-fab-list",inputs:["activated","side"]},{kind:"component",type:i1.IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"ngmodule",type:RouterModule}]}),i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.1.0",ngImport:i0,type:ModalChatVoiceInputComponent,decorators:[{type:Component,args:[{selector:"fm-modal-chat-voice-input",standalone:!0,imports:[CommonModule,IonicModule,RouterModule],template:' \n <ng-container *ngIf="fmodeChat">\n\n \x3c!-- 用户输入 提示区域 --\x3e\n <div class="user-asr-input" style="text-align: center;" *ngIf="!fmodeChat?.userInput && voiceServ.btnStatus!=\'OPEN\'">{{talkTips}}</div>\n <div class="user-asr-input">{{fmodeChat?.userInput}}</div>\n \n \x3c!-- 测试按钮 --\x3e\n <div class="test-button-group" *ngIf="false">\n <button class="button-record" (click)="voiceServ.toggleRecord()">开始录制 {{voiceServ.connStatus}} {{voiceServ.btnStatus}}</button>\n <br>\n <button class="button-record" (click)="voiceServ.playRecord()">播放录制结果</button>\n <br>\n <button class="button-record" (click)="voiceServ.playBuffers()">播放Buffers结果</button>\n <button (click)="testTTS()">测试TTS纯WEB</button>\n <button (click)="startASR()">测试ASR</button> \n <button (click)="testXunfeiTTS()">测试合成</button> \n </div>\n\n \n \n \x3c!-- 交互按钮 --\x3e\n <ion-fab slot="fixed" horizontal="center" vertical="bottom">\n <ng-container *ngIf="talkMode==\'click\'">\n \x3c!-- 默认按钮:开始讲话 --\x3e\n <ion-fab-button color="primary" closeIcon="checkmark" (click)="voiceServ.toggleRecord()">\n <ion-icon name="mic-outline"></ion-icon>\n </ion-fab-button>\n\n \x3c!-- 讲话中:取消发送 --\x3e\n <ion-fab-list side="end">\n <ion-fab-button [class]="\'loading\'" (click)="voiceServ.cancelTalk()">\n <ion-icon name="pause-outline"></ion-icon>\n </ion-fab-button>\n </ion-fab-list>\n </ng-container>\n \n <ng-container *ngIf="talkMode==\'press\'">\n <ion-fab-button color="primary" closeIcon="mic-outline" (touchstart)="voiceServ.toggleRecord()" (touchend)="voiceServ.cancelTalk()">\n <ion-icon name="mic-outline"></ion-icon>\n </ion-fab-button>\n </ng-container>\n </ion-fab>\n\n\n \x3c!-- 音频波动 --\x3e\n <div class="record-wave">\n </div>\n</ng-container>\n',styles:['ion-fab{margin-bottom:15vh}.fab-button-close-active:before{content:"";position:absolute;top:-5px;left:-5px;width:66px;height:66px;border-radius:50%;border:5px solid #fff;border-top-color:transparent;animation:spin 2s ease-in-out infinite;animation-fill-mode:both;animation-play-state:running}.record-wave{position:fixed;bottom:0;width:100vw;height:6vh}\n']}]}],ctorParameters:function(){return[{type:i1.Platform},{type:i2.Router},{type:i3.FmodeVoiceService},{type:i1.ToastController},{type:i4.NovaCloudService},{type:i5.ChatService}]},propDecorators:{fmodeChat:[{type:Input}],talkMode:[{type:Input}]}});
|
|
8
|
+
import{Component,Input}from"@angular/core";import{CommonModule}from"@angular/common";import{ToastController}from"@ionic/angular";import{Router,RouterModule}from"@angular/router";import{IonicModule,Platform}from"@ionic/angular";import{FmodeVoiceService}from"../../voice";import{FmodeChat,ChatService}from"../../service-fmai/service-chat";import{FmodeTTS}from"../../voice/tts";import{NovaCloudService}from"../../../nova-cloud/nova-cloud.service";import*as i0 from"@angular/core";import*as i1 from"@ionic/angular";import*as i2 from"@angular/router";import*as i3 from"../../voice";import*as i4 from"../../../nova-cloud/nova-cloud.service";import*as i5 from"../../service-fmai/service-chat";import*as i6 from"@angular/common";export class ModalChatVoiceInputComponent{constructor(t,o,e,n,i,a){this.platform=t,this.router=o,this.voiceServ=e,this.toastCtrl=n,this.ncloud=i,this.chatServ=a,this.talkMode="click",this.talkTips="点击话筒开始讲话",this.errorText="",this.player=new Audio}ngOnInit(){"press"==this.talkMode&&(this.talkTips="轻触底部开始讲话"),setTimeout((()=>{this.initVoiceSevice(),this.initVoiceASR()}),500)}async initVoiceASR(){this.voiceServ.requestPermission().then((()=>{this.voiceServ.openWithPriviledge(),this.startASRAwake()}))}async startASRAwake(){await this.voiceServ.openWithPriviledge(),new this.voiceServ.webSpeech(this.platform).startRecognition("Nihao | Hello")}playMusic(t){this.player.src=`/assets/avatar/voice/${t}.mp3`,this.player.play()}initVoiceSevice(){this.fmodeChat.userInput=this.voiceServ.resultText,this.voiceServ.requestPermission().then((()=>{this.voiceServ.openWithPriviledge()})),this.voiceServ.onBeforeStartTalk=()=>{this.fmodeChat.playAnimation("listening"),this.playMusic("start-talk")},this.voiceServ.onBeforeCancelTalk=()=>{this.playMusic("interupt-talk"),this.fmodeChat.playAnimation("waiting")},this.voiceServ.onAfterCancelTalk=()=>{this.startASRAwake()},this.voiceServ.onBeforeFinishTalk=()=>{this.fmodeChat.playAnimation("thinking"),this.playMusic("stop-talk")},this.voiceServ.onAfterFinishTalk=()=>{console.log("onAfterFinishTalk"),this.fmodeChat.userInput=this.voiceServ?.resultText,this.sendMessage(),this.startASRAwake()}}async sendMessage(){if(!this.fmodeChat.userInput){return this.errorText="内容不能为空",void(await this.toastCtrl.create({message:this.errorText,position:"top",icon:"alert",color:"warning-circle",duration:1e3})).present()}this.fmodeChat?.sendMessage(this.voiceServ.resultText,null,(t=>{let o=t.content;this.playTTS(o),this.fmodeChat.playAnimation("talking"),setTimeout((()=>{this.fmodeChat.playAnimation("waiting")}),6e3)})),this.fmodeChat.userInput="",this.fmodeChat.userImage=""}async initTTS(){let t=await this.ncloud.apig("voice/voice/tts/token",{company:localStorage.getItem("company")});if(console.log(t),t?.token){let o=new FmodeTTS(t);this.tts=o}}async playTTS(t){if(await this.initTTS(),console.log(this.tts),this.tts)try{await this.tts.speakAsync(t)}catch(t){console.error(t)}}playTTSTeting(){this.playTTS('<speak xmlns="http://www.w3.org/2001/10/synthesis" xmlns:mstts="http://www.w3.org/2001/mstts" xmlns:emo="http://www.w3.org/2009/10/emotionml" version="1.0" xml:lang="zh-CN">\n <voice name="zh-CN-XiaoxiaoNeural"><mstts:express-as style="angry">”好没意思的话!去不去,关我什么事儿?又没叫你替我解闷儿,还许你<mstts:ttsbreak strength="none" />从此<prosody contour="(24%, +49%) (59%, -2%)">不</prosody><prosody rate="-15.00%" contour="(24%, +49%) (59%, -2%)">理</prosody><prosody contour="(24%, +49%) (59%, -2%)">我呢</prosody>!”</mstts:express-as></voice>\n </speak>')}testTTS(t){console.log(t),t=t||"你好呀,我是飞马小智!很高兴为您介绍脑控科技的发展历程。我们成立于2019年",new this.voiceServ.webSpeech(this.platform).speak(t)}testXunfeiTTS(){}}ModalChatVoiceInputComponent.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.1.0",ngImport:i0,type:ModalChatVoiceInputComponent,deps:[{token:i1.Platform},{token:i2.Router},{token:i3.FmodeVoiceService},{token:i1.ToastController},{token:i4.NovaCloudService},{token:i5.ChatService}],target:i0.ɵɵFactoryTarget.Component}),ModalChatVoiceInputComponent.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.1.0",type:ModalChatVoiceInputComponent,isStandalone:!0,selector:"fm-modal-chat-voice-input",inputs:{fmodeChat:"fmodeChat",talkMode:"talkMode"},providers:[FmodeVoiceService],ngImport:i0,template:' \n <ng-container *ngIf="fmodeChat">\n\n \x3c!-- 用户输入 提示区域 --\x3e\n <div class="user-asr-input" style="text-align: center;" *ngIf="!fmodeChat?.userInput && voiceServ.btnStatus!=\'OPEN\'">{{talkTips}}</div>\n <div class="user-asr-input">{{fmodeChat?.userInput}}</div>\n \n \x3c!-- 测试按钮 --\x3e\n <div class="test-button-group" *ngIf="false">\n <button class="button-record" (click)="voiceServ.toggleRecord()">开始录制 {{voiceServ.connStatus}} {{voiceServ.btnStatus}}</button>\n <br>\n <button class="button-record" (click)="voiceServ.playRecord()">播放录制结果</button>\n <br>\n <button class="button-record" (click)="voiceServ.playBuffers()">播放Buffers结果</button>\n <button (click)="testTTS()">测试TTS纯WEB</button>\n <button (click)="startASR()">测试ASR</button> \n <button (click)="testXunfeiTTS()">测试合成</button> \n </div>\n\n \n \n \x3c!-- 交互按钮 --\x3e\n <ion-fab slot="fixed" horizontal="center" vertical="bottom">\n <ng-container *ngIf="talkMode==\'click\'">\n \x3c!-- 默认按钮:开始讲话 --\x3e\n <ion-fab-button color="primary" closeIcon="checkmark" (click)="voiceServ.toggleRecord()">\n <ion-icon name="mic-outline"></ion-icon>\n </ion-fab-button>\n\n \x3c!-- 讲话中:取消发送 --\x3e\n <ion-fab-list side="end">\n <ion-fab-button [class]="\'loading\'" (click)="voiceServ.cancelTalk()">\n <ion-icon name="pause-outline"></ion-icon>\n </ion-fab-button>\n </ion-fab-list>\n </ng-container>\n \n <ng-container *ngIf="talkMode==\'press\'">\n <ion-fab-button color="primary" closeIcon="mic-outline" (touchstart)="voiceServ.toggleRecord()" (touchend)="voiceServ.cancelTalk()">\n <ion-icon name="mic-outline"></ion-icon>\n </ion-fab-button>\n </ng-container>\n </ion-fab>\n\n\n \x3c!-- 音频波动 --\x3e\n <div class="record-wave">\n </div>\n</ng-container>\n',styles:['ion-fab{margin-bottom:15vh}.fab-button-close-active:before{content:"";position:absolute;top:-5px;left:-5px;width:66px;height:66px;border-radius:50%;border:5px solid #fff;border-top-color:transparent;animation:spin 2s ease-in-out infinite;animation-fill-mode:both;animation-play-state:running}.record-wave{position:fixed;bottom:0;width:100vw;height:6vh}\n'],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i6.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:IonicModule},{kind:"component",type:i1.IonFab,selector:"ion-fab",inputs:["activated","edge","horizontal","vertical"]},{kind:"component",type:i1.IonFabButton,selector:"ion-fab-button",inputs:["activated","closeIcon","color","disabled","download","href","mode","rel","routerAnimation","routerDirection","show","size","target","translucent","type"]},{kind:"component",type:i1.IonFabList,selector:"ion-fab-list",inputs:["activated","side"]},{kind:"component",type:i1.IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"ngmodule",type:RouterModule}]}),i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.1.0",ngImport:i0,type:ModalChatVoiceInputComponent,decorators:[{type:Component,args:[{selector:"fm-modal-chat-voice-input",standalone:!0,imports:[CommonModule,IonicModule,RouterModule],providers:[FmodeVoiceService],template:' \n <ng-container *ngIf="fmodeChat">\n\n \x3c!-- 用户输入 提示区域 --\x3e\n <div class="user-asr-input" style="text-align: center;" *ngIf="!fmodeChat?.userInput && voiceServ.btnStatus!=\'OPEN\'">{{talkTips}}</div>\n <div class="user-asr-input">{{fmodeChat?.userInput}}</div>\n \n \x3c!-- 测试按钮 --\x3e\n <div class="test-button-group" *ngIf="false">\n <button class="button-record" (click)="voiceServ.toggleRecord()">开始录制 {{voiceServ.connStatus}} {{voiceServ.btnStatus}}</button>\n <br>\n <button class="button-record" (click)="voiceServ.playRecord()">播放录制结果</button>\n <br>\n <button class="button-record" (click)="voiceServ.playBuffers()">播放Buffers结果</button>\n <button (click)="testTTS()">测试TTS纯WEB</button>\n <button (click)="startASR()">测试ASR</button> \n <button (click)="testXunfeiTTS()">测试合成</button> \n </div>\n\n \n \n \x3c!-- 交互按钮 --\x3e\n <ion-fab slot="fixed" horizontal="center" vertical="bottom">\n <ng-container *ngIf="talkMode==\'click\'">\n \x3c!-- 默认按钮:开始讲话 --\x3e\n <ion-fab-button color="primary" closeIcon="checkmark" (click)="voiceServ.toggleRecord()">\n <ion-icon name="mic-outline"></ion-icon>\n </ion-fab-button>\n\n \x3c!-- 讲话中:取消发送 --\x3e\n <ion-fab-list side="end">\n <ion-fab-button [class]="\'loading\'" (click)="voiceServ.cancelTalk()">\n <ion-icon name="pause-outline"></ion-icon>\n </ion-fab-button>\n </ion-fab-list>\n </ng-container>\n \n <ng-container *ngIf="talkMode==\'press\'">\n <ion-fab-button color="primary" closeIcon="mic-outline" (touchstart)="voiceServ.toggleRecord()" (touchend)="voiceServ.cancelTalk()">\n <ion-icon name="mic-outline"></ion-icon>\n </ion-fab-button>\n </ng-container>\n </ion-fab>\n\n\n \x3c!-- 音频波动 --\x3e\n <div class="record-wave">\n </div>\n</ng-container>\n',styles:['ion-fab{margin-bottom:15vh}.fab-button-close-active:before{content:"";position:absolute;top:-5px;left:-5px;width:66px;height:66px;border-radius:50%;border:5px solid #fff;border-top-color:transparent;animation:spin 2s ease-in-out infinite;animation-fill-mode:both;animation-play-state:running}.record-wave{position:fixed;bottom:0;width:100vw;height:6vh}\n']}]}],ctorParameters:function(){return[{type:i1.Platform},{type:i2.Router},{type:i3.FmodeVoiceService},{type:i1.ToastController},{type:i4.NovaCloudService},{type:i5.ChatService}]},propDecorators:{fmodeChat:[{type:Input}],talkMode:[{type:Input}]}});
|
|
9
9
|
var MODULE_PATH_NEED = `6K+l5paH5Lu25piv5pys6aG555uu55qE5LiA6YOo5YiGIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHRoZSBDb21wb25lbnRzIGluIEZtb2RlIEluYy4KICAgIOeJiOadg+aJgOaciSDCqSDmnKrmnaXpo57pqawgwqkg5rGf6KW/6ISR5o6n56eR5oqA5pyJ6ZmQ5YWs5Y+4IENvcHlyaWdodCDCqSBGbW9kZSBUZWNobm9sb2d5IENvLiwgTHRkLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCBSaWdodHMgUmVzZXJ2ZWQuCiAgICDkuKXnpoHlnKjmnKrnu4/mjojmnYPnmoTmg4XlhrXkuIvvvIzpgJrov4fku7vkvZXlqpLku4vlpI3liLbmraTmlofku7YgVW5hdXRob3JpemVkIGNvcHlpbmcgb2YgdGhpcyBmaWxlLCB2aWEgYW55IG1lZGl1bSBpcyBzdHJpY3RseSBwcm9oaWJpdGVkCiAgICDor6Xmlofku7bmmK/kuJPmnInnmoTmnLrlr4bmlofku7YgUHJvcHJpZXRhcnkgYW5kIGNvbmZpZGVudGlhbAogICAKICAgIENvcHlyaWdodCAyMDIxLW5vdyBGbW9kZSBJbmMuIHN1cHBvcnRAZm1vZGUuY24uIDE4NjA3MDA3MDczLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgUEFUSDovaG9tZS9yeWFuL3dvcmtzcGFjZS9ub3ZhL25vdmEtYWRtaW4vZGlzdC9mbW9kZS1uZy9lc20yMDIwL2xpYi9haWdjL2F2YXRhci9tb2RhbC1jaGF0LXZvaWNlLWlucHV0L21vZGFsLWNoYXQtdm9pY2UtaW5wdXQuY29tcG9uZW50Lm1qcw==`
|
|
10
10
|
|