package main
import (
"audio_to_text/store"
"bytes"
"fmt"
"io"
"log"
"log/slog"
"net/http"
"os"
"os/exec"
"strings"
"sync"
)
var (
xlog = slog.New(slog.NewTextHandler(os.Stdout, nil))
)
func main() {
input, err := store.Store.Get("INPUT")
if err != nil {
xlog.Error("failed to get input from kv store", "error", err)
return
}
source := input["source_url"].(string)
if strings.EqualFold(source, "") {
xlog.Error("not found 'source_url'", source)
}
model := input["model"].(string)
if strings.EqualFold(source, "") {
xlog.Error("not found 'source_url'", source)
}
transcription(source, model)
}
func Test() {
url := "https://raw.githubusercontent.com/donjuanMime/audio_to_text/main/video.mp4"
model := "tiny"
transcription(url, model)
}
func transcription(sourceUrl, model string) {
downloadFile(sourceUrl)
filename := "video.mp4"
command := fmt.Sprintf(`whisper-ctranslate2 %s --batched true --batch_size 4 --max_words_per_line 8 --word_timestamps true --vad_filter true --model %s`, filename, model)
runCmdWithProgress(command)
}
func runCmdWithProgress(command string) bool {
cmd := exec.Command("bash", "-c", command)
var stdoutBuf, stderrBuf bytes.Buffer
stdoutIn, _ := cmd.StdoutPipe()
stderrIn, _ := cmd.StderrPipe()
var errStdout, errStderr error
stdout := io.MultiWriter(os.Stdout, &stdoutBuf)
stderr := io.MultiWriter(os.Stderr, &stderrBuf)
if err := cmd.Start(); err != nil {
xlog.Error("cmd.Start() failed with ", err)
return false
}
var wg sync.WaitGroup
wg.Add(1)
go func() {
_, errStdout = io.Copy(stdout, stdoutIn)
log.Println(stdoutIn)
wg.Done()
}()
_, errStderr = io.Copy(stderr, stderrIn)
wg.Wait()
if err := cmd.Wait(); err != nil {
xlog.Error("cmd.Run() failed with ", err)
}
if errStdout != nil || errStderr != nil {
xlog.Error("failed to capture stdout or stderr", errStderr, errStdout)
return false
}
sendResult()
return true
}
func sendResult() {
if err := store.Dataset.Put(map[string]interface{}{
"json": string(mustReadFile("video.json")),
"srt": string(mustReadFile("video.srt")),
"tsv": string(mustReadFile("video.tsv")),
"txt": string(mustReadFile("video.txt")),
"vtt": string(mustReadFile("video.vtt")),
}); err != nil {
log.Fatal(err)
}
}
func mustReadFile(filename string) []byte {
file, err := os.ReadFile(filename)
if err != nil {
return nil
}
return file
}
func downloadFile(fileURL string) {
outputPath := "video.mp4"
// Create the file
out, err := os.Create(outputPath)
if err != nil {
log.Fatalf("Failed to create file: %v", err)
}
defer out.Close()
// Get the data
resp, err := http.Get(fileURL)
if err != nil {
log.Fatalf("Failed to download file: %v", err)
}
defer resp.Body.Close()
// Check server response
if resp.StatusCode != http.StatusOK {
log.Fatalf("Bad status: %s", resp.Status)
}
// Write the body to file
_, err = io.Copy(out, resp.Body)
if err != nil {
log.Fatalf("Failed to save file: %v", err)
}
log.Println("File downloaded successfully:", outputPath)
}