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

metas出力時に話者情報をマージする #728

Merged
merged 9 commits into from
Feb 9, 2024
2 changes: 1 addition & 1 deletion crates/voicevox_core/src/__internal/interop.rs
Original file line number Diff line number Diff line change
@@ -1 +1 @@
pub use crate::synthesizer::blocking::PerformInference;
pub use crate::{metas::merge as merge_metas, synthesizer::blocking::PerformInference};
44 changes: 27 additions & 17 deletions crates/voicevox_core/src/infer/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::{
error::{ErrorRepr, LoadModelError, LoadModelErrorKind, LoadModelResult},
infer::{InferenceOperation, ParamInfo},
manifest::ModelInnerId,
metas::{SpeakerMeta, StyleId, StyleMeta, VoiceModelMeta},
metas::{self, SpeakerMeta, StyleId, StyleMeta, VoiceModelMeta},
voice_model::{VoiceModelHeader, VoiceModelId},
Result,
};
Expand Down Expand Up @@ -130,11 +130,7 @@ struct LoadedModel<R: InferenceRuntime, D: InferenceDomain> {

impl<R: InferenceRuntime, D: InferenceDomain> LoadedModels<R, D> {
fn metas(&self) -> VoiceModelMeta {
self.0
.values()
.flat_map(|LoadedModel { metas, .. }| metas)
.cloned()
.collect()
metas::merge(self.0.values().flat_map(|LoadedModel { metas, .. }| metas))
}

fn ids_for(&self, style_id: StyleId) -> Result<(VoiceModelId, ModelInnerId)> {
Expand Down Expand Up @@ -184,20 +180,33 @@ impl<R: InferenceRuntime, D: InferenceDomain> LoadedModels<R, D> {
///
/// # Errors
///
/// 音声モデルIDかスタイルIDが`model_header`と重複するとき、エラーを返す。
/// 次の場合にエラーを返す。
///
/// - 音声モデルIDかスタイルIDが`model_header`と重複するとき
/// - 同じ`speaker_uuid`で、スタイル以外でプロパティが異なっている話者があるとき
fn ensure_acceptable(&self, model_header: &VoiceModelHeader) -> LoadModelResult<()> {
let loaded = self.styles();
let external = model_header
.metas
.iter()
.flat_map(|speaker| speaker.styles());

let error = |context| LoadModelError {
path: model_header.path.clone(),
context,
source: None,
};

let loaded = self.speakers();
let external = model_header.metas.iter();
if let Some((_loaded, _external)) =
iproduct!(loaded, external).find(|(loaded, external)| {
loaded.speaker_uuid() == external.speaker_uuid()
&& !loaded.eq_except_styles(external)
})
{
todo!("same `speaker_uuid` but different properties");
Copy link
Member Author

Choose a reason for hiding this comment

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

エラーを一つ増設するか悩みます。別に検査しなくてもいいような気がしますし。

Copy link
Member

@Hiroshiba Hiroshiba Jan 21, 2024

Choose a reason for hiding this comment

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

どっちでもって感じかなと!
人為的なミスには気づきやすくなるので、実装があるならありがたいかもです。
todoが何するかわかってないのですが、エラー取り回し面倒という感じだと思うので、stderrにwarn吐くかpanicでも良いのかもとか思いました!

Copy link
Member Author

Choose a reason for hiding this comment

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

todo!はパニックを起こすものですが、これをやめてwarning止まりにするようにしました。

25a918c (#728)

}

let loaded = self.styles();
let external = model_header
.metas
.iter()
.flat_map(|speaker| speaker.styles());
if self.0.contains_key(&model_header.id) {
return Err(error(LoadModelErrorKind::ModelAlreadyLoaded {
id: model_header.id.clone(),
Expand Down Expand Up @@ -242,11 +251,12 @@ impl<R: InferenceRuntime, D: InferenceDomain> LoadedModels<R, D> {
Ok(())
}

fn speakers(&self) -> impl Iterator<Item = &SpeakerMeta> {
self.0.values().flat_map(|LoadedModel { metas, .. }| metas)
}

fn styles(&self) -> impl Iterator<Item = &StyleMeta> {
self.0
.values()
.flat_map(|LoadedModel { metas, .. }| metas)
.flat_map(|speaker| speaker.styles())
self.speakers().flat_map(|speaker| speaker.styles())
}
}

Expand Down
47 changes: 47 additions & 0 deletions crates/voicevox_core/src/metas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,35 @@ use std::fmt::Display;

use derive_getters::Getters;
use derive_new::new;
use itertools::Itertools as _;
use serde::{Deserialize, Serialize};

pub fn merge<'a>(metas: impl IntoIterator<Item = &'a SpeakerMeta>) -> Vec<SpeakerMeta> {
metas
.into_iter()
.into_grouping_map_by(|speaker| &speaker.speaker_uuid)
.aggregate::<_, SpeakerMeta>(|acc, _, speaker| {
Some(
acc.map(|mut acc| {
acc.styles.extend(speaker.styles.clone());
acc
})
.unwrap_or_else(|| speaker.clone()),
)
})
.into_values()
.map(|mut speaker| {
speaker
.styles
.sort_unstable_by_key(|&StyleMeta { id, .. }| id);
speaker
})
.sorted_unstable_by_key(|SpeakerMeta { styles, .. }| {
styles.first().map(|&StyleMeta { id, .. }| id)
})
.collect()
}
Copy link
Member Author

Choose a reason for hiding this comment

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

実装になんかコメントを付けようと考えましたが、別に要らないかも...

Copy link
Member

@Hiroshiba Hiroshiba Jan 21, 2024

Choose a reason for hiding this comment

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

この関数の役割兼、何するかの1行ドキュメントくらいはあると道標になるかもとは思いました!
よくよく見直すと、単純なarrayのconcatenateなのか、何かをkeyにして名寄せするのかとかは関数名からじゃわからないかもです。
「同じ話者IDのものを集約しつつ結合」とか…?

(まぁ、多少知識があるとspeaker idで名寄せなのはすぐ想像できるので、なくても良いという方針でもあまり問題ないかなとも思います。)

Copy link
Member Author

Choose a reason for hiding this comment

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

書きました。
9d2b1a2 (#728)


/// [`StyleId`]の実体。
///
/// [`StyleId`]: StyleId
Expand Down Expand Up @@ -67,6 +94,26 @@ pub struct SpeakerMeta {
speaker_uuid: String,
}

impl SpeakerMeta {
pub(crate) fn eq_except_styles(&self, other: &Self) -> bool {
let Self {
name: name1,
styles: _,
version: version1,
speaker_uuid: speaker_uuid1,
} = self;

let Self {
name: name2,
styles: _,
version: version2,
speaker_uuid: speaker_uuid2,
} = other;

(name1, version1, speaker_uuid1) == (name2, version2, speaker_uuid2)
}
}

/// **スタイル**(_style_)のメタ情報。
#[derive(Deserialize, Serialize, Getters, Clone)]
pub struct StyleMeta {
Expand Down
4 changes: 3 additions & 1 deletion crates/voicevox_core_c_api/src/compatible_engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ static VOICE_MODEL_SET: Lazy<VoiceModelSet> = Lazy::new(|| {
.iter()
.map(|vvm| (vvm.id().clone(), vvm.clone()))
.collect();
let metas: Vec<_> = all_vvms.iter().flat_map(|vvm| vvm.metas()).collect();
let metas = voicevox_core::__internal::interop::merge_metas(
all_vvms.iter().flat_map(|vvm| vvm.metas()),
);
let mut style_model_map = BTreeMap::default();
for vvm in all_vvms.iter() {
for meta in vvm.metas().iter() {
Expand Down
Loading