web版看板娘專案更新點選語音功能
阿新 • • 發佈:2021-02-10
技術標籤:Live2D網頁看板娘javascripttypescript
web版看板娘專案更新點選語音功能
按載入流程來看,所有的音訊都事先載入完畢的,應該不會出現聲音延遲現象
但這樣也導致頁面初次載入時會比原來慢
功能修改方法
-
找到 Samples\TypeScript\Demo\src\lappmodel.ts 檔案
-
在類的屬性中新增Audio物件集合,並初始化
class LAppModel{ ...省略... //構造方法 public constructor() { ...省略... //儲存音訊物件的map集合 this._motionSounds = new Map(); ...省略... } ...省略... _motionSounds :Map<string,any>;//儲存adido物件的集合 }
3.在preLoadMotionGroup方法裡新建audio物件並加入集合。
public preLoadMotionGroup(group: string): void { for (let i = 0; i < this._modelSetting.getMotionCount(group); i++) { const motionFileName = this._modelSetting.getMotionFileName(group, i); const soundFileName = this._modelSetting.getMotionSoundFileName(group,i); const fileName = `${this._modelHomeDir}/${motionFileName}`; console.log("-------preLoadMotionGroup------當前正在載入動作檔案:【---"+fileName+"----】") console.log("-------preLoadMotionGroup------當前正在載入聲音檔案:【---"+this._modelHomeDir+soundFileName+"----】") // ex) idle_0 const name = `${group}_${i}`; if (this._debugMode) { LAppPal.printMessage( `[APP]load motion: ${motionFileName} => [${name}]` ); } //載入動作檔案 fetch(`${this._modelHomeDir}/${motionFileName}`) .then(response => response.arrayBuffer()) .then(arrayBuffer => { const tmpMotion: CubismMotion = this.loadMotion( arrayBuffer, arrayBuffer.byteLength, name ); let fadeTime = this._modelSetting.getMotionFadeInTimeValue(group, i); if (fadeTime >= 0.0) { tmpMotion.setFadeInTime(fadeTime); } fadeTime = this._modelSetting.getMotionFadeOutTimeValue(group, i); if (fadeTime >= 0.0) { tmpMotion.setFadeOutTime(fadeTime); } tmpMotion.setEffectIds(this._eyeBlinkIds, this._lipSyncIds); if (this._motions.getValue(name) != null) { ACubismMotion.delete(this._motions.getValue(name)); } this._motions.setValue(name, tmpMotion); //新增motion對應的聲音檔案的到map集合 if(this._motionSounds.get(name)!=null){ this._motionSounds.delete(name); } let pathOfAudio = this._modelHomeDir+soundFileName; if(pathOfAudio != this._modelHomeDir){ //請求音訊檔案 fetch(pathOfAudio).then(response => response.blob()).then( audioBlob =>{ let blobUrl = URL.createObjectURL(audioBlob) let audio = new Audio(blobUrl) this._motionSounds.set(name,audio); } ); } this._motionCount++; if (this._motionCount >= this._allMotionCount) { this._state = LoadStep.LoadTexture; // 全てのモーションを停止する this._motionManager.stopAllMotions(); this._updating = false; this._initialized = true; this.createRenderer(); this.setupTextures(); this.getRenderer().startUp(gl); } }); } }
4.在 startMotion 物件中取出相應物件並播放
public startMotion( group: string, no: number, priority: number, onFinishedMotionHandler?: FinishedMotionCallback ): CubismMotionQueueEntryHandle { if (priority == LAppDefine.PriorityForce) { this._motionManager.setReservePriority(priority); } else if (!this._motionManager.reserveMotion(priority)) { if (this._debugMode) { LAppPal.printMessage("[APP]can't start motion."); } return InvalidMotionQueueEntryHandleValue; } const motionFileName = this._modelSetting.getMotionFileName(group, no); const fileName = `${this._modelHomeDir}/${motionFileName}`; const soundFileName = this._modelSetting.getMotionSoundFileName(group, no); const fileName1 = `${this._modelHomeDir}/${soundFileName}`; console.log("-------startMotion------當前正在載入音訊檔案:【---"+fileName1+"----】") // ex) idle_0 const name = `${group}_${no}`; //從motions Map裡面取出motions物件,故想載入對應的聲音檔案也同樣需要將聲音物件儲存到map裡面 let motion: CubismMotion = this._motions.getValue(name) as CubismMotion; let audio = this._motionSounds.get(name); if(audio!=null){ if(audio.paused==false) { audio.load(); } } let autoDelete = false; //如果motion物件為空,則重新載入檔案,生成物件 if (motion == null) { fetch(`${this._modelHomeDir}/${motionFileName}`) .then(response => response.arrayBuffer()) .then(arrayBuffer => { motion = this.loadMotion( arrayBuffer, arrayBuffer.byteLength, null, onFinishedMotionHandler ); let fadeTime: number = this._modelSetting.getMotionFadeInTimeValue( group, no ); if (fadeTime >= 0.0) { motion.setFadeInTime(fadeTime); } fadeTime = this._modelSetting.getMotionFadeOutTimeValue(group, no); if (fadeTime >= 0.0) { motion.setFadeOutTime(fadeTime); } motion.setEffectIds(this._eyeBlinkIds, this._lipSyncIds); autoDelete = true; // 終了時にメモリから削除 }); } else { //motion物件不為空,關閉當前的motion動作並重新載入正在播放的聲音 motion.setFinishedMotionHandler(onFinishedMotionHandler); if(audio!=null){ audio.load(); } } if(audio!=null){ audio.play(); }else{ console.log("當前動作沒有語音"); } if (this._debugMode) { LAppPal.printMessage(`[APP]start motion: [${group}_${no}`); } //按優先順序呼叫motion return this._motionManager.startMotionPriority( motion, autoDelete, priority ); }
5.模型檔案的修改【*.moc3.json】
{
"Version": 3,
"FileReferences": {
"Moc": "l2d01.u.moc3",
"Textures": [
"textures/texture_00.png"
],
"Physics": "l2d01.u.physics3.json",
"Motions": {
"Idle":[
{
"File":"motions/Mgirl10_tingge.motion3.json",
##在這裡新增音訊檔案的相對路徑
},
{"File":"Mgirl10_stand_c.motion3.json"}
],
"TapBody":[
{
"File":"motions/Mgirl10_haixiu_a.motion3.json",
"Sound": "voice/03.wav" ##在這裡新增音訊檔案的相對路徑
},
{
"File":"motions/Mgirl10_shihao_a.motion3.json",
"Sound": "voice/02.wav"
}
],
"TapHead":[
{"File":"motions/Mgirl10_motouyihuo.motion3.json"},
{"File":"motions/Mgirl10_zeguai_a.motion3.json"}
]
}
}
}
注意事項
-
由於原生的web sdk並未提供播放聲音相關的api,且使用按優先順序播放人物動作,故音訊可能會出現與動作不一致的情況