Skip to content

Instantly share code, notes, and snippets.

@masakielastic
Created February 21, 2026 03:27
Show Gist options
  • Select an option

  • Save masakielastic/9328069f3515276965fdd6e94d3f4f2e to your computer and use it in GitHub Desktop.

Select an option

Save masakielastic/9328069f3515276965fdd6e94d3f4f2e to your computer and use it in GitHub Desktop.
VOICEVOX Core で Rust で使う

VOICEVOX Core で Rust で使う

前提環境

Debian 12 (Chromebook)

再生プレイヤー

aplayer をインストールします。

sudo apt-get update
sudo apt-get install -y alsa-utils

関連ファイルのダウンロード

chmod +x download
./download --exclude c-api

構成

Cargo.toml

[package]
name = "voicevox-core"
version = "0.1.0"
edition = "2024"

[dependencies]
anyhow = "1.0.102"
const_format = "0.2.35"
open = "5.3.3"
tempfile = "3.25.0"
voicevox_core = { git = "https://github.com/VOICEVOX/voicevox_core", tag = "0.16.4", package = "voicevox_core", features = ["load-onnxruntime"] }

src/main.rs

use anyhow::Context as _;
use const_format::concatcp;

use voicevox_core::{
    blocking::{Onnxruntime, OpenJtalk, Synthesizer, VoiceModelFile},
    CharacterMeta, StyleMeta,
};

// ダウンローダーにて`onnxruntime`としてダウンロードできるもの
const VVORT: &str = concatcp!(
    "./voicevox_core/onnxruntime/lib/",
    Onnxruntime::LIB_VERSIONED_FILENAME,
);

// ダウンローダーにて`dict`としてダウンロードできるもの
const OJT_DIC: &str = "./voicevox_core/dict/open_jtalk_dic_utf_8-1.11";

// ダウンローダーにて`models`としてダウンロードできるもの
const VVM: &str = "./voicevox_core/models/vvms/0.vvm";

const TARGET_CHARACTER_NAME: &str = "ずんだもん";
const TARGET_STYLE_NAME: &str = "ノーマル";
const TEXT: &str = "こんにちは";

fn main() -> anyhow::Result<()> {
    let synth = {
        let ort = Onnxruntime::load_once().filename(VVORT).perform()?;
        let ojt = OpenJtalk::new(OJT_DIC)?;
        Synthesizer::builder(ort).text_analyzer(ojt).build()?
    };

    dbg!(synth.is_gpu_mode());

    synth.load_voice_model(&VoiceModelFile::open(VVM)?)?;

    let StyleMeta { id: style_id, .. } = synth
        .metas()
        .into_iter()
        .filter(|CharacterMeta { name, .. }| name == TARGET_CHARACTER_NAME)
        .flat_map(|CharacterMeta { styles, .. }| styles)
        .find(|StyleMeta { name, .. }| name == TARGET_STYLE_NAME)
        .with_context(|| {
            format!("could not find \"{TARGET_CHARACTER_NAME} ({TARGET_STYLE_NAME})\"")
        })?;

    eprintln!("Synthesizing");
    let wav = &synth.tts(TEXT, style_id).perform()?;

    eprintln!("Playing the WAV");
    play(wav)?;

    Ok(())
}

use std::process::Command;

fn play(wav: &[u8]) -> anyhow::Result<()> {
    use std::io::Write;

    let tempfile = tempfile::Builder::new().suffix(".wav").tempfile()?;
    (&tempfile).write_all(wav)?;
    let path = tempfile.into_temp_path();

    let status = Command::new("aplay")
        .arg("-q") // quiet
        .arg(&path)
        .status()?;

    anyhow::ensure!(status.success(), "aplay failed: {status}");
    Ok(())
}

ビルド

cargo run
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment