Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ttsaas update #2

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
FROM golang:1.17.2-alpine AS builder

# Set the Current Working Directory inside the container
WORKDIR /app

# Copy go mod and sum files
COPY go.mod go.sum ./

RUN go mod download

# Copy the source from the current directory to the Working Directory inside the container
COPY . .

RUN go build -o ttsaas

FROM alpine:3.12

RUN apk update \
&& apk add bash \
&& apk add ffmpeg \
&& apk add mplayer \
&& rm -rf /var/chache/apk/* \
&& mkdir -p /app/audio \
&& addgroup -S app && adduser -S app -G app \
&& chown -R app:app /app

USER app

WORKDIR /app

COPY --from=builder /app/ttsaas .

EXPOSE 1337

ENTRYPOINT ["./ttsaas"]
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,14 @@ The api can be used as a source for audio tags. For example:
<source src="http://localhost/hello%20world" type="audio/mpeg">
</audio>
```

## Docker

### Build
To build the docker image, run `docker build -t vektor/ttsaas:1.1 .`

### Run
To run the docker image, run `docker run -p 1337:1337 vektor/ttsaas:1.1`

(This will map to port 1337, change portnumber (`1337:<change_me>`) to map to another port)

5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module ttsaas.com

go 1.17

require github.com/hegedustibor/htgo-tts v0.0.0-20211106065519-4b33b08f698f
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
github.com/hegedustibor/htgo-tts v0.0.0-20211106065519-4b33b08f698f h1:9hj9NB/nSMz1AF/uw1J51gNmbfInP8oQ446C/50o1gE=
github.com/hegedustibor/htgo-tts v0.0.0-20211106065519-4b33b08f698f/go.mod h1:Uqnv3qFrs2WtaeO2/+PQ35x4HdD4u2ZAX/PcQEEP5VY=
116 changes: 60 additions & 56 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,78 +1,82 @@
package main

import (
"fmt"
"github.com/hegedustibor/htgo-tts"
"github.com/kennygrant/sanitize"
"log"
"net/http"
"os"
"os/exec"
"strconv"
"strings"
"time"
"fmt"
"io"
"log"
"net/http"
"os"
"os/exec"
"strconv"
"strings"
"time"

htgotts "github.com/hegedustibor/htgo-tts"
)

const audioFolder = "audio"
const fileName = "speech"
const defaultPort = 1337
const volume = 2

func main() {
http.HandleFunc("/", serveSpeech)
port := defaultPort
if os.Getenv("TTSAAS_PORT") != "" {
var err error
port, err = strconv.Atoi(os.Getenv("TTSAAS_PORT"))
if err != nil {
log.Fatalf("Port environment variable set, but could not convert it to int %s\n", err)
}
}
log.Printf("Starting text to speech as a service on port %d\n", port)
if err := http.ListenAndServe(":"+strconv.Itoa(port), nil); err != nil {
panic(err)
}
http.HandleFunc("/", serveSpeech)
port := defaultPort
if os.Getenv("TTSAAS_PORT") != "" {
var err error
port, err = strconv.Atoi(os.Getenv("TTSAAS_PORT"))
if err != nil {
log.Fatalf("Port environment variable set, but could not convert it to int %s\n", err)
}
}
log.Printf("Starting text to speech as a service on port %d\n", port)
if err := http.ListenAndServe(":"+strconv.Itoa(port), nil); err != nil {
panic(err)
}
}

func serveSpeech(w http.ResponseWriter, r *http.Request) {
addCORSHeader(w)
addCORSHeader(w)
b, _ := io.ReadAll(r.Body)
urlParts := strings.Split(strings.TrimPrefix(r.URL.Path, "/"), "/")
if len(urlParts) < 1 {
http.Error(w, "bad request", http.StatusBadRequest)
log.Println("Bad request")
return
}
sentence := string(b)

urlParts := strings.Split(strings.TrimPrefix(r.URL.Path, "/"), "/")
if len(urlParts) < 1 {
http.Error(w, "bad request", http.StatusBadRequest)
log.Println("Bad request")
return
}
sentence := sanitize.BaseName(urlParts[0])
if len(sentence) == 0 {
fmt.Fprintln(w, "TTSAAS is running...")
return
}

// Save audio file to audio folder
speech := htgotts.Speech{Folder: audioFolder, Language: "no"}
err := speech.Speak(sentence)
if err != nil {
http.Error(w, "server error", http.StatusInternalServerError)
log.Printf("Error converting text to speech: %s\n", err)
return
speech := htgotts.Speech{Folder: audioFolder, Language: "no"}
speechFile, err := speech.CreateSpeechFile(sentence,fileName)
if err != nil {
log.Printf("CreateSpeechFile fail %v", err)
}

fileURI := audioFolder + "/" + sentence + ".mp3"
loudFileURI := audioFolder + "/" + sentence + "LOUD" + ".mp3"
cmdString := fmt.Sprintf("ffmpeg -y -i %s -filter:a \"volume=%d\" %s", fileURI, volume, loudFileURI)

cmd := exec.Command("bash", "-c", cmdString)
buf, err := cmd.Output()
if err != nil {
http.Error(w, "server error", http.StatusInternalServerError)
log.Printf("Error increasing audio volume: %s: %s\n", err, string(buf))
log.Printf(cmdString)
return
}
fileURI := speechFile
loudFileURI := audioFolder + "/" + fileName + "LOUD" + ".mp3"
cmdString := fmt.Sprintf("ffmpeg -y -i %s -filter:a \"volume=%d\" %s", fileURI, volume, loudFileURI)
cmd := exec.Command("bash", "-c", cmdString)
buf, err := cmd.CombinedOutput()
e := os.Remove(speechFile)
if (err != nil || e != nil) {
http.Error(w, "server error", http.StatusInternalServerError)
log.Printf("Error increasing audio volume: %s: %s\n", err, string(buf))
log.Printf(cmdString)
return
}

time.Sleep(500 * time.Millisecond)
http.ServeFile(w, r, loudFileURI)
time.Sleep(500 * time.Millisecond)
http.ServeFile(w, r, loudFileURI)
}

func addCORSHeader(w http.ResponseWriter) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers",
"Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers",
"Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
}