Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

vits-piper-de_DE-thorsten_emotional-medium

Info about this model

This model is converted from https://huggingface.co/rhasspy/piper-voices/tree/main/de/de_DE/thorsten_emotional/medium

Number of speakersSample rate
822050

Download the model

Click to expand

Model download address

https://github.com/k2-fsa/sherpa-onnx/releases/download/tts-models/vits-piper-de_DE-thorsten_emotional-medium.tar.bz2

Android APK

Click to expand

The following table shows the Android TTS Engine APK with this model for sherpa-onnx v1.13.2

ABIURL中国镜像
arm64-v8aDownload下载
armeabi-v7aDownload下载
x86_64Download下载
x86Download下载

If you don’t know what ABI is, you probably need to select arm64-v8a.

The source code for the APK can be found at

https://github.com/k2-fsa/sherpa-onnx/tree/master/android/SherpaOnnxTtsEngine

Please refer to the documentation for how to build the APK from source code.

More Android APKs can be found at

https://k2-fsa.github.io/sherpa/onnx/tts/apk-engine.html

C API

Click to expand

You can use the following code to play with vits-piper-de_DE-thorsten_emotional-medium with C API.

#include <stdio.h>
#include <string.h>

#include "sherpa-onnx/c-api/c-api.h"

int main() {
  SherpaOnnxOfflineTtsConfig config;
  memset(&config, 0, sizeof(config));

  config.model.vits.model = "vits-piper-de_DE-thorsten_emotional-medium/de_DE-thorsten_emotional-medium.onnx";
  config.model.vits.tokens = "vits-piper-de_DE-thorsten_emotional-medium/tokens.txt";
  config.model.vits.data_dir = "vits-piper-de_DE-thorsten_emotional-medium/espeak-ng-data";
  config.model.num_threads = 1;

  // If you want to see debug messages, please set it to 1
  config.model.debug = 0;

  const SherpaOnnxOfflineTts *tts = SherpaOnnxCreateOfflineTts(&config);

  const char *text = "Alles hat ein Ende, nur die Wurst hat zwei.";

  SherpaOnnxGenerationConfig gen_cfg;
  memset(&gen_cfg, 0, sizeof(gen_cfg));
  gen_cfg.sid = 0;
  gen_cfg.speed = 1.0;

  const SherpaOnnxGeneratedAudio *audio =
      SherpaOnnxOfflineTtsGenerateWithConfig(tts, text, &gen_cfg, NULL, NULL);

  SherpaOnnxWriteWave(audio->samples, audio->n, audio->sample_rate,
                      "./test.wav");

  // You need to free the pointers to avoid memory leak in your app
  SherpaOnnxDestroyOfflineTtsGeneratedAudio(audio);
  SherpaOnnxDestroyOfflineTts(tts);

  printf("Saved to ./test.wav\n");

  return 0;
}

In the following, we describe how to compile and run the above C example.

cd /tmp
git clone https://github.com/k2-fsa/sherpa-onnx
cd sherpa-onnx
mkdir build-shared
cd build-shared

cmake  -DSHERPA_ONNX_ENABLE_C_API=ON  -DCMAKE_BUILD_TYPE=Release  -DBUILD_SHARED_LIBS=ON  -DCMAKE_INSTALL_PREFIX=/tmp/sherpa-onnx/shared  ..

make
make install

You can find required header file and library files inside /tmp/sherpa-onnx/shared.

Assume you have saved the above example file as /tmp/test-piper.c. Then you can compile it with the following command:

gcc   -I /tmp/sherpa-onnx/shared/include   -L /tmp/sherpa-onnx/shared/lib   -lsherpa-onnx-c-api   -lonnxruntime   -o /tmp/test-piper   /tmp/test-piper.c

Now you can run

cd /tmp

# Assume you have downloaded the model and extracted it to /tmp
./test-piper

You probably need to run

# For Linux
export LD_LIBRARY_PATH=/tmp/sherpa-onnx/shared/lib:$LD_LIBRARY_PATH

# For macOS
export DYLD_LIBRARY_PATH=/tmp/sherpa-onnx/shared/lib:$DYLD_LIBRARY_PATH

before you run /tmp/test-piper.

Please see the documentation at

https://k2-fsa.github.io/sherpa/onnx/c-api/index.html

Python API

Click to expand

Assume you have installed sherpa-onnx via

pip install sherpa-onnx

and you have downloaded the model from

https://github.com/k2-fsa/sherpa-onnx/releases/download/tts-models/vits-piper-de_DE-thorsten_emotional-medium.tar.bz2

You can use the following code to play with vits-piper-de_DE-thorsten_emotional-medium

import sherpa_onnx
import soundfile as sf

config = sherpa_onnx.OfflineTtsConfig(
    model=sherpa_onnx.OfflineTtsModelConfig(
        vits=sherpa_onnx.OfflineTtsVitsModelConfig(
            model="vits-piper-de_DE-thorsten_emotional-medium/de_DE-thorsten_emotional-medium.onnx",
            data_dir="vits-piper-de_DE-thorsten_emotional-medium/espeak-ng-data",
            tokens="vits-piper-de_DE-thorsten_emotional-medium/tokens.txt",
        ),
        num_threads=1,
    ),
)

if not config.validate():
    raise ValueError("Please check your config")

tts = sherpa_onnx.OfflineTts(config)
audio = tts.generate(text="Alles hat ein Ende, nur die Wurst hat zwei.",
                     sid=0,
                     speed=1.0)

sf.write("test.mp3", audio.samples, samplerate=audio.sample_rate)

C++ API

Click to expand

You can use the following code to play with vits-piper-de_DE-thorsten_emotional-medium with C++ API.

#include <cstdint>
#include <cstdio>
#include <string>

#include "sherpa-onnx/c-api/cxx-api.h"

static int32_t ProgressCallback(const float *samples, int32_t num_samples,
                                float progress, void *arg) {
  fprintf(stderr, "Progress: %.3f%%\n", progress * 100);
  // return 1 to continue generating
  // return 0 to stop generating
  return 1;
}

int32_t main(int32_t argc, char *argv[]) {
  using namespace sherpa_onnx::cxx; // NOLINT
  OfflineTtsConfig config;
  config.model.vits.model = "vits-piper-de_DE-thorsten_emotional-medium/de_DE-thorsten_emotional-medium.onnx";
  config.model.vits.tokens = "vits-piper-de_DE-thorsten_emotional-medium/tokens.txt";
  config.model.vits.data_dir = "vits-piper-de_DE-thorsten_emotional-medium/espeak-ng-data";
  config.model.num_threads = 1;

  // If you want to see debug messages, please set it to 1
  config.model.debug = 0;

  std::string filename = "./test.wav";
  std::string text = "Alles hat ein Ende, nur die Wurst hat zwei.";

  auto tts = OfflineTts::Create(config);

  GenerationConfig gen_cfg;
  gen_cfg.sid = 0;
  gen_cfg.speed = 1.0; // larger -> faster in speech speed

#if 0
  // If you don't want to use a callback, then please enable this branch
  GeneratedAudio audio = tts.Generate(text, gen_cfg);
#else
  GeneratedAudio audio = tts.Generate(text, gen_cfg, ProgressCallback);
#endif

  WriteWave(filename, {audio.samples, audio.sample_rate});

  fprintf(stderr, "Input text is: %s\n", text.c_str());
  fprintf(stderr, "Speaker ID is: %d\n", gen_cfg.sid);
  fprintf(stderr, "Saved to: %s\n", filename.c_str());

  return 0;
}

In the following, we describe how to compile and run the above C++ example.

cd /tmp
git clone https://github.com/k2-fsa/sherpa-onnx
cd sherpa-onnx
mkdir build-shared
cd build-shared

cmake  -DSHERPA_ONNX_ENABLE_C_API=ON  -DCMAKE_BUILD_TYPE=Release  -DBUILD_SHARED_LIBS=ON  -DCMAKE_INSTALL_PREFIX=/tmp/sherpa-onnx/shared  ..

make
make install

You can find required header file and library files inside /tmp/sherpa-onnx/shared.

Assume you have saved the above example file as /tmp/test-piper.cc. Then you can compile it with the following command:

g++   -std=c++17   -I /tmp/sherpa-onnx/shared/include   -L /tmp/sherpa-onnx/shared/lib   -lsherpa-onnx-cxx-api   -lsherpa-onnx-c-api   -lonnxruntime   -o /tmp/test-piper   /tmp/test-piper.cc

Now you can run

cd /tmp

# Assume you have downloaded the model and extracted it to /tmp
./test-piper

You probably need to run

# For Linux
export LD_LIBRARY_PATH=/tmp/sherpa-onnx/shared/lib:$LD_LIBRARY_PATH

# For macOS
export DYLD_LIBRARY_PATH=/tmp/sherpa-onnx/shared/lib:$DYLD_LIBRARY_PATH

before you run /tmp/test-piper.

Please see the documentation at

https://k2-fsa.github.io/sherpa/onnx/c-api/index.html

Rust API

Click to expand

You can use the following code to play with vits-piper-de_DE-thorsten_emotional-medium with Rust API.

use sherpa_onnx::{
    GenerationConfig, OfflineTts, OfflineTtsConfig, OfflineTtsVitsModelConfig,
};

fn main() {
    let config = OfflineTtsConfig {
        model: sherpa_onnx::OfflineTtsModelConfig {
            vits: OfflineTtsVitsModelConfig {
                model: Some("vits-piper-de_DE-thorsten_emotional-medium/de_DE-thorsten_emotional-medium.onnx".into()),
                tokens: Some("vits-piper-de_DE-thorsten_emotional-medium/tokens.txt".into()),
                data_dir: Some("vits-piper-de_DE-thorsten_emotional-medium/espeak-ng-data".into()),
                ..Default::default()
            },
            num_threads: 2,
            debug: false,
            ..Default::default()
        },
        ..Default::default()
    };

    let tts = OfflineTts::create(&config).expect("Failed to create OfflineTts");

    println!("Sample rate: {}", tts.sample_rate());
    println!("Num speakers: {}", tts.num_speakers());

    let text = "Alles hat ein Ende, nur die Wurst hat zwei.";

    let gen_config = GenerationConfig {
        sid: 0,
        speed: 1.0,
        ..Default::default()
    };

    let audio = tts
        .generate_with_config(
            text,
            &gen_config,
            Some(|_samples: &[f32], progress: f32| -> bool {
                println!("Progress: {:.1}%", progress * 100.0);
                true
            }),
        )
        .expect("Generation failed");

    let filename = "./test.wav";
    if audio.save(filename) {
        println!("Saved to: {}", filename);
    } else {
        eprintln!("Failed to save {}", filename);
    }
}

Please refer to the Rust API documentation for how to build and run the above Rust example.

Node.js (addon) API

Click to expand

You need to install the sherpa-onnx-node npm package first:

npm install sherpa-onnx-node

You can use the following code to play with vits-piper-de_DE-thorsten_emotional-medium with the Node.js addon API.

const sherpa_onnx = require('sherpa-onnx-node');

function createOfflineTts() {
  const config = {
    model: {
      vits: {
        model: 'vits-piper-de_DE-thorsten_emotional-medium/de_DE-thorsten_emotional-medium.onnx',
        tokens: 'vits-piper-de_DE-thorsten_emotional-medium/tokens.txt',
        dataDir: 'vits-piper-de_DE-thorsten_emotional-medium/espeak-ng-data',
      },
      debug: true,
      numThreads: 1,
      provider: 'cpu',
    },
    maxNumSentences: 1,
  };
  return new sherpa_onnx.OfflineTts(config);
}

const tts = createOfflineTts();

const text = 'Alles hat ein Ende, nur die Wurst hat zwei.';

const generationConfig = new sherpa_onnx.GenerationConfig({
  sid: 0,
  speed: 1.0,
  silenceScale: 0.2,
});

let start = Date.now();
const audio = tts.generate({text, generationConfig});
let stop = Date.now();
const elapsed_seconds = (stop - start) / 1000;
const duration = audio.samples.length / audio.sampleRate;
const real_time_factor = elapsed_seconds / duration;
console.log('Wave duration', duration.toFixed(3), 'seconds');
console.log('Elapsed', elapsed_seconds.toFixed(3), 'seconds');
console.log(
    `RTF = ${elapsed_seconds.toFixed(3)}/${duration.toFixed(3)} =`,
    real_time_factor.toFixed(3));

const filename = 'test.wav';
sherpa_onnx.writeWave(
    filename, {samples: audio.samples, sampleRate: audio.sampleRate});

console.log(`Saved to ${filename}`);

Please refer to the Node.js addon API documentation for more details.

Dart API

Click to expand

You can use the following code to play with vits-piper-de_DE-thorsten_emotional-medium with Dart API.

import 'package:sherpa_onnx/sherpa_onnx.dart' as sherpa_onnx;

void main() {
  final vits = sherpa_onnx.OfflineTtsVitsModelConfig(
    model: 'vits-piper-de_DE-thorsten_emotional-medium/de_DE-thorsten_emotional-medium.onnx',
    tokens: 'vits-piper-de_DE-thorsten_emotional-medium/tokens.txt',
    dataDir: 'vits-piper-de_DE-thorsten_emotional-medium/espeak-ng-data',
  );

  final modelConfig = sherpa_onnx.OfflineTtsModelConfig(
    vits: vits,
    numThreads: 1,
    debug: true,
  );
  final config = sherpa_onnx.OfflineTtsConfig(
    model: modelConfig,
    maxNumSenetences: 1,
  );

  final tts = sherpa_onnx.OfflineTts(config);
  final genConfig = sherpa_onnx.OfflineTtsGenerationConfig(
    sid: 0,
    speed: 1.0,
    silenceScale: 0.2,
  );
  final audio = tts.generateWithConfig(text: 'Alles hat ein Ende, nur die Wurst hat zwei.', config: genConfig);
  tts.free();

  sherpa_onnx.writeWave(
    filename: 'test.wav',
    samples: audio.samples,
    sampleRate: audio.sampleRate,
  );
  print('Saved to test.wav');
}

Please refer to the Dart API documentation for more details.

Swift API

Click to expand

You can use the following code to play with vits-piper-de_DE-thorsten_emotional-medium with Swift API.

func run() {
  let vits = sherpaOnnxOfflineTtsVitsModelConfig(
    model: "vits-piper-de_DE-thorsten_emotional-medium/de_DE-thorsten_emotional-medium.onnx",
    lexicon: "",
    tokens: "vits-piper-de_DE-thorsten_emotional-medium/tokens.txt",
    dataDir: "vits-piper-de_DE-thorsten_emotional-medium/espeak-ng-data"
  )
  let modelConfig = sherpaOnnxOfflineTtsModelConfig(vits: vits)
  var ttsConfig = sherpaOnnxOfflineTtsConfig(model: modelConfig)

  let tts = SherpaOnnxOfflineTtsWrapper(config: &ttsConfig)

  let text = "Alles hat ein Ende, nur die Wurst hat zwei."
  var genConfig = SherpaOnnxGenerationConfigSwift()
  genConfig.sid = 0
  genConfig.speed = 1.0
  genConfig.silenceScale = 0.2

  let audio = tts.generateWithConfig(text: text, config: genConfig, callback: nil, arg: nil)
  let filename = "test.wav"
  let ok = audio.save(filename: filename)
  if ok == 1 {
    print("Saved to \(filename)")
  } else {
    print("Failed to save \(filename)")
  }
}

@main
struct App {
  static func main() {
    run()
  }
}

Please refer to the Swift API documentation for more details.

C# API

Click to expand

You can use the following code to play with vits-piper-de_DE-thorsten_emotional-medium with C# API.

using SherpaOnnx;

var config = new OfflineTtsConfig();
config.Model.Vits.Model = "vits-piper-de_DE-thorsten_emotional-medium/de_DE-thorsten_emotional-medium.onnx";
config.Model.Vits.Tokens = "vits-piper-de_DE-thorsten_emotional-medium/tokens.txt";
config.Model.Vits.DataDir = "vits-piper-de_DE-thorsten_emotional-medium/espeak-ng-data";
config.Model.NumThreads = 1;
config.Model.Debug = 1;
config.Model.Provider = "cpu";
config.MaxNumSentences = 1;

var tts = new OfflineTts(config);
var text = "Alles hat ein Ende, nur die Wurst hat zwei.";

OfflineTtsGenerationConfig genConfig = new OfflineTtsGenerationConfig();
genConfig.Sid = 0;
genConfig.Speed = 1.0f;
genConfig.SilenceScale = 0.2f;

var audio = tts.GenerateWithConfig(text, genConfig, null);
var ok = audio.SaveToWaveFile("./test.wav");

if (ok)
{
  Console.WriteLine("Saved to ./test.wav");
}
else
{
  Console.WriteLine("Failed to save ./test.wav");
}

Please refer to the C# API documentation for more details.

Kotlin API

Click to expand

You can use the following code to play with vits-piper-de_DE-thorsten_emotional-medium with Kotlin API.

package com.k2fsa.sherpa.onnx

fun main() {
  var config = OfflineTtsConfig(
    model = OfflineTtsModelConfig(
      vits = OfflineTtsVitsModelConfig(
        model = "vits-piper-de_DE-thorsten_emotional-medium/de_DE-thorsten_emotional-medium.onnx",
        tokens = "vits-piper-de_DE-thorsten_emotional-medium/tokens.txt",
        dataDir = "vits-piper-de_DE-thorsten_emotional-medium/espeak-ng-data",
      ),
      numThreads = 1,
      debug = true,
    ),
  )
  val tts = OfflineTts(config = config)
  val genConfig = GenerationConfig(
    sid = 0,
    speed = 1.0f,
    silenceScale = 0.2f,
  )
  val audio = tts.generateWithConfigAndCallback(
    text = "Alles hat ein Ende, nur die Wurst hat zwei.",
    config = genConfig,
    callback = ::callback,
  )
  audio.save(filename = "test.wav")
  tts.release()
  println("Saved to test.wav")
}

fun callback(samples: FloatArray): Int {
  // 1 means to continue
  // 0 means to stop
  return 1
}

Please refer to the Kotlin API documentation for more details.

Java API

Click to expand

You can use the following code to play with vits-piper-de_DE-thorsten_emotional-medium with Java API.

import com.k2fsa.sherpa.onnx.*;

public class TtsDemo {
  public static void main(String[] args) {
    var vits = new OfflineTtsVitsModelConfig();
    vits.setModel("vits-piper-de_DE-thorsten_emotional-medium/de_DE-thorsten_emotional-medium.onnx");
    vits.setTokens("vits-piper-de_DE-thorsten_emotional-medium/tokens.txt");
    vits.setDataDir("vits-piper-de_DE-thorsten_emotional-medium/espeak-ng-data");

    var modelConfig = new OfflineTtsModelConfig();
    modelConfig.setVits(vits);
    modelConfig.setNumThreads(1);
    modelConfig.setDebug(true);

    var config = new OfflineTtsConfig();
    config.setModel(modelConfig);
    config.setMaxNumSentences(1);

    var tts = new OfflineTts(config);
    var text = "Alles hat ein Ende, nur die Wurst hat zwei.";

    var genConfig = new GenerationConfig();
    genConfig.setSid(0);
    genConfig.setSpeed(1.0f);
    genConfig.setSilenceScale(0.2f);

    var audio = tts.generateWithConfigAndCallback(text, genConfig, (samples) -> {
      // 1 means to continue, 0 means to stop
      return 1;
    });

    audio.save("test.wav");
    tts.release();
    System.out.println("Saved to test.wav");
  }
}

Please refer to the Java API documentation for more details.

Pascal API

Click to expand

You can use the following code to play with vits-piper-de_DE-thorsten_emotional-medium with Pascal API.

program test_piper;

{$mode objfpc}

uses
  SysUtils,
  sherpa_onnx;

var
  Config: TSherpaOnnxOfflineTtsConfig;
  Tts: TSherpaOnnxOfflineTts;
  Audio: TSherpaOnnxGeneratedAudio;
  GenConfig: TSherpaOnnxGenerationConfig;

begin
  FillChar(Config, SizeOf(Config), 0);

  Config.Model.Vits.Model := 'vits-piper-de_DE-thorsten_emotional-medium/de_DE-thorsten_emotional-medium.onnx';
  Config.Model.Vits.Tokens := 'vits-piper-de_DE-thorsten_emotional-medium/tokens.txt';
  Config.Model.Vits.DataDir := 'vits-piper-de_DE-thorsten_emotional-medium/espeak-ng-data';
  Config.Model.NumThreads := 1;
  Config.Model.Debug := True;
  Config.MaxNumSentences := 1;

  Tts := TSherpaOnnxOfflineTts.Create(@Config);

  GenConfig.Sid := 0;
  GenConfig.Speed := 1.0;
  GenConfig.SilenceScale := 0.2;

  Audio := Tts.GenerateWithConfig('Alles hat ein Ende, nur die Wurst hat zwei.', @GenConfig, nil);

  WriteWave('./test.wav', Audio.Samples, Audio.N, Audio.SampleRate);

  WriteLn('Saved to ./test.wav');

  Audio.Free;
  Tts.Free;
end.

Please refer to the Pascal API documentation for more details.

Go API

Click to expand

You can use the following code to play with vits-piper-de_DE-thorsten_emotional-medium with Go API.

package main

import (
	"fmt"
	sherpa "github.com/k2-fsa/sherpa-onnx-go/sherpa_onnx"
)

func main() {
	config := sherpa.OfflineTtsConfig{
		Model: sherpa.OfflineTtsModelConfig{
			Vits: sherpa.OfflineTtsVitsModelConfig{
				Model:   "vits-piper-de_DE-thorsten_emotional-medium/de_DE-thorsten_emotional-medium.onnx",
				Tokens:  "vits-piper-de_DE-thorsten_emotional-medium/tokens.txt",
				DataDir: "vits-piper-de_DE-thorsten_emotional-medium/espeak-ng-data",
			},
			NumThreads: 1,
			Debug:      true,
		},
		MaxNumSentences: 1,
	}

	tts := sherpa.NewOfflineTts(&config)
	defer tts.Delete()

	text := "Alles hat ein Ende, nur die Wurst hat zwei."

	genConfig := sherpa.GenerationConfig{
		Sid:          0,
		Speed:        1.0,
		SilenceScale: 0.2,
	}

	audio := tts.GenerateWithConfig(text, &genConfig, nil)

	filename := "./test.wav"
	sherpa.WriteWave(filename, audio.Samples, audio.SampleRate)

	fmt.Printf("Saved to %s\n", filename)
}

Please refer to the Go API documentation for more details.

Samples

For the following text:

Alles hat ein Ende, nur die Wurst hat zwei.

sample audios for different speakers are listed below:

Speaker 0

Speaker 1

Speaker 2

Speaker 3

Speaker 4

Speaker 5

Speaker 6

Speaker 7