mirror of
https://github.com/neodyland/sbv2-api.git
synced 2026-01-04 13:32:57 +00:00
168 lines
4.2 KiB
Rust
168 lines
4.2 KiB
Rust
use pyo3::prelude::*;
|
|
use pyo3::types::PyBytes;
|
|
use sbv2_core::tts::{SynthesizeOptions, TTSModelHolder};
|
|
|
|
use crate::style::StyleVector;
|
|
|
|
use std::fs;
|
|
|
|
/// TTSModel class
|
|
///
|
|
/// 音声合成するために使うクラス
|
|
///
|
|
/// Parameters
|
|
/// ----------
|
|
/// bert_model_bytes : bytes
|
|
/// BERTモデルのバイナリデータ
|
|
/// tokenizer_bytes : bytes
|
|
/// トークナイザーのバイナリデータ
|
|
#[pyclass]
|
|
pub struct TTSModel {
|
|
pub model: TTSModelHolder,
|
|
}
|
|
|
|
#[pymethods]
|
|
impl TTSModel {
|
|
#[pyo3(signature = (bert_model_bytes, tokenizer_bytes, max_loaded_models=None))]
|
|
#[new]
|
|
fn new(
|
|
bert_model_bytes: Vec<u8>,
|
|
tokenizer_bytes: Vec<u8>,
|
|
max_loaded_models: Option<usize>,
|
|
) -> anyhow::Result<Self> {
|
|
Ok(Self {
|
|
model: TTSModelHolder::new(bert_model_bytes, tokenizer_bytes, max_loaded_models)?,
|
|
})
|
|
}
|
|
|
|
/// パスからTTSModelインスタンスを生成する
|
|
///
|
|
/// Parameters
|
|
/// ----------
|
|
/// bert_model_path : str
|
|
/// BERTモデルのパス
|
|
/// tokenizer_path : str
|
|
/// トークナイザーのパス
|
|
/// max_loaded_models: int | None
|
|
/// 同時にVRAMに存在するモデルの数
|
|
#[pyo3(signature = (bert_model_path, tokenizer_path, max_loaded_models=None))]
|
|
#[staticmethod]
|
|
fn from_path(
|
|
bert_model_path: String,
|
|
tokenizer_path: String,
|
|
max_loaded_models: Option<usize>,
|
|
) -> anyhow::Result<Self> {
|
|
Ok(Self {
|
|
model: TTSModelHolder::new(
|
|
fs::read(bert_model_path)?,
|
|
fs::read(tokenizer_path)?,
|
|
max_loaded_models,
|
|
)?,
|
|
})
|
|
}
|
|
|
|
/// SBV2ファイルを読み込む
|
|
///
|
|
/// Parameters
|
|
/// ----------
|
|
/// ident : str
|
|
/// 識別子
|
|
/// sbv2file_bytes : bytes
|
|
/// SBV2ファイルのバイナリデータ
|
|
fn load_sbv2file(&mut self, ident: String, sbv2file_bytes: Vec<u8>) -> anyhow::Result<()> {
|
|
self.model.load_sbv2file(ident, sbv2file_bytes)?;
|
|
Ok(())
|
|
}
|
|
|
|
/// パスからSBV2ファイルを読み込む
|
|
///
|
|
/// Parameters
|
|
/// ----------
|
|
/// ident : str
|
|
/// 識別子
|
|
/// sbv2file_path : str
|
|
/// SBV2ファイルのパス
|
|
fn load_sbv2file_from_path(
|
|
&mut self,
|
|
ident: String,
|
|
sbv2file_path: String,
|
|
) -> anyhow::Result<()> {
|
|
self.model.load_sbv2file(ident, fs::read(sbv2file_path)?)?;
|
|
Ok(())
|
|
}
|
|
|
|
/// スタイルベクトルを取得する
|
|
///
|
|
/// Parameters
|
|
/// ----------
|
|
/// ident : str
|
|
/// 識別子
|
|
/// style_id : int
|
|
/// スタイルID
|
|
/// weight : float
|
|
/// 重み
|
|
///
|
|
/// Returns
|
|
/// -------
|
|
/// style_vector : StyleVector
|
|
/// スタイルベクトル
|
|
fn get_style_vector(
|
|
&mut self,
|
|
ident: String,
|
|
style_id: i32,
|
|
weight: f32,
|
|
) -> anyhow::Result<StyleVector> {
|
|
Ok(StyleVector::new(
|
|
self.model.get_style_vector(ident, style_id, weight)?,
|
|
))
|
|
}
|
|
|
|
/// テキストから音声を合成する
|
|
///
|
|
/// Parameters
|
|
/// ----------
|
|
/// text : str
|
|
/// テキスト
|
|
/// ident : str
|
|
/// 識別子
|
|
/// style_id : int
|
|
/// スタイルID
|
|
/// sdp_ratio : float
|
|
/// SDP比率
|
|
/// length_scale : float
|
|
/// 音声の長さのスケール
|
|
///
|
|
/// Returns
|
|
/// -------
|
|
/// voice_data : bytes
|
|
/// 音声データ
|
|
#[allow(clippy::too_many_arguments)]
|
|
fn synthesize<'p>(
|
|
&'p mut self,
|
|
py: Python<'p>,
|
|
text: String,
|
|
ident: String,
|
|
style_id: i32,
|
|
speaker_id: i64,
|
|
sdp_ratio: f32,
|
|
length_scale: f32,
|
|
) -> anyhow::Result<Bound<'p, PyBytes>> {
|
|
let data = self.model.easy_synthesize(
|
|
ident.as_str(),
|
|
&text,
|
|
style_id,
|
|
speaker_id,
|
|
SynthesizeOptions {
|
|
sdp_ratio,
|
|
length_scale,
|
|
..Default::default()
|
|
},
|
|
)?;
|
|
Ok(PyBytes::new(py, &data))
|
|
}
|
|
|
|
fn unload(&mut self, ident: String) -> bool {
|
|
self.model.unload(ident)
|
|
}
|
|
}
|