go - 如何在 Go 中从麦克风获取 WAV 音频

标签 go wav microphone audio-capture vosk

我的程序使用 Vosk 语音识别库的 Go 绑定(bind),它将音频作为 WAV 单声道音频的字节 slice 进行接收。我的程序当前使用外部命令 arecord 从麦克风获取 WAV 音频,但我更喜欢在 Go 中正确执行此操作,并且最好没有任何共享库依赖项。

我尝试使用 malgo包,但卡在如何将麦克风的原始音频转换为 WAV 上。我发现 WAV 编码包只能写入文件 (io.WriteSeeker),但我需要转换来自麦克风的连续流以进行实时语音识别。

至少是Linux

最佳答案

我最终也使用了 malgo,以及 malgo.FormatS16

在此回调中生成字节:

    // https://github.com/gen2brain/malgo/blob/master/_examples/capture/capture.go
    onRecvFrames := func(pSample2, pSample []byte, framecount uint32) {
        // Empirically, len(pSample) is 480, so for sample rate 44100 it's triggered about every 10ms.
        // sampleCount := framecount * deviceConfig.Capture.Channels * sizeInBytes
        pSampleData = append(pSampleData, pSample...)
    }

我可以将其转换为 int (为此使用 GPT-4):

func twoByteDataToIntSlice(audioData []byte) []int {
    intData := make([]int, len(audioData)/2)
    for i := 0; i < len(audioData); i += 2 {
        // Convert the pCapturedSamples byte slice to int16 slice for FormatS16 as we go
        value := int(binary.LittleEndian.Uint16(audioData[i : i+2]))
        intData[i/2] = value
    }
    return intData
}

然后使用“github.com/go-audio/wav”来生成内存中的wav字节(GPT-4再次创建了内存中文件系统黑客来克服 io.WriteSeeker 要求)

// Create an in-memory file to support io.WriteSeeker needed for NewEncoder which is needed for finalizing headers.
    inMemoryFilename := "in-memory-output.wav"
    inMemoryFile, err := fs.Create(inMemoryFilename)
    dbg(err)
    // We will call Close ourselves.

    // Convert audio data to IntBuffer
    inputBuffer := &audio.IntBuffer{Data: intData, Format: &audio.Format{SampleRate: iSampleRate, NumChannels: iNumChannels}}

    // Create a new WAV wavEncoder
    bitDepth := 16
    audioFormat := 1
    wavEncoder := wav.NewEncoder(inMemoryFile, iSampleRate, bitDepth, iNumChannels, audioFormat)

我在尝试将您想要的东西组合在一起时开发了这些片段 - 流式语音助手 [WIP] https://github.com/Petrzlen/vocode-golang

关于go - 如何在 Go 中从麦克风获取 WAV 音频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76096551/

相关文章:

iphone - 使用 SCListener 监听 iPhone 麦克风并同时播放音乐 : how?

audio - .WAV 格式(秒)的音频文件长度与文件大小有关吗?

ios - Swift:ViewDidLoad 在接受通知权限请求后不会继续

python - 用python通过麦克风播放mp3文件

go - 如果更改仅是一种参数类型,则避免代码重复

audio - 为什么在 WAV header 中同时使用小端和大端

python - 使用 pyDub 分割长音频文件

go - 为什么 goroutine 执行命令在运行之间是相同的

go - 退出后保持外部进程运行

random - 在最小值、最大值之间生成加密随机整数