Rework TTS algorithm

This commit is contained in:
Jan-Lukas Else 2023-01-24 18:53:24 +01:00
parent 720fc62919
commit c8229ab28d
1 changed files with 26 additions and 36 deletions

62
tts.go
View File

@ -13,11 +13,11 @@ import (
"net/url" "net/url"
"path" "path"
"strings" "strings"
"sync"
"github.com/carlmjohnson/requests" "github.com/carlmjohnson/requests"
"go.goblog.app/app/pkgs/bufferpool" "go.goblog.app/app/pkgs/bufferpool"
"go.goblog.app/app/pkgs/mp3merge" "go.goblog.app/app/pkgs/mp3merge"
"golang.org/x/sync/errgroup"
) )
const ttsParameter = "tts" const ttsParameter = "tts"
@ -72,52 +72,41 @@ func (a *goBlog) createPostTTSAudio(p *post) error {
parts = append(parts, strings.Split(htmlText(a.postHtml(&postHtmlOptions{p: p})), "\n\n")...) parts = append(parts, strings.Split(htmlText(a.postHtml(&postHtmlOptions{p: p})), "\n\n")...)
// Create TTS audio for each part // Create TTS audio for each part
partWriters := make([]io.Writer, len(parts)) partReaders := []io.Reader{}
partReaders := make([]io.Reader, len(parts)) var g errgroup.Group
for i := range parts { for _, part := range parts {
buf := bufferpool.Get() part := part
defer bufferpool.Put(buf) pr, pw := io.Pipe()
partWriters[i] = buf defer func() {
partReaders[i] = buf pw.Close()
} }()
errs := make([]error, len(parts)) partReaders = append(partReaders, pr)
var wg sync.WaitGroup g.Go(func() error {
for i, part := range parts {
// Increase wait group
wg.Add(1)
go func(i int, part string) {
defer wg.Done()
// Build SSML // Build SSML
ssml := "<speak>" + html.EscapeString(part) + "<break time=\"500ms\"/></speak>" ssml := "<speak>" + html.EscapeString(part) + "<break time=\"500ms\"/></speak>"
// Create TTS audio // Create TTS audio
err := a.createTTSAudio(lang, ssml, partWriters[i]) err := a.createTTSAudio(lang, ssml, pw)
if err != nil { _ = pw.CloseWithError(err)
errs[i] = err
return
}
}(i, part)
}
// Wait for all parts to be created
wg.Wait()
// Check if any errors occurred
for _, err := range errs {
if err != nil {
return err return err
} })
} }
// Merge partsBuffers into final buffer // Merge parts together (needs buffer because the hash is needed before the file can be uploaded)
final := bufferpool.Get() buf := bufferpool.Get()
defer bufferpool.Put(final) defer bufferpool.Put(buf)
hash := sha256.New() hash := sha256.New()
if err := mp3merge.MergeMP3(io.MultiWriter(final, hash), partReaders...); err != nil { err := mp3merge.MergeMP3(io.MultiWriter(buf, hash), partReaders...)
if err != nil {
return err
}
// Check if other errors appeared
if err = g.Wait(); err != nil {
return err return err
} }
// Save audio // Save audio
loc, err := a.saveMediaFile(fmt.Sprintf("%x.mp3", hash.Sum(nil)), final) loc, err := a.saveMediaFile(fmt.Sprintf("%x.mp3", hash.Sum(nil)), buf)
if err != nil { if err != nil {
return err return err
} }
@ -125,6 +114,7 @@ func (a *goBlog) createPostTTSAudio(p *post) error {
return errors.New("no media location for tts audio") return errors.New("no media location for tts audio")
} }
// Check existing tts parameter
if old := p.firstParameter(ttsParameter); old != "" && old != loc { if old := p.firstParameter(ttsParameter); old != "" && old != loc {
// Already has tts audio, but with different location // Already has tts audio, but with different location
// Try to delete the old audio file // Try to delete the old audio file