live2d-motionsync
Version:
Live2D Motionsync, a lip-sync library for Live2D models.
179 lines (171 loc) • 5.43 kB
JavaScript
var h = Object.defineProperty;
var d = (s, t, e) => t in s ? h(s, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : s[t] = e;
var o = (s, t, e) => d(s, typeof t != "symbol" ? t + "" : t, e);
import { C as r, M as f, a as p, f as _, c as y } from "./fallback.motionsync3-1oooNFSa.js";
const m = `/**
* Copyright(c) Live2D Inc. All rights reserved.
*
* Use of this source code is governed by the Live2D Open Software license
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
*/
class LAppAudioWorkletProcessor extends AudioWorkletProcessor {
constructor() {
super();
this.useChannel = 0;
}
process(inputs, outputs, parameters) {
const channel = this.useChannel % inputs[0].length;
const input = inputs[0][channel];
if (input == undefined || input == null) {
return true;
}
// 後ろに追加する
const audioBuffer = Float32Array.from([...input]);
this.port.postMessage({
eventType: "data",
audioBuffer: audioBuffer,
});
let inputArray = inputs[0];
let output = outputs[0];
for (let currentChannel = 0; currentChannel < inputArray.length; ++currentChannel) {
let inputChannel = inputArray[currentChannel];
let outputChannel = output[currentChannel];
for (let i = 0; i < inputChannel.length; ++i){
outputChannel[i] = inputChannel[i];
}
}
return true;
}
}
registerProcessor('lappaudioworkletprocessor', LAppAudioWorkletProcessor);
`, a = 48e3;
class g {
constructor(t) {
o(this, "_motionSync", null);
o(this, "_internalModel");
o(this, "_model");
o(this, "_context", null);
o(this, "_source", null);
o(this, "_buffer", null);
this._internalModel = t, this._model = t.coreModel, r.startUp(new f()), r.initialize();
}
async play(t) {
(this._source || this._context) && this.reset();
const e = t.getAudioTracks();
if (e.length == 0) {
p("没有找到音频轨道.");
return;
}
const n = 48e3, i = 30, c = 2;
this._buffer = new M(
Math.trunc(n / i * c)
), this._context = new AudioContext({ sampleRate: n }), this._source = this._context.createMediaStreamSource(
new MediaStream([e[0]])
);
const l = URL.createObjectURL(
new Blob([m], {
type: "application/javascript"
})
);
await this._context.audioWorklet.addModule(l);
const u = new AudioWorkletNode(
this._context,
"lappaudioworkletprocessor"
);
this._source.connect(u), u.port.onmessage = this.onMessage.bind(this);
}
async reset() {
this._source && (this._source.disconnect(), this._source = null), this._context && (this._context.close(), this._context = null), this._buffer = null, this.resetMouthStatus();
}
resetMouthStatus() {
try {
if (!this._motionSync) return;
const t = this._motionSync.getData().getSetting(0);
if (!t) return;
const e = t.cubismParameterList;
if (!e) return;
const n = e._ptr.map(
(i) => i.parameterIndex
);
for (const i of n)
this._model.setParameterValueByIndex(i, 0);
} catch (t) {
console.error(t);
}
}
pop() {
if (!this._buffer)
return;
const t = this._buffer.toVector();
return this._buffer.clear(), t;
}
onMessage(t) {
const e = t.data;
if (e.eventType === "data" && e.audioBuffer)
for (let n = 0; n < e.audioBuffer.length; n++)
this._buffer.addLast(e.audioBuffer[n]);
}
updateMotionSync() {
const t = performance.now() / 1e3, e = this.pop();
e && (this._motionSync.setSoundBuffer(0, e, 0), this._motionSync.updateParameters(this._model, t));
}
modelUpdateWithMotionSync() {
if (!this._motionSync) return;
const e = this._internalModel, n = e.motionManager.update;
e.motionManager.update = (...i) => {
n.apply(this._internalModel.motionManager, i), this.updateMotionSync();
};
}
loadMotionSync(t, e = a) {
if (t == null || t.byteLength == 0) {
console.warn("Failed to loadMotionSync().");
return;
}
this._motionSync = r.create(
this._model,
t,
t.byteLength,
e
), this.modelUpdateWithMotionSync();
}
async loadDefaultMotionSync(t = a) {
const n = await new Blob([_], { type: "application/json" }).arrayBuffer();
this.loadMotionSync(n, t);
}
async loadMotionSyncFromUrl(t, e = a) {
try {
const i = await (await fetch(t)).arrayBuffer();
this.loadMotionSync(i, e);
} catch {
console.warn("Failed to loadMotionSync(). Use default fallback."), await this.loadDefaultMotionSync(e);
}
}
}
class M {
constructor(t) {
o(this, "_buffer");
o(this, "_size");
o(this, "_head");
this._buffer = new Float32Array(t), this._size = 0, this._head = 0;
}
get size() {
return this._size;
}
addLast(t) {
this._buffer[this._head] = t, this._size = Math.min(this._size + 1, this._buffer.length), this._head++, this._head >= this._buffer.length && (this._head = 0);
}
toVector() {
const t = new y(this._size);
let e = this._head - this._size;
e < 0 && (e += this._buffer.length);
for (let n = 0; n < this._size; n++)
t.pushBack(this._buffer[e]), e++, e >= this._buffer.length && (e = 0);
return t;
}
clear() {
this._size = 0, this._head = 0;
}
}
export {
g as MotionSync
};