Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Live2D with Lipsync (using audio file/link) #122

Open
wants to merge 47 commits into
base: master
Choose a base branch
from

Conversation

RaSan147
Copy link

Solving issues mentioned in #117

Copy link
Owner

@guansss guansss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks again for the PR! I think we are getting close but some changes are still needed as described in the comments.

I noticed that some of the code is not properly linted. After making changes to the code, please run npm run lint:fix to automatically fix the linting errors, and address any remaining errors manually. (except for the triple slash reference errors, which I will fix later)

After you finish theses changes, I'll be adding some tests to make sure this feature works as expected.

src/cubism-common/MotionManager.ts Outdated Show resolved Hide resolved
src/cubism-common/MotionManager.ts Outdated Show resolved Hide resolved
src/cubism-common/SoundManager.ts Outdated Show resolved Hide resolved
@@ -248,6 +257,11 @@ export class Cubism4InternalModel extends InternalModel {
this.coreModel.addParameterValueById(this.idParamBodyAngleX, this.focusController.x * 10); // -10 ~ 10
}


updateFacialEmotion(mouthForm: number) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could a name like setMouthForm be better? Because it's not changing the entire facial expression but only the mouth form. Also, update implies that this function will do some computations other than setting the value, so set will be more suitable here.

As a new API, this method should also be added to Cubism2InternalModel for consistency.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll test and run on the cubism 2 (well the issue is i tried and failed to set up the development env on my local system, but the github action worked fine even the codespace failed, i know my skill issue) So probably won't be able to run the npm lint (will try)

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The development guide in DEVELOPMENT.md was a bit messy and I've rewritten it, now I guess there won't be problems if you follow the steps (if there is please let me know!)

It's not your issue but the codespaces being problematic with submodules, browser testing etc. So better run it locally.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot 😭

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided to remove this method because setting this param is pretty straightforward and isn't really worth adding a method for it.

RaSan147 and others added 7 commits December 14, 2023 19:05
Co-authored-by: Guan <46285865+guansss@users.noreply.github.com>
Co-authored-by: Guan <46285865+guansss@users.noreply.github.com>
Co-authored-by: Guan <46285865+guansss@users.noreply.github.com>
also remove cache buster and autoplay
@RaSan147
Copy link
Author

RaSan147 commented Mar 7, 2024

Yeah, lets give them options (and specify in the docs) and let them pick

@xumx
Copy link

xumx commented Mar 11, 2024

A new behavior is breaking some existing tests, that is, when a motion with a sound is playing, the model does not allow another motion to start even if it has a higher priority, because there's already a playing audio.

I tried removing that audio check but just got some other errors. Anyway, I think this is mainly because we didn't have a thorough design for how to reconcile motions with sounds (model.motion()) and lipsync audios (model.speak()).

So here we go! My intuitive idea is, motions shouldn't be disallowed to play because of a playing audio, and motion sounds should have a higher priority than lipsync audios. So if a motion is going to play and it has a sound, the current lipsync audio should be canceled; and if it doesn't have a sound, the lipsync audio should keep playing along with the motion.

Could you share your thoughts on this?

Why can't both speaking audio and motion sound be played together?

@guansss
Copy link
Owner

guansss commented Mar 11, 2024

@xumx Yeah that's exactly what my latest comment was talking about.

@guansss
Copy link
Owner

guansss commented Mar 11, 2024

Hey @RaSan147 , is there a reason why these two calculations are different? I wonder if they can be consistent so I can move them into InternalModel.

let value = this.motionManager.mouthSync();
let min_ = 0;
const max_ = 1;
const bias_weight = 1.2;
const bias_power = 0.7;
if (value > 0.0) {
min_ = 0.4;
}
value = Math.pow(value, bias_power);
value = clamp(value * bias_weight, min_, max_);
for (let i = 0; i < this.motionManager.lipSyncIds.length; ++i) {
this.coreModel.setParamFloat(
this.coreModel.getParamIndex(this.motionManager.lipSyncIds[i]!),
value,
);
}

let value = this.motionManager.mouthSync();
let min_ = 0;
const max_ = 1;
const weight = 1.2;
if (value > 0) {
min_ = 0.4;
}
value = clamp(value * weight, min_, max_);
for (let i = 0; i < this.motionManager.lipSyncIds.length; ++i) {
model.addParameterValueById(this.motionManager.lipSyncIds[i], value, 0.8);
}

@RaSan147
Copy link
Author

Hey @RaSan147 , is there a reason why these two calculations are different? I wonder if they can be consistent so I can move them into InternalModel.

let value = this.motionManager.mouthSync();
let min_ = 0;
const max_ = 1;
const bias_weight = 1.2;
const bias_power = 0.7;
if (value > 0.0) {
min_ = 0.4;
}
value = Math.pow(value, bias_power);
value = clamp(value * bias_weight, min_, max_);
for (let i = 0; i < this.motionManager.lipSyncIds.length; ++i) {
this.coreModel.setParamFloat(
this.coreModel.getParamIndex(this.motionManager.lipSyncIds[i]!),
value,
);
}

let value = this.motionManager.mouthSync();
let min_ = 0;
const max_ = 1;
const weight = 1.2;
if (value > 0) {
min_ = 0.4;
}
value = clamp(value * weight, min_, max_);
for (let i = 0; i < this.motionManager.lipSyncIds.length; ++i) {
model.addParameterValueById(this.motionManager.lipSyncIds[i], value, 0.8);
}

Sorry, i might forgot to update the another one. Would recommend adding bias_power and weighted one (otherwise lips don't move well).

@guansss
Copy link
Owner

guansss commented Apr 15, 2024

Finally it's ready to merge! Before I merge it, are there any changes you would like to make or suggest?

@RaSan147
Copy link
Author

Sorry didn't notice, gimme a bit time, testing...

@RaSan147
Copy link
Author

btw can you please check the PR i've sent you on cubism folder repo...
that should fix the process not found (or you may tweak the results a bit)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vite requires terser in this version (my fresh install was not working without it, so kindly add it the deps
i fixed it with npm install terser

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add another option, force or priority, if force or higher priority, will stop current audio, otherwise current one will play.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will add onFinish and onError callback as option

@RaSan147
Copy link
Author

Well, I'm gonna miss motion(...., {sound})
it was a great option (since its optional feature, removing it is kinda feeling like a bad idea)
that would help retain certain posture and motion while speaking. Also the expression and many more things are missing from the PR_version...
😥

@liyao1520
Copy link

期待,更新

@RaSan147
Copy link
Author

RaSan147 commented May 8, 2024

Gotta re-test and look for compatible way to shift from patch to official version

@liyao1520
Copy link

#150

live2d official website The demonstration video of the model can flexibly display mouth movements, and the lip-syncing looks quite natural. Demo Video

In this example model, not only can the mouth opening be set based on audio information, but vowel mouth shapes can also be set by adjusting 'ParamA', 'ParamE', 'ParamI', 'ParamO', 'ParamU'.

model.internalModel.coreModel.setParameterValueById('ParamMouthOpenY', mouthY)
model.internalModel.coreModel.setParameterValueById('ParamA', 0.3)

I feel there might be better methods to achieve lip-syncing. Can the model be set to correspond to the mouth shape based on the audio?

Also, Alibaba Cloud's TTS can output the time position of each Chinese character/English word in the audio. How can the model play the audio, and can it set the corresponding mouth shape based on the phonetic information?

Seeking guidance from the experts! 🙏

@RaSan147
Copy link
Author

Finally it's ready to merge! Before I merge it, are there any changes you would like to make or suggest?

Whenever you're ready. Thanks for all your hard works

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants