BjoernSchilberg / steve

Steve a coffee mumble bot
MIT License
0 stars 1 forks source link

Integrate Text-to-Speech-System (TTS) aka Vorleseautomat #11

Open BjoernSchilberg opened 4 years ago

BjoernSchilberg commented 4 years ago

There are several TTS (Text To Speech) engines avaliable you can find a list here: https://elinux.org/RPi_Text_to_Speech_(Speech_Synthesis)

Favorit is https://android.googlesource.com/platform/external/svox/ (pico2wave)

Simple example using espeak / espeak-ng / festival.

package main

import (
    "os/exec"
    "log"
)

func main() {
    s := "Make steve speak"
    cmd := exec.Command("espeak-ng", s)
    if err := cmd.Run(); err != nil {
        log.Fatal(err)
    }
}
BjoernSchilberg commented 4 years ago

Or with Google Text to Speech API. Example based on https://github.com/hegedustibor/htgo-tts.

package main

import (
    "fmt"
    "io"
    "net/http"
    "net/url"
    "os"
    "os/exec"
)

/**
 * Required:
 * - mplayer
 *
 * Use:
 *
 * speech := Speech{Folder: "audio", Language: "en"}
 */

// Speech struct
type Speech struct {
    Folder   string
    Language string
}

// Speak downloads speech and plays it using mplayer
func (speech *Speech) Speak(text string) error {

    fileName := speech.Folder + "/" + text + ".mp3"

    var err error
    if err = speech.createFolderIfNotExists(speech.Folder); err != nil {
        return err
    }
    if err = speech.downloadIfNotExists(fileName, text); err != nil {
        return err
    }

    return speech.play(fileName)
}

/**
 * Create the folder if does not exists.
 */
func (speech *Speech) createFolderIfNotExists(folder string) error {
    dir, err := os.Open(folder)
    if os.IsNotExist(err) {
        return os.MkdirAll(folder, 0700)
    }

    dir.Close()
    return nil
}

/**
 * Download the voice file if does not exists.
 */
func (speech *Speech) downloadIfNotExists(fileName string, text string) error {
    f, err := os.Open(fileName)
    if err != nil {
        url := fmt.Sprintf("http://translate.google.com/translate_tts?ie=UTF-8&total=1&idx=0&textlen=32&client=tw-ob&q=%s&tl=%s", url.QueryEscape(text), speech.Language)
        response, err := http.Get(url)
        if err != nil {
            return err
        }
        defer response.Body.Close()

        output, err := os.Create(fileName)
        if err != nil {
            return err
        }

        _, err = io.Copy(output, response.Body)
        return err
    }

    f.Close()
    return nil
}

/**
 * Play voice file.
 */
func (speech *Speech) play(fileName string) error {
    mplayer := exec.Command("mplayer", "-cache", "8092", "-", fileName)
    return mplayer.Run()
}

func main() {
    speech := Speech{Folder: "audio", Language: "de"}
    speech.Speak("Fliege zum Mond.")
}