ling-baseling-base

ASR 语音识别

14 个 vendor,Factory + Engine 与 WebSocket Recognizer 双模式

在线 Playground

在浏览器中直接体验本页相关 API,无需本地安装 Go 环境。

ASR 语音识别

voice/recognizer 提供语音识别(ASR)抽象,支持 14 个云厂商/本地引擎。每个 vendor 在独立子 module 中实现 Engine 接口;部分厂商(如火山引擎 LLM ASR)内部复用高层 Recognizer WebSocket 客户端。

架构

voice/recognizer/
├── types.go        # Engine 接口、Result、回调类型
├── factory.go      # Factory 注册表、Create(config)
├── config.go       # WebSocket Recognizer 配置
├── recognizer.go   # 高层 Recognizer(缓冲 + 回调)
├── client.go       # 底层 WebSocket 二进制协议客户端
├── qcloud/         # 腾讯云流式 ASR
├── aliyun/         # 阿里云
├── volcengine/     # 火山引擎
├── whisper/        # Whisper API
├── deepgram/       # Deepgram
├── local/          # 本地命令行 ASR(whisper.cpp、vosk 等)
└── ...             # google, aws, baidu, gladia, funasr, xfyun_mul, voiceapi

安装

go get github.com/LingByte/ling-base/voice/recognizer
go get github.com/LingByte/ling-base/voice/recognizer/qcloud
go get github.com/LingByte/ling-base/voice/recognizer/volcengine

Engine 接口(推荐)

所有 vendor 实现同一套流式 ASR 生命周期:

type Engine interface {
    Init(resultCallback ResultFunc, errorCallback ErrorFunc)
    Vendor() string
    ConnAndReceive(dialogID string) error
    Activity() bool
    RestartClient()
    SendAudioBytes(data []byte) error
    SendEnd() error
    StopConn() error
}

// 结果回调:text 文本,isLast 是否为本轮最终句,duration 耗时,dialogID 会话 ID
type ResultFunc func(text string, isLast bool, duration time.Duration, dialogID string)
type ErrorFunc func(err error, isFatal bool)

腾讯云流式 ASR 完整示例

package main

import (
    "fmt"
    "os"
    "time"

    "github.com/LingByte/ling-base/voice/recognizer/qcloud"
    gonanoid "github.com/matoous/go-nanoid"
)

func main() {
    opt := qcloud.NewQcloudASROption(
        os.Getenv("QCLOUD_APP_ID"),
        os.Getenv("QCLOUD_SECRET_ID"),
        os.Getenv("QCLOUD_SECRET_KEY"),
    )
    opt.ModelType = "16k_zh"
    opt.VadSilenceTime = 300 // 静音 300ms 判定一句话结束

    engine := qcloud.NewQcloudASR(opt)

    engine.Init(
        func(text string, isLast bool, duration time.Duration, dialogID string) {
            fmt.Printf("[%s] isLast=%v text=%q\n", dialogID, isLast, text)
        },
        func(err error, isFatal bool) {
            fmt.Printf("error (fatal=%v): %v\n", isFatal, err)
        },
    )

    dialogID, _ := gonanoid.Nanoid()
    if err := engine.ConnAndReceive(dialogID); err != nil {
        panic(err)
    }
    defer engine.StopConn()

    pcm, _ := os.ReadFile("sample.pcm") // PCM 16kHz 16-bit mono
    chunkSize := 3200 // 100ms @ 16kHz mono 16-bit
    for i := 0; i < len(pcm); i += chunkSize {
        end := i + chunkSize
        if end > len(pcm) {
            end = len(pcm)
        }
        _ = engine.SendAudioBytes(pcm[i:end])
        time.Sleep(100 * time.Millisecond)
    }
    _ = engine.SendEnd()

    time.Sleep(2 * time.Second) // 等待最终结果
}

Factory 模式(多 vendor 切换)

import (
    "github.com/LingByte/ling-base/voice/recognizer"
    "github.com/LingByte/ling-base/voice/recognizer/qcloud"
    "github.com/LingByte/ling-base/voice/recognizer/deepgram"
)

f := recognizer.NewFactory()
f.RegisterCreator(recognizer.VendorQCloud, func(cfg recognizer.TranscriberConfig) (recognizer.Engine, error) {
    opt, ok := cfg.(qcloud.QCloudASROption)
    if !ok {
        return nil, fmt.Errorf("expected QCloudASROption")
    }
    return qcloud.NewQcloudASR(opt), nil
})
f.RegisterCreator(recognizer.VendorDeepgram, func(cfg recognizer.TranscriberConfig) (recognizer.Engine, error) {
    opt := cfg.(deepgram.DeepgramASROption)
    return deepgram.NewDeepgramASR(opt), nil
})

opt := qcloud.NewQcloudASROption(appID, secretID, secretKey)
engine, err := f.CreateTranscriber(opt)

也可用全局工厂:recognizer.Create(config) / recognizer.MustCreate(config)(需各 vendor 已 RegisterCreator)。

支持的 Vendor

Vendor 常量字符串说明
VendorQCloudqcloud腾讯云流式 ASR
VendorAliyunaliyun阿里云
VendorVolcenginevolcengine火山引擎
VendorVolcengineLLMvolcllmasr火山 LLM ASR(内部用 Recognizer)
VendorGooglegoogleGoogle Cloud Speech
VendorAWSawsAWS Transcribe
VendorBaidubaidu百度
VendorDeepgramdeepgramDeepgram
VendorGladiagladiaGladia
VendorWhisperwhisperWhisper HTTP API
VendorFunASRfunasrFunASR
VendorFunASRRealtimefunasr_realtimeFunASR 实时
VendorXfyunMulxfyun_mul讯飞多语种
VendorVoiceAPIvoiceapi通用 Voice API
VendorLocallocal本地 CLI 工具
for _, v := range recognizer.AllVendors() {
    fmt.Println(recognizer.VendorString(v))
}

高层 Recognizer(WebSocket 协议)

部分场景使用 Recognizer 包装底层 Client,自动做音频分片缓冲与 Result 回调:

cfg := recognizer.DefaultConfig().
    WithURL("wss://your-asr-endpoint").
    WithAuth(recognizer.AuthConfig{
        AccessKey: "your-key",
        AppKey:    "your-app",
    }).
    WithAudio(recognizer.AudioConfig{
        Rate: 16000, Bits: 16, Channel: 1, Format: "pcm",
    })

rec := recognizer.NewRecognizer(cfg)

rec.OnResult(func(r *recognizer.Result) {
    fmt.Printf("final=%v text=%q\n", r.IsFinal, r.Text)
})
rec.OnError(func(err error) {
    log.Println(err)
})

rec.Start()
defer rec.Stop()

// 发送音频帧(自动缓冲到 segment 大小)
_ = rec.SendAudioFrame(&recognizer.AudioFrame{Data: pcmChunk})
// 结束并 flush
_ = rec.SendAudioFrame(&recognizer.AudioFrame{IsEnd: true})

Config 字段

分组字段说明
AuthAccessKey, AppKey, ResourceId鉴权
AudioRate, Bits, Channel, Format默认 16kHz / 16-bit / mono / pcm
RequestModelName, EnableITN, EnablePUNC, EndWindowSize识别模型与标点
BufferSegmentDurationMs分片时长,默认 200ms

热词(腾讯云)

opt.HotWords = []recognizer.HotWord{
    {Word: "ling-base", Weight: 10},
    {Word: "语音识别", Weight: 5},
}

音频格式约定

绝大多数 vendor 要求 PCM 16-bit little-endian mono,采样率 16000 Hz。发送前请对照各 vendor 文档确认 Format / ModelType(如腾讯云 16k_zh)。

字节率计算:

bytesPerSecond := recognizer.ComputeSampleByteCount(16000, 16, 1) // 32000

错误处理

  • ErrClientClosed:客户端已关闭,停止发送
  • ErrorFuncisFatal=true 表示需重建连接(RestartClient 或重新 ConnAndReceive
  • 使用 context 控制上层超时;Engine 本身通过回调异步返回

与 synthesizer / realtime 的关系

职责
recognizer仅 ASR(语音 → 文本)
synthesizer仅 TTS(文本 → 语音)
realtimeASR + LLM + TTS 端到端实时对话

自定义流水线:recognizer + 自有 LLM + synthesizer;语音助手场景优先 realtime

On this page