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,且使用按优先级播放人物动作,故音频可能会出现与动作不一致的情况