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

feat!: Rust APIだけTextAnalyzerをパブリックにする #919

Merged
merged 6 commits into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/voicevox_core/src/__internal/doctest_fixtures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub async fn synthesizer_with_sample_voice_model(
#[cfg(feature = "link-onnxruntime")]
crate::nonblocking::Onnxruntime::init_once().await?,
)
.open_jtalk(crate::nonblocking::OpenJtalk::new(open_jtalk_dic_dir).await?)
.text_analyzer(crate::nonblocking::OpenJtalk::new(open_jtalk_dic_dir).await?)
.acceleration_mode(AccelerationMode::Cpu)
.build()?;

Expand Down
3 changes: 2 additions & 1 deletion crates/voicevox_core/src/blocking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
pub use crate::{
engine::open_jtalk::blocking::OpenJtalk, infer::runtimes::onnxruntime::blocking::Onnxruntime,
synthesizer::blocking::AudioFeature, synthesizer::blocking::Synthesizer,
user_dict::dict::blocking::UserDict, voice_model::blocking::VoiceModelFile,
text_analyzer::blocking::TextAnalyzer, user_dict::dict::blocking::UserDict,
voice_model::blocking::VoiceModelFile,
};

pub mod onnxruntime {
Expand Down
5 changes: 2 additions & 3 deletions crates/voicevox_core/src/engine/full_context_label.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use crate::{
use jlabel::Label;
use smallvec::SmallVec;

// FIXME: 入力テキストをここで持って、メッセージに含む
#[derive(thiserror::Error, Debug)]
#[error("入力テキストからのフルコンテキストラベル抽出に失敗しました: {context}")]
pub(crate) struct FullContextLabelError {
Expand Down Expand Up @@ -428,7 +427,7 @@ mod tests {
let open_jtalk = crate::nonblocking::OpenJtalk::new(OPEN_JTALK_DIC_DIR)
.await
.unwrap();
assert_eq!(&open_jtalk.extract_fullcontext(text).unwrap(), labels);
assert_eq!(&open_jtalk.0.extract_fullcontext(text).unwrap(), labels);
}

#[apply(label_cases)]
Expand All @@ -451,7 +450,7 @@ mod tests {
.await
.unwrap();
assert_eq!(
&extract_full_context_label(&open_jtalk, text).unwrap(),
&extract_full_context_label(&open_jtalk.0, text).unwrap(),
accent_phrase
);
}
Expand Down
3 changes: 3 additions & 0 deletions crates/voicevox_core/src/engine/kana_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ fn text_to_accent_phrase(phrase: &str) -> KanaParseResult<AccentPhrase> {

pub(crate) fn parse_kana(text: &str) -> KanaParseResult<Vec<AccentPhrase>> {
const TERMINATOR: char = '\0';
if text.is_empty() {
return Ok(vec![]);
}
let mut parsed_result = Vec::new();
let chars_of_text = text.chars().chain([TERMINATOR]);
let mut phrase = String::new();
Expand Down
3 changes: 1 addition & 2 deletions crates/voicevox_core/src/engine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ pub(crate) mod open_jtalk;
pub(crate) use self::acoustic_feature_extractor::OjtPhoneme;
pub(crate) use self::audio_file::to_s16le_pcm;
pub use self::audio_file::wav_from_s16le;
pub(crate) use self::full_context_label::{extract_full_context_label, FullContextLabelError};
pub(crate) use self::full_context_label::extract_full_context_label;
pub(crate) use self::interpret_query::{initial_process, split_mora, DecoderFeature};
pub(crate) use self::kana_parser::{create_kana, parse_kana, KanaParseError};
pub use self::model::{AccentPhrase, AudioQuery, Mora};
pub(crate) use self::mora_list::mora2text;
pub use self::open_jtalk::FullcontextExtractor;
46 changes: 36 additions & 10 deletions crates/voicevox_core/src/engine/open_jtalk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub(crate) struct OpenjtalkFunctionError {
source: Option<Text2MecabError>,
}

pub trait FullcontextExtractor: Clone + Send + Sync + 'static {
pub(crate) trait FullcontextExtractor {
fn extract_fullcontext(&self, text: &str) -> anyhow::Result<Vec<String>>;
}

Expand All @@ -38,7 +38,10 @@ pub(crate) mod blocking {

use crate::error::ErrorRepr;

use super::{FullcontextExtractor, OpenjtalkFunctionError};
use super::{
super::{extract_full_context_label, AccentPhrase},
FullcontextExtractor, OpenjtalkFunctionError,
};

/// テキスト解析器としてのOpen JTalk。
#[derive(Clone)]
Expand Down Expand Up @@ -80,12 +83,19 @@ pub(crate) mod blocking {
}

impl FullcontextExtractor for self::OpenJtalk {
fn extract_fullcontext(&self, text: &str) -> anyhow::Result<Vec<String>> {
self.0.extract_fullcontext(text)
}
}

// TODO: このコードの移動
impl FullcontextExtractor for Inner {
fn extract_fullcontext(&self, text: &str) -> anyhow::Result<Vec<String>> {
let Resources {
mecab,
njd,
jpcommon,
} = &mut *self.0.resources.lock().unwrap();
} = &mut *self.resources.lock().unwrap();

jpcommon.refresh();
njd.refresh();
Expand Down Expand Up @@ -129,6 +139,15 @@ pub(crate) mod blocking {
}
}

impl crate::blocking::TextAnalyzer for self::OpenJtalk {
fn analyze(&self, text: &str) -> anyhow::Result<Vec<AccentPhrase>> {
if text.is_empty() {
return Ok(Vec::new());
}
Ok(extract_full_context_label(&*self.0, text)?)
}
}

pub(super) struct Inner {
resources: std::sync::Mutex<Resources>,
dict_dir: Utf8PathBuf,
Expand Down Expand Up @@ -196,7 +215,7 @@ pub(crate) mod blocking {
pub(crate) mod nonblocking {
use camino::Utf8Path;

use super::FullcontextExtractor;
use super::super::{extract_full_context_label, AccentPhrase};

/// テキスト解析器としてのOpen JTalk。
///
Expand All @@ -207,7 +226,7 @@ pub(crate) mod nonblocking {
/// [blocking]: https://docs.rs/crate/blocking
/// [`nonblocking`モジュールのドキュメント]: crate::nonblocking
#[derive(Clone)]
pub struct OpenJtalk(super::blocking::OpenJtalk);
pub struct OpenJtalk(pub(in super::super) super::blocking::OpenJtalk);

impl self::OpenJtalk {
pub async fn new(open_jtalk_dict_dir: impl AsRef<Utf8Path>) -> crate::result::Result<Self> {
Expand All @@ -231,9 +250,16 @@ pub(crate) mod nonblocking {
}
}

impl FullcontextExtractor for self::OpenJtalk {
fn extract_fullcontext(&self, text: &str) -> anyhow::Result<Vec<String>> {
self.0.extract_fullcontext(text)
impl crate::nonblocking::TextAnalyzer for self::OpenJtalk {
async fn analyze(&self, text: &str) -> anyhow::Result<Vec<AccentPhrase>> {
if text.is_empty() {
return Ok(Vec::new());
}
let inner = self.0 .0.clone();
let text = text.to_owned();
crate::task::asyncify(move || extract_full_context_label(&*inner, &text))
.await
.map_err(Into::into)
}
}
}
Expand Down Expand Up @@ -345,7 +371,7 @@ mod tests {
let open_jtalk = super::nonblocking::OpenJtalk::new(OPEN_JTALK_DIC_DIR)
.await
.unwrap();
let result = open_jtalk.extract_fullcontext(text);
let result = open_jtalk.0.extract_fullcontext(text);
assert_debug_fmt_eq!(expected, result);
}

Expand All @@ -360,7 +386,7 @@ mod tests {
.await
.unwrap();
for _ in 0..10 {
let result = open_jtalk.extract_fullcontext(text);
let result = open_jtalk.0.extract_fullcontext(text);
assert_debug_fmt_eq!(expected, result);
}
}
Expand Down
21 changes: 11 additions & 10 deletions crates/voicevox_core/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use crate::{
devices::DeviceAvailabilities,
engine::{FullContextLabelError, KanaParseError},
user_dict::InvalidWordError,
StyleId, StyleType, VoiceModelId,
devices::DeviceAvailabilities, engine::KanaParseError, user_dict::InvalidWordError, StyleId,
StyleType, VoiceModelId,
};
//use engine::
use duplicate::duplicate_item;
Expand All @@ -19,7 +17,6 @@ pub struct Error(#[from] ErrorRepr);
#[duplicate_item(
E;
[ LoadModelError ];
[ FullContextLabelError ];
[ KanaParseError ];
[ InvalidWordError ];
)]
Expand Down Expand Up @@ -48,7 +45,7 @@ impl Error {
ErrorRepr::StyleNotFound { .. } => ErrorKind::StyleNotFound,
ErrorRepr::ModelNotFound { .. } => ErrorKind::ModelNotFound,
ErrorRepr::RunModel { .. } => ErrorKind::RunModel,
ErrorRepr::ExtractFullContextLabel(_) => ErrorKind::ExtractFullContextLabel,
ErrorRepr::AnalyzeText { .. } => ErrorKind::AnalyzeText,
ErrorRepr::ParseKana(_) => ErrorKind::ParseKana,
ErrorRepr::LoadUserDict(_) => ErrorKind::LoadUserDict,
ErrorRepr::SaveUserDict(_) => ErrorKind::SaveUserDict,
Expand Down Expand Up @@ -99,8 +96,12 @@ pub(crate) enum ErrorRepr {
#[error("推論に失敗しました")]
RunModel(#[source] anyhow::Error),

#[error(transparent)]
ExtractFullContextLabel(#[from] FullContextLabelError),
#[error("入力テキストの解析に失敗しました")]
AnalyzeText {
text: String,
#[source]
source: anyhow::Error,
},

#[error(transparent)]
ParseKana(#[from] KanaParseError),
Expand Down Expand Up @@ -150,8 +151,8 @@ pub enum ErrorKind {
ModelNotFound,
/// 推論に失敗した。
RunModel,
/// コンテキストラベル出力に失敗した
ExtractFullContextLabel,
/// 入力テキストの解析に失敗した
AnalyzeText,
/// AquesTalk風記法のテキストの解析に失敗した。
ParseKana,
/// ユーザー辞書を読み込めなかった。
Expand Down
2 changes: 1 addition & 1 deletion crates/voicevox_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ use rstest_reuse;

pub use self::{
devices::SupportedDevices,
engine::{wav_from_s16le, AccentPhrase, AudioQuery, FullcontextExtractor, Mora},
engine::{wav_from_s16le, AccentPhrase, AudioQuery, Mora},
error::{Error, ErrorKind},
metas::{
RawStyleId, RawStyleVersion, SpeakerMeta, StyleId, StyleMeta, StyleType, StyleVersion,
Expand Down
3 changes: 2 additions & 1 deletion crates/voicevox_core/src/nonblocking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
pub use crate::{
engine::open_jtalk::nonblocking::OpenJtalk,
infer::runtimes::onnxruntime::nonblocking::Onnxruntime, synthesizer::nonblocking::Synthesizer,
user_dict::dict::nonblocking::UserDict, voice_model::nonblocking::VoiceModelFile,
text_analyzer::nonblocking::TextAnalyzer, user_dict::dict::nonblocking::UserDict,
voice_model::nonblocking::VoiceModelFile,
};

pub mod onnxruntime {
Expand Down
Loading
Loading