mirror of
https://github.com/xzeldon/whisper-api-server.git
synced 2025-07-12 23:04:36 +03:00
Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
2d44f72466 | |||
8275ad584b | |||
1546e3f145 | |||
fc48cca110 | |||
c4daf3ec71 | |||
dde206facd | |||
2e92dd91cb | |||
dacad9a4f6
|
|||
7d6be4b7d3
|
|||
7b0797cca1
|
|||
482616fb4c
|
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@ -29,4 +29,4 @@ jobs:
|
|||||||
version: ${{ env.GITHUB_REF_NAME }}
|
version: ${{ env.GITHUB_REF_NAME }}
|
||||||
args: release --clean
|
args: release --clean
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.PUBLISHER_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,5 +1,6 @@
|
|||||||
Whisper.dll
|
Whisper.dll
|
||||||
ggml-medium.bin
|
ggml-*
|
||||||
|
*.exe
|
||||||
|
|
||||||
whisper-api-server.exe
|
whisper-api-server.exe
|
||||||
|
|
||||||
|
25
README.md
25
README.md
@ -11,6 +11,20 @@ This API server enables audio transcription using the OpenAI Whisper models.
|
|||||||
|
|
||||||
# Build from source
|
# Build from source
|
||||||
|
|
||||||
|
Before build make sure that **CGO_ENABLED** env is set to **1**
|
||||||
|
|
||||||
|
```
|
||||||
|
set CGO_ENABLED 1
|
||||||
|
```
|
||||||
|
|
||||||
|
or preferable set it parament. Then check it via
|
||||||
|
|
||||||
|
```
|
||||||
|
go env
|
||||||
|
```
|
||||||
|
|
||||||
|
Also you have to have installed gcc x64 i.e. by MYSYS
|
||||||
|
|
||||||
Download the sources and use `go build`.
|
Download the sources and use `go build`.
|
||||||
For example, you can build using the following command:
|
For example, you can build using the following command:
|
||||||
|
|
||||||
@ -23,7 +37,7 @@ go build -ldflags "-s -w" -o server.exe main.go
|
|||||||
Make a request to the server using the following command:
|
Make a request to the server using the following command:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
curl http://localhost:3000/v1/audio/transcriptions \
|
curl http://localhost:3031/v1/audio/transcriptions \
|
||||||
-H "Content-Type: multipart/form-data" \
|
-H "Content-Type: multipart/form-data" \
|
||||||
-F file="@/path/to/file/audio.mp3" \
|
-F file="@/path/to/file/audio.mp3" \
|
||||||
```
|
```
|
||||||
@ -38,12 +52,11 @@ Receive a response in JSON format:
|
|||||||
|
|
||||||
# Usage with [Obsidian](https://obsidian.md/)
|
# Usage with [Obsidian](https://obsidian.md/)
|
||||||
|
|
||||||
To integrate this with the [Obsidian voice recognotion plugin](https://github.com/nikdanilov/whisper-obsidian-plugin), follow these steps:
|
1. Install [Obsidian voice recognotion plugin](https://github.com/nikdanilov/whisper-obsidian-plugin)
|
||||||
|
2. Open the plugin's settings.
|
||||||
1. Open the plugin's settings.
|
3. Set the following values:
|
||||||
2. Set the following values:
|
|
||||||
- API KEY: `sk-1`
|
- API KEY: `sk-1`
|
||||||
- API URL: `http://localhost:3000/v1/audio/transcriptions`
|
- API URL: `http://localhost:3031/v1/audio/transcriptions`
|
||||||
- Model: `whisper-1`
|
- Model: `whisper-1`
|
||||||
|
|
||||||
# Roadmap
|
# Roadmap
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -11,7 +12,7 @@ type TranscribeResponse struct {
|
|||||||
Text string `json:"text"`
|
Text string `json:"text"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func Transcribe(c echo.Context, whisperState *WhisperState) error {
|
func TranscribeFromFile(c echo.Context, whisperState *WhisperState) error {
|
||||||
audioPath, err := saveFormFile("file", c)
|
audioPath, err := saveFormFile("file", c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Logger().Errorf("Error reading file: %s", err)
|
c.Logger().Errorf("Error reading file: %s", err)
|
||||||
@ -26,6 +27,11 @@ func Transcribe(c echo.Context, whisperState *WhisperState) error {
|
|||||||
|
|
||||||
err = whisperState.context.RunFull(whisperState.params, buffer)
|
err = whisperState.context.RunFull(whisperState.params, buffer)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
c.Logger().Errorf("Error processing audio: %s", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
result, err := getResult(whisperState.context)
|
result, err := getResult(whisperState.context)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Logger().Error(err)
|
c.Logger().Error(err)
|
||||||
@ -43,3 +49,59 @@ func Transcribe(c echo.Context, whisperState *WhisperState) error {
|
|||||||
|
|
||||||
return c.JSON(http.StatusOK, response)
|
return c.JSON(http.StatusOK, response)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Transcribe(c echo.Context, whisperState *WhisperState) error {
|
||||||
|
// Get the file header
|
||||||
|
fileHeader, err := c.FormFile("file")
|
||||||
|
if err != nil {
|
||||||
|
c.Logger().Errorf("Error retrieving the file: %s", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the file
|
||||||
|
file, err := fileHeader.Open()
|
||||||
|
if err != nil {
|
||||||
|
c.Logger().Errorf("Error opening the file: %s", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
// Read the file into a buffer
|
||||||
|
buffer, err := io.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
c.Logger().Errorf("Error reading the file into buffer: %s", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
whisperState.mutex.Lock()
|
||||||
|
defer whisperState.mutex.Unlock()
|
||||||
|
|
||||||
|
bufferSpecial, err := whisperState.media.LoadAudioFileData(&buffer, true)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
c.Logger().Errorf("Error loading audio file data: %s", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = whisperState.context.RunStreamed(whisperState.params, bufferSpecial)
|
||||||
|
if err != nil {
|
||||||
|
c.Logger().Errorf("Error processing audio: %s", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := getResult(whisperState.context)
|
||||||
|
if err != nil {
|
||||||
|
c.Logger().Error(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(result) == 0 {
|
||||||
|
return c.JSON(http.StatusInternalServerError, map[string]string{"error": "Internal server error"})
|
||||||
|
}
|
||||||
|
|
||||||
|
response := TranscribeResponse{
|
||||||
|
Text: strings.TrimLeft(result, " "),
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.JSON(http.StatusOK, response)
|
||||||
|
}
|
||||||
|
@ -15,7 +15,7 @@ type WhisperState struct {
|
|||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitializeWhisperState(modelPath string) (*WhisperState, error) {
|
func InitializeWhisperState(modelPath string, lang int32) (*WhisperState, error) {
|
||||||
lib, err := whisper.New(whisper.LlDebug, whisper.LfUseStandardError, nil)
|
lib, err := whisper.New(whisper.LlDebug, whisper.LfUseStandardError, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -41,8 +41,7 @@ func InitializeWhisperState(modelPath string) (*WhisperState, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
params.AddFlags(whisper.FlagNoContext)
|
params.SetLanguage(lang)
|
||||||
params.AddFlags(whisper.FlagTokenTimestamps)
|
|
||||||
|
|
||||||
fmt.Printf("Params CPU Threads : %d\n", params.CpuThreads())
|
fmt.Printf("Params CPU Threads : %d\n", params.CpuThreads())
|
||||||
|
|
||||||
|
@ -22,9 +22,14 @@ func saveFormFile(name string, c echo.Context) (string, error) {
|
|||||||
}
|
}
|
||||||
defer src.Close()
|
defer src.Close()
|
||||||
|
|
||||||
|
tmpDir, err := ensureDir("tmp")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
ext := filepath.Ext(file.Filename)
|
ext := filepath.Ext(file.Filename)
|
||||||
filename := time.Now().Format(time.RFC3339)
|
filename := time.Now().Format(time.RFC3339)
|
||||||
filename = "./tmp/" + sanitizeFilename(filename) + ext
|
filename = tmpDir + "/" + sanitizeFilename(filename) + ext
|
||||||
|
|
||||||
dst, err := os.Create(filename)
|
dst, err := os.Create(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -46,3 +51,14 @@ func sanitizeFilename(filename string) string {
|
|||||||
}
|
}
|
||||||
return filename
|
return filename
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ensureDir(dirPath string) (string, error) {
|
||||||
|
if _, err := os.Stat(dirPath); os.IsNotExist(err) {
|
||||||
|
err := os.MkdirAll(dirPath, 0700)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dirPath, nil
|
||||||
|
}
|
||||||
|
96
internal/resources/cli_arguments.go
Normal file
96
internal/resources/cli_arguments.go
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
package resources
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Arguments defines the structure to hold parsed arguments
|
||||||
|
type Arguments struct {
|
||||||
|
Language string
|
||||||
|
ModelPath string
|
||||||
|
Port int
|
||||||
|
}
|
||||||
|
type ParsedArguments struct {
|
||||||
|
Language int32
|
||||||
|
ModelPath string
|
||||||
|
Port int
|
||||||
|
}
|
||||||
|
|
||||||
|
type LanguageMap map[string]string
|
||||||
|
|
||||||
|
func processLanguageAndCode(args *Arguments) (int32, error) {
|
||||||
|
// Read the language map from JSON file
|
||||||
|
jsonFile, err := os.Open("languageMap.json")
|
||||||
|
if err != nil {
|
||||||
|
return 0x6E65, fmt.Errorf("error opening language map: %w", err) // Wrap error for context
|
||||||
|
}
|
||||||
|
defer jsonFile.Close()
|
||||||
|
|
||||||
|
byteData, err := io.ReadAll(jsonFile)
|
||||||
|
if err != nil {
|
||||||
|
return 0x6E65, fmt.Errorf("error reading language map: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var languageMap LanguageMap
|
||||||
|
err = json.Unmarshal(byteData, &languageMap)
|
||||||
|
if err != nil {
|
||||||
|
return 0x6E65, fmt.Errorf("error parsing language map: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
hexCode, ok := languageMap[strings.ToLower(args.Language)]
|
||||||
|
if !ok {
|
||||||
|
return 0x6E65, fmt.Errorf("unsupported language: %s", args.Language)
|
||||||
|
}
|
||||||
|
|
||||||
|
languageCode, err := strconv.ParseInt(hexCode, 0, 32)
|
||||||
|
if err != nil {
|
||||||
|
return 0x6E65, fmt.Errorf("error converting hex code: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return int32(languageCode), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseFlags parses command line arguments and returns an Arguments struct
|
||||||
|
func ParseFlags() (*ParsedArguments, error) {
|
||||||
|
args := &Arguments{}
|
||||||
|
|
||||||
|
flag.StringVar(&args.Language, "l", "", "Language to be processed")
|
||||||
|
flag.StringVar(&args.Language, "language", "", "Language to be processed") // Optional: Redundant to demonstrate
|
||||||
|
flag.StringVar(&args.ModelPath, "m", "", "Path to the model file (required)")
|
||||||
|
flag.StringVar(&args.ModelPath, "modelPath", "", "Path to the model file (required)") // Optional: Redundant
|
||||||
|
flag.IntVar(&args.Port, "p", 3031, "Port to start the server on")
|
||||||
|
flag.IntVar(&args.Port, "port", 3031, "Port to start the server on") // Optional: Redundant
|
||||||
|
|
||||||
|
flag.Usage = func() {
|
||||||
|
fmt.Println("Usage: your_program [OPTIONS]")
|
||||||
|
fmt.Println("Options:")
|
||||||
|
flag.PrintDefaults() // Print default values for all flags
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parsing flags
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
args.Language = strings.ToLower(args.Language)
|
||||||
|
|
||||||
|
if args.ModelPath == "" {
|
||||||
|
return nil, fmt.Errorf("modelPath argument is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
languageCode, err := processLanguageAndCode(args)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error setting language, defaulting to English:", err)
|
||||||
|
// Use default language code directly as the result here
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ParsedArguments{
|
||||||
|
Language: languageCode,
|
||||||
|
ModelPath: args.ModelPath,
|
||||||
|
Port: args.Port,
|
||||||
|
}, nil
|
||||||
|
}
|
@ -1,38 +0,0 @@
|
|||||||
package resources
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/schollz/progressbar/v3"
|
|
||||||
)
|
|
||||||
|
|
||||||
func DownloadFile(url string, filepath string) error {
|
|
||||||
out, err := os.Create(filepath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer out.Close()
|
|
||||||
|
|
||||||
resp, err := http.Get(url)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
fileSize := resp.ContentLength
|
|
||||||
bar := progressbar.DefaultBytes(
|
|
||||||
fileSize,
|
|
||||||
"Downloading",
|
|
||||||
)
|
|
||||||
|
|
||||||
writer := io.MultiWriter(out, bar)
|
|
||||||
|
|
||||||
_, err = io.Copy(writer, resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
package resources
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"path/filepath"
|
|
||||||
)
|
|
||||||
|
|
||||||
func GetModel(modelType string) (string, error) {
|
|
||||||
fileURL := fmt.Sprintf("https://huggingface.co/ggerganov/whisper.cpp/resolve/main/%s", modelType)
|
|
||||||
filePath := modelType
|
|
||||||
|
|
||||||
isModelFileExists := IsFileExists(filePath)
|
|
||||||
|
|
||||||
if !isModelFileExists {
|
|
||||||
fmt.Println("Model not found.")
|
|
||||||
err := DownloadFile(fileURL, filePath)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
absPath, err := filepath.Abs(filePath)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Model found: %s\n", absPath)
|
|
||||||
return filePath, nil
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
package resources
|
|
||||||
|
|
||||||
import "os"
|
|
||||||
|
|
||||||
func IsFileExists(filename string) bool {
|
|
||||||
_, err := os.Stat(filename)
|
|
||||||
if err != nil {
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
@ -1,78 +0,0 @@
|
|||||||
package resources
|
|
||||||
|
|
||||||
import (
|
|
||||||
"archive/zip"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
)
|
|
||||||
|
|
||||||
func GetWhisperDll(version string) (string, error) {
|
|
||||||
fileUrl := fmt.Sprintf("https://github.com/Const-me/Whisper/releases/download/%s/Library.zip", version)
|
|
||||||
fileToExtract := "Binary/Whisper.dll"
|
|
||||||
|
|
||||||
isWhisperDllExists := IsFileExists("Whisper.dll")
|
|
||||||
|
|
||||||
if !isWhisperDllExists {
|
|
||||||
fmt.Println("Whisper DLL not found.")
|
|
||||||
archivePath, err := os.CreateTemp("", "WhisperLibrary-*.zip")
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
defer archivePath.Close()
|
|
||||||
|
|
||||||
err = DownloadFile(fileUrl, archivePath.Name())
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = extractFile(archivePath.Name(), fileToExtract)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
absPath, err := filepath.Abs("Whisper.dll")
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Library found: %s\n", absPath)
|
|
||||||
return "Whisper.dll", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func extractFile(archivePath string, fileToExtract string) error {
|
|
||||||
reader, err := zip.OpenReader(archivePath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer reader.Close()
|
|
||||||
|
|
||||||
for _, file := range reader.File {
|
|
||||||
if file.Name == fileToExtract {
|
|
||||||
targetPath := filepath.Base(fileToExtract)
|
|
||||||
|
|
||||||
writer, err := os.Create(targetPath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer writer.Close()
|
|
||||||
|
|
||||||
src, err := file.Open()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer src.Close()
|
|
||||||
|
|
||||||
_, err = io.Copy(writer, src)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Errorf("File not found in the archive")
|
|
||||||
}
|
|
84
languageMap.json
Normal file
84
languageMap.json
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
{
|
||||||
|
"af": "0x6661",
|
||||||
|
"sq": "0x7173",
|
||||||
|
"am": "0x6D61",
|
||||||
|
"ar": "0x7261",
|
||||||
|
"hy": "0x7968",
|
||||||
|
"as": "0x7361",
|
||||||
|
"az": "0x7A61",
|
||||||
|
"ba": "0x6162",
|
||||||
|
"eu": "0x7565",
|
||||||
|
"be": "0x6562",
|
||||||
|
"bn": "0x6E62",
|
||||||
|
"bs": "0x7362",
|
||||||
|
"br": "0x7262",
|
||||||
|
"bg": "0x6762",
|
||||||
|
"ca": "0x6163",
|
||||||
|
"zh": "0x687A",
|
||||||
|
"hr": "0x7268",
|
||||||
|
"cs": "0x7363",
|
||||||
|
"da": "0x6164",
|
||||||
|
"nl": "0x6C6E",
|
||||||
|
"en": "0x6E65",
|
||||||
|
"et": "0x7465",
|
||||||
|
"fo": "0x6F66",
|
||||||
|
"fi": "0x6966",
|
||||||
|
"fr": "0x7266",
|
||||||
|
"gl": "0x6C67",
|
||||||
|
"ka": "0x616B",
|
||||||
|
"de": "0x7265",
|
||||||
|
"el": "0x6C61",
|
||||||
|
"gu": "0x7567",
|
||||||
|
"he": "0x6568",
|
||||||
|
"hi": "0x6968",
|
||||||
|
"hu": "0x7568",
|
||||||
|
"is": "0x7369",
|
||||||
|
"id": "0x6469",
|
||||||
|
"it": "0x7469",
|
||||||
|
"ja": "0x616A",
|
||||||
|
"kn": "0x6E6B",
|
||||||
|
"kk": "0x6B6B",
|
||||||
|
"km": "0x6D6B",
|
||||||
|
"ko": "0x6F6B",
|
||||||
|
"ky": "0x796B",
|
||||||
|
"lo": "0x6F6C",
|
||||||
|
"lv": "0x766C",
|
||||||
|
"lt": "0x746C",
|
||||||
|
"mk": "0x6B6D",
|
||||||
|
"ms": "0x736D",
|
||||||
|
"ml": "0x6C6D",
|
||||||
|
"mr": "0x726D",
|
||||||
|
"mn": "0x6E6D",
|
||||||
|
"ne": "0x6570",
|
||||||
|
"no": "0x6F6E",
|
||||||
|
"or": "0x726F",
|
||||||
|
"ps": "0x7368",
|
||||||
|
"fa": "0x6172",
|
||||||
|
"pl": "0x6C70",
|
||||||
|
"pt": "0x7470",
|
||||||
|
"pa": "0x6170",
|
||||||
|
"ro": "0x6F72",
|
||||||
|
"ru": "0x7572",
|
||||||
|
"sa": "0x6173",
|
||||||
|
"sr": "0x7273",
|
||||||
|
"sd": "0x6473",
|
||||||
|
"si": "0x6973",
|
||||||
|
"sk": "0x6B73",
|
||||||
|
"sl": "0x6C73",
|
||||||
|
"es": "0x6573",
|
||||||
|
"sw": "0x7773",
|
||||||
|
"sv": "0x6576",
|
||||||
|
"tg": "0x6769",
|
||||||
|
"ta": "0x6174",
|
||||||
|
"te": "0x6574",
|
||||||
|
"th": "0x6874",
|
||||||
|
"tr": "0x7274",
|
||||||
|
"uk": "0x6B75",
|
||||||
|
"ur": "0x7275",
|
||||||
|
"uz": "0x7A75",
|
||||||
|
"vi": "0x6976",
|
||||||
|
"cy": "0x7963",
|
||||||
|
"xh": "0x6877",
|
||||||
|
"yi": "0x6979",
|
||||||
|
"yo": "0x6F79"
|
||||||
|
}
|
46
main.go
46
main.go
@ -1,6 +1,10 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"github.com/labstack/echo/v4/middleware"
|
"github.com/labstack/echo/v4/middleware"
|
||||||
"github.com/labstack/gommon/log"
|
"github.com/labstack/gommon/log"
|
||||||
@ -8,9 +12,37 @@ import (
|
|||||||
"github.com/xzeldon/whisper-api-server/internal/resources"
|
"github.com/xzeldon/whisper-api-server/internal/resources"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func change_working_directory(e *echo.Echo) {
|
||||||
|
exePath, errs := os.Executable()
|
||||||
|
if errs != nil {
|
||||||
|
e.Logger.Error(errs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
exeDir := filepath.Dir(exePath)
|
||||||
|
|
||||||
|
// Change the working directory to the executable directory
|
||||||
|
errs = os.Chdir(exeDir)
|
||||||
|
if errs != nil {
|
||||||
|
e.Logger.Error(errs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cwd, _ := os.Getwd()
|
||||||
|
fmt.Println("Current working directory:", cwd)
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
e := echo.New()
|
e := echo.New()
|
||||||
e.HideBanner = true
|
e.HideBanner = true
|
||||||
|
change_working_directory(e)
|
||||||
|
|
||||||
|
args, errParsing := resources.ParseFlags()
|
||||||
|
if errParsing != nil {
|
||||||
|
e.Logger.Error("Error parsing flags: ", errParsing)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
e.Use(middleware.CORS())
|
e.Use(middleware.CORS())
|
||||||
|
|
||||||
@ -18,24 +50,16 @@ func main() {
|
|||||||
l.SetHeader("${time_rfc3339} ${level}")
|
l.SetHeader("${time_rfc3339} ${level}")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := resources.GetWhisperDll("1.12.0")
|
whisperState, err := api.InitializeWhisperState(args.ModelPath, args.Language)
|
||||||
if err != nil {
|
|
||||||
e.Logger.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
model, err := resources.GetModel("ggml-medium.bin")
|
|
||||||
if err != nil {
|
|
||||||
e.Logger.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
whisperState, err := api.InitializeWhisperState(model)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e.Logger.Error(err)
|
e.Logger.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
e.POST("/v1/audio/transcriptions", func(c echo.Context) error {
|
e.POST("/v1/audio/transcriptions", func(c echo.Context) error {
|
||||||
|
|
||||||
return api.Transcribe(c, whisperState)
|
return api.Transcribe(c, whisperState)
|
||||||
})
|
})
|
||||||
|
|
||||||
e.Logger.Fatal(e.Start("127.0.0.1:3000"))
|
e.Logger.Fatal(e.Start(fmt.Sprintf("127.0.0.1:%d", args.Port)))
|
||||||
}
|
}
|
||||||
|
@ -86,6 +86,16 @@ func (this *FullParams) RemoveFlags(newflag eFullParamsFlags) {
|
|||||||
this.cStruct.Flags = this.cStruct.Flags ^ newflag
|
this.cStruct.Flags = this.cStruct.Flags ^ newflag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *FullParams) SetLanguage(language int32) {
|
||||||
|
if this == nil {
|
||||||
|
return
|
||||||
|
} else if this.cStruct == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.cStruct.Language = eLanguage(language)
|
||||||
|
}
|
||||||
|
|
||||||
/*using pfnNewSegment = HRESULT( __cdecl* )( iContext* ctx, uint32_t n_new, void* user_data ) noexcept;*/
|
/*using pfnNewSegment = HRESULT( __cdecl* )( iContext* ctx, uint32_t n_new, void* user_data ) noexcept;*/
|
||||||
type NewSegmentCallback_Type func(context *IContext, n_new uint32, user_data unsafe.Pointer) EWhisperHWND
|
type NewSegmentCallback_Type func(context *IContext, n_new uint32, user_data unsafe.Pointer) EWhisperHWND
|
||||||
|
|
||||||
@ -136,9 +146,9 @@ func (this *FullParams) TestDefaultsOK() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if this.cStruct.Language != English {
|
// if this.cStruct.Language != English {
|
||||||
return false
|
// return false
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Todo ... why do these not line up as expected.. is our struct out of alignment ?
|
// Todo ... why do these not line up as expected.. is our struct out of alignment ?
|
||||||
/*
|
/*
|
||||||
@ -204,6 +214,7 @@ func NewFullParams(cstruct *_FullParams) *FullParams {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func _newFullParams_cStruct() *_FullParams {
|
func _newFullParams_cStruct() *_FullParams {
|
||||||
|
|
||||||
return &_FullParams{
|
return &_FullParams{
|
||||||
|
|
||||||
strategy: 0,
|
strategy: 0,
|
||||||
|
@ -207,6 +207,7 @@ func (context *IContext) FullDefaultParams(strategy eSamplingStrategy) (*FullPar
|
|||||||
return nil, errors.New("FullDefaultParams did not return params")
|
return nil, errors.New("FullDefaultParams did not return params")
|
||||||
}
|
}
|
||||||
ParamObj := NewFullParams(params)
|
ParamObj := NewFullParams(params)
|
||||||
|
// ParamObj.SetLanguage(Polish)
|
||||||
|
|
||||||
if ParamObj.TestDefaultsOK() {
|
if ParamObj.TestDefaultsOK() {
|
||||||
return ParamObj, nil
|
return ParamObj, nil
|
||||||
|
Reference in New Issue
Block a user