Skip to content

Commit

Permalink
add: request sharding, diskless playback; fix: hegedustibor#10, heged…
Browse files Browse the repository at this point in the history
  • Loading branch information
kendfss committed Dec 16, 2022
1 parent 04f3cda commit 5618c8d
Show file tree
Hide file tree
Showing 8 changed files with 260 additions and 44 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

### Requirement:
- mplayer (optional)
- Internet connection
- [hajimehoshi/oto Prerequisites](https://github.com/hajimehoshi/oto/blob/main/README.md#prerequisite)

### Install
```
Expand Down Expand Up @@ -47,7 +49,7 @@ speech.Speak("Your sentence.")

### Use tts without external player

Note: The "Native" handler works around the Oto librery, see the ["Prerequisite"](https://github.com/hajimehoshi/oto/blob/main/README.md#prerequisite) section to work with this handler
Note: The "Native" handler depends on the Oto librery, [see the "Prerequisite" section](https://github.com/hajimehoshi/oto/blob/main/README.md#prerequisite) for instructions on environment configuration to use it!

```go
import (
Expand Down
5 changes: 4 additions & 1 deletion handlers/Handler.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package handlers

import "io"

type PlayerInterface interface {
Play(fileName string) error
}
PlayBuf(io.Reader) error
}
8 changes: 7 additions & 1 deletion handlers/MPlayer.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
package handlers

import (
"errors"
"io"
"os/exec"
)

type MPlayer struct {}
type MPlayer struct{}

func (MPlayer *MPlayer) Play(fileName string) error {
mplayer := exec.Command("mplayer", "-cache", "8092", "-", fileName)
return mplayer.Run()
}

func (MPlayer *MPlayer) PlayBuf(buf io.Reader) error {
return errors.New("MPlayer.PlayBuf: Not implemented")
}
28 changes: 15 additions & 13 deletions handlers/Native.go
Original file line number Diff line number Diff line change
@@ -1,34 +1,37 @@
package handlers

import (
"bytes"
"io"
"os"
"time"

"github.com/hajimehoshi/go-mp3"
"github.com/hajimehoshi/oto/v2"
mp3 "github.com/hajimehoshi/go-mp3"
oto "github.com/hajimehoshi/oto/v2"
)

type Native struct {
}
type Native struct{}

func (n *Native) Play(fileName string) error {
// Read the mp3 file into memory
fileBytes, err := os.ReadFile(fileName)
f, err := os.Open(fileName)
if err != nil {
return err
}
defer f.Close()
return n.PlayBuf(f)
}

fileBytesReader := bytes.NewReader(fileBytes)

// PlayBuf plays an mp3 file straight from the buffer
func (n *Native) PlayBuf(buf io.Reader) error {
// Decode file
decodedMp3, err := mp3.NewDecoder(fileBytesReader)
decodedMp3, err := mp3.NewDecoder(buf)
if err != nil {
return err
}

numOfChannels := 2
audioBitDepth := 2
const (
numOfChannels = 2
audioBitDepth = 2
)

otoCtx, readyChan, err := oto.NewContext(decodedMp3.SampleRate(), numOfChannels, audioBitDepth)
if err != nil {
Expand All @@ -41,7 +44,6 @@ func (n *Native) Play(fileName string) error {
player.Play()

for player.IsPlaying() {
time.Sleep(time.Millisecond)
}

return player.Close()
Expand Down
60 changes: 35 additions & 25 deletions htgotts.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import (
"encoding/hex"
"fmt"
"io"
"net/http"
"net/url"
"os"

"github.com/hegedustibor/htgo-tts/handlers"
Expand Down Expand Up @@ -44,6 +42,14 @@ func (speech *Speech) CreateSpeechFile(text string, fileName string) (string, er
return f, nil
}

func (speech *Speech) PlayString(text string) (err error) {
buf, err := speech.fetch(text)
if err == nil {
return speech.Handler.PlayBuf(buf)
}
return
}

// Plays an existent .mp3 file
func (speech *Speech) PlaySpeechFile(fileName string) error {
if speech.Handler == nil {
Expand All @@ -56,9 +62,8 @@ func (speech *Speech) PlaySpeechFile(fileName string) error {

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

var err error
generatedHashName := speech.generateHashName(text)
generatedHashName := speech.fnameFromHash(text)

fileName, err := speech.CreateSpeechFile(text, generatedHashName)
if err != nil {
Expand All @@ -68,46 +73,51 @@ func (speech *Speech) Speak(text string) error {
return speech.PlaySpeechFile(fileName)
}

/**
* Create the folder if does not exists.
*/
// Read downloads speech and plays it without writing to disk
func (speech *Speech) Read(text string) error {
buf, err := speech.fetch(text)
if err != nil {
return err
}
return speech.Handler.PlayBuf(buf)
}

// 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)
return os.MkdirAll(folder, 0o700)
}

dir.Close()
return nil
}

/**
* Download the voice file if does not exists.
*/
// 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
if os.IsNotExist(err) {
buf, err := speech.fetch(text)
if err != nil {
return err
}

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

_, err = io.Copy(output, buf)
}

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

f.Close()
return nil
}

func (speech *Speech) generateHashName(name string) string {
hash := md5.Sum([]byte(name))
func (speech *Speech) fnameFromHash(text string) string {
hash := md5.Sum([]byte(text))
return fmt.Sprintf("%s_%s", speech.Language, hex.EncodeToString(hash[:]))
}
79 changes: 77 additions & 2 deletions htgotts_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package htgotts

import (
"fmt"
"testing"

"github.com/hegedustibor/htgo-tts/handlers"
"github.com/hegedustibor/htgo-tts/voices"

"testing"
)

func TestSpeech_Speak(t *testing.T) {
Expand Down Expand Up @@ -48,3 +49,77 @@ func TestSpeech_(t *testing.T) {
}
speech.PlaySpeechFile(f)
}

func TestChunking(t *testing.T) {
tests := []string{
"the quick brown fox jumps over the lazy dog",
`our father, who art in heaven, hallowed be thy name.
thine kingdom come, thy will be done on earth, as it is in heaven.
give us this day, our daily bread, and forgive us this day as we forgive those who have trespassed against us.
holy mary mother of god pray for our sins, now and at the hour of our death; amen.`,
"the quick ∂brown fox∂≈© juçmps over the lazy dogø",
`Medical assistance in dying (MAID) has been available in Canada since 2016 and is set to expand in March 2023, extending eligibility to those with a mental illness.
Bill C-7 would allow individuals seeking MAID to apply solely on the basis of a mental disorder. Prior to the bill’s passage, MAID eligibility was based on having a “grievous and irremediable medical condition,” according to a report from the Canadian government on the practice.
Creighton School of Medicine professor Charles Camosy said Wednesday on “Tucker Carlson Tonight” the bill would allow “mature minors” to be euthanized by state doctors without the consent of their parents.
Camosy argued that the MAID practice exists for several groups already.
“We’ve got the homeless, we talked about that last time. The poor. The disabled. Those with chronic pain. And then right before coming on, I researched the physicians group in Quebec that wants to kill newborn infants. That’s what’s coming next,” he told host Tucker Carlson.
“This is what happens when autonomy just goes nuts.”
The medical humanities professor said health care has been “hyper-secularized” in recent years and is based on “cost-benefit analysis.”
Camosy said he doesn’t think this type of law would come into effect in the U.S., but added doctors need to focus on saving the lives of their patients. “What we need to do, is support in whatever way [we] can, health care that is about caring, not killing.”
“There’s a coalition of people coming up with a brand new medical school, the Padre Pio School of Medicine in 2026, that is going to do this very clearly, very ably,” he added.
“We have to get off the couch and do something about this for those of us that see the writing on the wall here,” he concluded.
Oregon was the first state in the United States to approve medically assisted suicide, with a law going into effect in 1997. California, Colorado, Hawaii, Maine, New Jersey, New Mexico, Vermont, Washington state and Washington, D.C., have approved similar laws, all with residency requirements. Montana’s Supreme Court has ruled that state law does not prohibit medical aid in dying.
`,
`Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`,
}

t.Run("cleanText", func(t *testing.T) {
t.Run("constants", func(t *testing.T) {
// test that things that are already clean do not lose content
indices := []int{0, 1}
for _, i := range indices {
want := tests[i]
have := cleanText(want)
if have != want {
t.Fatalf("test #%d\n\toutput is not the same as input:\n\t\twant:\t%v\n\t\thave:\t%v", i, want, have)
}
}
})
})

t.Run("chunkate", func(t *testing.T) {
for i, test := range tests {
want := cleanText(test)
ctr := -1
have := []byte{}
for chunk := range chunkate(want) {
ctr++
switch width := len(chunk); {
case width == 0 || width > chunkSizeLimit:
t.Fatalf("\ntest #%d\tchunk #%d:\n%v", i, ctr, string(chunk))
default:
have = append(have, chunk...)
}
}
if string(have) != want {
fmt.Printf("test #%d - \"%s...\"\n", i, truncate(want, 15))
t.Fatalf("output is not the same as input:\n\twant:\t%s\n\thave:\t%s", want, have)
}
}
})
}
Loading

0 comments on commit 5618c8d

Please sign in to comment.