mirror of
https://github.com/EvolutionAPI/evolution-audio-converter.git
synced 2025-07-13 15:14:50 -06:00
refactor: performance improvements
This commit is contained in:
parent
800acd4c0d
commit
ae14a6c1e2
132
main.go
132
main.go
@ -6,22 +6,44 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
)
|
)
|
||||||
|
|
||||||
func validateAPIKey(c *gin.Context) bool {
|
var (
|
||||||
apiKey := os.Getenv("API_KEY")
|
apiKey string
|
||||||
|
httpClient = &http.Client{}
|
||||||
|
bufferPool = sync.Pool{
|
||||||
|
New: func() interface{} {
|
||||||
|
return new(bytes.Buffer)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// Carrega o arquivo .env
|
||||||
|
err := godotenv.Load()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Erro ao carregar o arquivo .env")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inicializa a variável apiKey
|
||||||
|
apiKey = os.Getenv("API_KEY")
|
||||||
if apiKey == "" {
|
if apiKey == "" {
|
||||||
fmt.Println("API_KEY não configurada no arquivo .env")
|
fmt.Println("API_KEY não configurada no arquivo .env")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateAPIKey(c *gin.Context) bool {
|
||||||
|
if apiKey == "" {
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erro interno no servidor"})
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erro interno no servidor"})
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -43,22 +65,28 @@ func validateAPIKey(c *gin.Context) bool {
|
|||||||
func convertAudioToOpusWithDuration(inputData []byte) ([]byte, int, error) {
|
func convertAudioToOpusWithDuration(inputData []byte) ([]byte, int, error) {
|
||||||
cmd := exec.Command("ffmpeg", "-i", "pipe:0", "-ac", "1", "-ar", "16000", "-c:a", "libopus", "-f", "ogg", "pipe:1")
|
cmd := exec.Command("ffmpeg", "-i", "pipe:0", "-ac", "1", "-ar", "16000", "-c:a", "libopus", "-f", "ogg", "pipe:1")
|
||||||
|
|
||||||
var outBuffer bytes.Buffer
|
outBuffer := bufferPool.Get().(*bytes.Buffer)
|
||||||
var errBuffer bytes.Buffer
|
errBuffer := bufferPool.Get().(*bytes.Buffer)
|
||||||
|
defer bufferPool.Put(outBuffer)
|
||||||
|
defer bufferPool.Put(errBuffer)
|
||||||
|
|
||||||
|
outBuffer.Reset()
|
||||||
|
errBuffer.Reset()
|
||||||
|
|
||||||
cmd.Stdin = bytes.NewReader(inputData)
|
cmd.Stdin = bytes.NewReader(inputData)
|
||||||
cmd.Stdout = &outBuffer
|
cmd.Stdout = outBuffer
|
||||||
cmd.Stderr = &errBuffer
|
cmd.Stderr = errBuffer
|
||||||
|
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, fmt.Errorf("error during conversion: %v, details: %s", err, errBuffer.String())
|
return nil, 0, fmt.Errorf("error during conversion: %v, details: %s", err, errBuffer.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
convertedData := outBuffer.Bytes()
|
convertedData := make([]byte, outBuffer.Len())
|
||||||
|
copy(convertedData, outBuffer.Bytes())
|
||||||
|
|
||||||
|
// Parsing da duração
|
||||||
outputText := errBuffer.String()
|
outputText := errBuffer.String()
|
||||||
|
|
||||||
splitTime := strings.Split(outputText, "time=")
|
splitTime := strings.Split(outputText, "time=")
|
||||||
|
|
||||||
if len(splitTime) < 2 {
|
if len(splitTime) < 2 {
|
||||||
@ -66,7 +94,7 @@ func convertAudioToOpusWithDuration(inputData []byte) ([]byte, int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
re := regexp.MustCompile(`(\d+):(\d+):(\d+\.\d+)`)
|
re := regexp.MustCompile(`(\d+):(\d+):(\d+\.\d+)`)
|
||||||
matches := re.FindStringSubmatch(string(splitTime[2]))
|
matches := re.FindStringSubmatch(splitTime[2])
|
||||||
if len(matches) != 4 {
|
if len(matches) != 4 {
|
||||||
return nil, 0, errors.New("formato de duração não encontrado")
|
return nil, 0, errors.New("formato de duração não encontrado")
|
||||||
}
|
}
|
||||||
@ -79,77 +107,57 @@ func convertAudioToOpusWithDuration(inputData []byte) ([]byte, int, error) {
|
|||||||
return convertedData, duration, nil
|
return convertedData, duration, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fetchAudioFromURL(url string) ([]byte, error) {
|
||||||
|
resp, err := httpClient.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
return io.ReadAll(resp.Body)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getInputData(c *gin.Context) ([]byte, error) {
|
||||||
|
if file, _, err := c.Request.FormFile("file"); err == nil {
|
||||||
|
return io.ReadAll(file)
|
||||||
|
}
|
||||||
|
|
||||||
|
if base64Data := c.PostForm("base64"); base64Data != "" {
|
||||||
|
return base64.StdEncoding.DecodeString(base64Data)
|
||||||
|
}
|
||||||
|
|
||||||
|
if url := c.PostForm("url"); url != "" {
|
||||||
|
return fetchAudioFromURL(url)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, errors.New("Nenhum arquivo, base64 ou URL fornecido")
|
||||||
|
}
|
||||||
|
|
||||||
func processAudio(c *gin.Context) {
|
func processAudio(c *gin.Context) {
|
||||||
if !validateAPIKey(c) {
|
if !validateAPIKey(c) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var inputData []byte
|
inputData, err := getInputData(c)
|
||||||
var err error
|
if err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||||
// Verifica se o arquivo foi enviado como form-data
|
return
|
||||||
file, _, err := c.Request.FormFile("file")
|
|
||||||
if err == nil {
|
|
||||||
inputData, err = ioutil.ReadAll(file)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Erro ao ler o arquivo"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Verifica se foi enviado um base64
|
|
||||||
base64Data := c.PostForm("base64")
|
|
||||||
if base64Data != "" {
|
|
||||||
inputData, err = base64.StdEncoding.DecodeString(base64Data)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Erro ao decodificar base64"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Verifica se foi enviada uma URL
|
|
||||||
url := c.PostForm("url")
|
|
||||||
if url != "" {
|
|
||||||
resp, err := http.Get(url)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Erro ao obter o arquivo da URL"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
inputData, err = io.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Erro ao ler o arquivo da URL"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Nenhum arquivo, base64 ou URL fornecido"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chama a função para converter o áudio e obter a duração
|
// Conversão e resposta
|
||||||
convertedData, duration, err := convertAudioToOpusWithDuration(inputData)
|
convertedData, duration, err := convertAudioToOpusWithDuration(inputData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Codifica o áudio convertido para base64
|
|
||||||
base64Audio := base64.StdEncoding.EncodeToString(convertedData)
|
|
||||||
|
|
||||||
// Retorna a resposta em JSON
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"duration": duration,
|
"duration": duration,
|
||||||
"audio": base64Audio,
|
"audio": base64.StdEncoding.EncodeToString(convertedData),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// Carrega o arquivo .env
|
|
||||||
err := godotenv.Load()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Erro ao carregar o arquivo .env")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtém a porta do arquivo .env ou usa a porta 8080 por padrão
|
// Obtém a porta do arquivo .env ou usa a porta 8080 por padrão
|
||||||
port := os.Getenv("PORT")
|
port := os.Getenv("PORT")
|
||||||
if port == "" {
|
if port == "" {
|
||||||
|
Loading…
Reference in New Issue
Block a user