audio_pipeline
This commit is contained in:
117
workers/transcribe/internal/nexara/nexara.go
Normal file
117
workers/transcribe/internal/nexara/nexara.go
Normal file
@@ -0,0 +1,117 @@
|
||||
package nexara
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/yourorg/transcribe/internal/models"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
apiURL string
|
||||
apiKey string
|
||||
model string
|
||||
httpClient *http.Client
|
||||
}
|
||||
|
||||
func New(baseURL, apiKey, model string, timeout time.Duration) *Client {
|
||||
baseURL = strings.TrimRight(baseURL, "/")
|
||||
return &Client{
|
||||
apiURL: baseURL + "/api/v1/audio/transcriptions",
|
||||
apiKey: apiKey,
|
||||
model: model,
|
||||
httpClient: &http.Client{
|
||||
Timeout: timeout,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) TranscribeFile(ctx context.Context, path string) (text, language string, segments []models.Segment, err error) {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return "", "", nil, fmt.Errorf("open file: %w", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
body := &bytes.Buffer{}
|
||||
writer := multipart.NewWriter(body)
|
||||
part, err := writer.CreateFormFile("file", filepath.Base(path))
|
||||
if err != nil {
|
||||
return "", "", nil, err
|
||||
}
|
||||
if _, err := io.Copy(part, f); err != nil {
|
||||
return "", "", nil, err
|
||||
}
|
||||
if c.model != "" {
|
||||
if err := writer.WriteField("model", c.model); err != nil {
|
||||
return "", "", nil, err
|
||||
}
|
||||
}
|
||||
if err := writer.WriteField("response_format", "json"); err != nil {
|
||||
return "", "", nil, err
|
||||
}
|
||||
if err := writer.Close(); err != nil {
|
||||
return "", "", nil, err
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.apiURL, body)
|
||||
if err != nil {
|
||||
return "", "", nil, err
|
||||
}
|
||||
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||||
req.Header.Set("Authorization", "Bearer "+c.apiKey)
|
||||
|
||||
resp, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return "", "", nil, fmt.Errorf("request: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
respBody, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", "", nil, err
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return "", "", nil, fmt.Errorf("status %d: %s", resp.StatusCode, string(respBody))
|
||||
}
|
||||
|
||||
var raw map[string]any
|
||||
if err := json.Unmarshal(respBody, &raw); err != nil {
|
||||
return "", "", nil, fmt.Errorf("parse: %w", err)
|
||||
}
|
||||
if t, ok := raw["text"].(string); ok {
|
||||
text = t
|
||||
}
|
||||
if lang, ok := raw["language"].(string); ok {
|
||||
language = lang
|
||||
}
|
||||
if segs, ok := raw["segments"].([]any); ok {
|
||||
for _, s := range segs {
|
||||
m, ok := s.(map[string]any)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
var seg models.Segment
|
||||
if v, ok := m["start"].(float64); ok {
|
||||
seg.Start = v
|
||||
}
|
||||
if v, ok := m["end"].(float64); ok {
|
||||
seg.End = v
|
||||
}
|
||||
if v, ok := m["text"].(string); ok {
|
||||
seg.Text = v
|
||||
}
|
||||
segments = append(segments, seg)
|
||||
}
|
||||
}
|
||||
return text, language, segments, nil
|
||||
}
|
||||
Reference in New Issue
Block a user