Nik Afiq 5238298b55
Some checks failed
CI / test (push) Successful in 6s
CI / build-ai-gateway (push) Failing after 28s
CI / build-ha-gateway (push) Failing after 24s
CI / build-discord-bot (push) Failing after 29s
Add TTS model components and inference server
- Implemented core model components in `modules.py` including various convolutional layers and normalization techniques.
- Added transformation functions in `transforms.py` for piecewise rational quadratic transformations.
- Created utility functions in `utils.py` for checkpoint management, logging, and hyperparameter handling.
- Introduced monotonic alignment functionality with Cython optimization in `monotonic_align`.
- Developed a minimal inference server in `server.py` to handle synthesis requests.
- Updated requirements to include necessary dependencies for Cython and scipy.
2026-07-24 22:38:36 +09:00

56 lines
1.5 KiB
Go

// Package ffmpeg implements driven.AudioEncoder: WAV framing done by hand,
// then a shell-out to the system ffmpeg binary to transcode to AAC/M4A,
// matching uma-tts-api's pydub `.export(..., format="ipod")` step
// (mimetype audio/aac, despite the "ipod" format name being an M4A/AAC
// container alias).
package ffmpeg
import (
"bytes"
"context"
"fmt"
"os"
"os/exec"
)
type Encoder struct{}
func NewEncoder() *Encoder {
return &Encoder{}
}
// Encode transcodes PCM samples to AAC. The output goes to a temp file
// rather than a stdout pipe because the M4A/MP4 muxer needs a seekable
// destination to write its moov atom.
func (e *Encoder) Encode(ctx context.Context, pcm []float32, sampleRate int) ([]byte, string, error) {
wavBytes := encodeWAV(pcm, sampleRate)
tmpFile, err := os.CreateTemp("", "tts-gateway-*.m4a")
if err != nil {
return nil, "", fmt.Errorf("ffmpeg: create temp output file: %w", err)
}
tmpPath := tmpFile.Name()
_ = tmpFile.Close()
defer os.Remove(tmpPath)
cmd := exec.CommandContext(ctx, "ffmpeg",
"-y",
"-f", "wav", "-i", "pipe:0",
"-f", "ipod",
tmpPath,
)
cmd.Stdin = bytes.NewReader(wavBytes)
var stderr bytes.Buffer
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
return nil, "", fmt.Errorf("ffmpeg: transcode failed: %w: %s", err, stderr.String())
}
data, err := os.ReadFile(tmpPath)
if err != nil {
return nil, "", fmt.Errorf("ffmpeg: read transcoded output: %w", err)
}
return data, "audio/aac", nil
}