Skip to main content

스트리밍 STT - WebSocket

본 문서는 스트리밍 STT 중에서 WebSocket로 구현하는 방식에 대한 가이드를 제공합니다.

연동예제

본 문서의 예제는 로컬 오디오 파일로부터 스트리밍 음성인식을 수행하는 방법을 설명해줍니다. 마이크와 같은 스트리밍 입력 장치로 API를 이용하고 싶은 경우, 파일로 읽어오는 코드 부분을 장치 인식을 수행하는 코드로 변경함으로써 사용하실 수 있습니다.

모든 스트리밍 요청에는 사용 한도가 있습니다. 한도를 초과하면 오류가 발생합니다.

인증 토큰 발급

스트리밍 STT API를 사용하기 위해서는 인증 토큰 발급 가이드를 통해 토큰을 발급받아야 합니다.

Parameter

NameTypeDescriptionRequired
sample_rateinteger범위: 8000 ~ 48000, 단위: HzO
encodingstring인코딩 타입 (참고. 지원 인코딩)O
use_itnboolean영어/숫자/단위 변환 사용 여부 (default: true, 참고: 영어/숫자/단위 변환)X
use_disfluency_filterboolean간투어 필터기능 사용 여부 (default: false, 참고: 간투어 필터)X
use_profanity_filterboolean비속어 필터기능 사용 여부 (default: false, 참고: 비속어 필터)X

Response

{
// 문장의 발화 id
seq: integer
// 스트리밍 시작 기준 문장의 발화 시점 (단위: msec)
start_at: integer
// final이 true 일 경우 문자의 발화 시간, final 이 false일 경우 0 (단위: msec)
duration: integer
// 문장의 종료 여부
final: boolean

// 대체 텍스트, 첫번째 값이 정확도가 가장 높은 결과
alternatives: [
{
// 문장의 텍스트
text: string
// 단어(토큰)의 정보, final 이 true 일 경우만 제공
words?: [
{
// 단어(토큰)의 텍스트, `|` 로 띄어쓰기 구분
text: string
// 문장의 시작 기준 단어(토큰)의 발화 시점 (단위: msec)
start_at: integer
// 단어(토큰)의 발화 시간 (단위: msec)
duration: integer
// 단어(토큰)의 정확도 (미지원)
confidence: float
}
]
}
]
}

샘플 코드

package main

import (
"encoding/json"
"flag"
"fmt"
"io"
"log"
"net/http"
"net/url"
"os"
"os/signal"
"time"

"github.com/gorilla/websocket"
)

const ServerHost = "openapi.vito.ai"
const ClientId = "{YOUR_CLIENT_ID}"
const ClientSecret = "{YOUR_CLIENT_SECRET}"

func main() {
flag.Parse()
log.SetFlags(0)

interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt)

u := url.URL{Scheme: "wss", Host: ServerHost, Path: "/v1/transcribe:streaming"}

query := u.Query()
query.Set("sample_rate", "8000")
query.Set("encoding", "LINEAR16")
query.Set("use_itn", "true")
query.Set("use_disfluency_filter", "true")
query.Set("use_profanity_filter", "false")
u.RawQuery = query.Encode()

log.Printf("connecting to %s", u.String())

audioFile := flag.Arg(0)
f, err := os.Open(audioFile)

data := map[string][]string{
"client_id": []string{ClientId},
"client_secret": []string{ClientSecret},
}
resp, _ := http.PostForm("https://openapi.vito.ai/v1/authenticate", data)
if resp.StatusCode != 200 {
panic("Failed to authenticate")
}

bytes, _ := io.ReadAll(resp.Body)
var result struct {
Token string `json:"access_token"`
}
json.Unmarshal(bytes, &result)
requestHeader := http.Header{
"Authorization": []string{fmt.Sprintf("Bearer %s", result.Token)},
}
c, res, err := websocket.DefaultDialer.Dial(u.String(), requestHeader)
if err != nil {
log.Printf("status: %s, body: %v", res.Status, res.Body)
log.Fatal("dial:", err)
}
defer c.Close()

start := time.Now()
go func() {
buf := make([]byte, 1024)
for {
n, err := f.Read(buf)
if err == io.EOF {
// Nothing else to pipe, close the stream.
log.Println("send EOS")
if err := c.WriteMessage(websocket.TextMessage, []byte("EOS")); err != nil {
log.Fatalf("Could not close stream: %v", err)
}
return
}
if err != nil {
log.Printf("Could not read from %s: %v", audioFile, err)
continue
}
err = c.WriteMessage(websocket.BinaryMessage, buf[:n])
if err != nil {
log.Println("write:", err)
}
//time.Sleep((time.Duration(n) * 1000 / 2 / 8000) * time.Millisecond)

select {
case <-interrupt:
log.Println("interrupt")
if err := c.WriteMessage(websocket.TextMessage, []byte("EOS")); err != nil {
log.Fatalf("Could not close: %v", err)
}
return
default:

}
}
}()

start2 := time.Now()
for {
_, message, err := c.ReadMessage()
if err != nil {
log.Printf("elapsed[%v]\n", time.Since(start))
log.Println("read:", err)
return
}
log.Printf("[%v]recv: %s", time.Since(start2), message)
start2 = time.Now()
}

}

오류 코드

스트리밍 STT - WebSocket 의 오류 처리는 Dial시 응답값의 StatusCode로 오류를 처리 합니다.

HttpStatusCodeNotes
400H0001잘못된 파라미터 요청
401H0002인증실패
429A0001사용량 초과
500E500서버 오류

참고사항

오디오 파일을 텍스트로 변환할 경우, 스트리밍 STT API를 이용하여 처리할 수도 있지만 일반 STT 가이드 문서에서 기술된 것처럼 일반 STT API로 변환 작업을 수행하는 것이 더 편리합니다.