本文介绍了一款根据ChatGPT的英语白话操练运用SpokenAi,包含PortAudio的装置流程和中心代码,以及语音组成TextToSpeech的实现。一起供给了装备文件和布置运转示例。 –由ChatGPT总结

一.前语

Hi,大家好,我是Baird。最近几个月大火大热的ChatGPT已经发布到ChatGPT4版别了,我也一直在关注ChatGPT的发展,一直在考虑能根据ChatGPT或着说openai的才能能做出点什么运用,处理一些问题。

在细心看过openai的API文档后,发现openai不止供给了Chat的才能,还供给了如语音转文字,图片生成等才能。尽管没有ChatGPT那么火,但经过一番试用后,发现和ChatGPT作用一样让人冷艳。干脆就直接来一个openai全家桶,经过openai的才能开发一款运用试试。

开发什么呢?

ChatGPT对英语的言语才能天然不用说,而咱们国人当下英语学习面临的一大问题便是哑巴英语,市面上的供给的英语对话机器人和ChatGPT比起来差得不是一星半点。只能请教师一对一真人教学? 托付,现在都2023年了,还需求花钱请白话教师么?

来造一款Ai白话操练运用处理这个问题

ChatGPT4是由OpenAI开发的天然言语处理模型,采用了大规模无监督学习的方法进行训练,可用于生成文本、答复问题和谈天等使命。OpenAI是人工智能范畴的一家公司,其API文档供给了多种功用,包含语音转文字、图片生成等。

二.需求清单

首选先列出咱们需求清单,这个是一个简略版别的英语白话操练功用,先不方案造一个大app,咱们只需求处理如下问题

  1. 读取语音输入
  2. 语音转文字
  3. 经过ChatGPT沟通交流
  4. 文字转音频
  5. 音频播映
  6. 持续进行上述1~5步骤

根据上述功用,第一期我方案先做一个终端版别的运用-SpokenAi,看看后续发展再考虑做一个Web或APP版别的程序 (实际上是缺人手缺时刻 )

三.体系架构

来,先规划一下咱们SpokenAi的体系架构

基于ChatGPT制作的一款英语口语练习应用SpokenAi

  • portaudio: PortAudio是一个跨渠道的音频I/O库,供给了简略的API,使得开发人员能够在不同的渠道上以相似的方法拜访音频硬件。它支撑Windows、Mac OS X、Linux和其他首要的操作体系。PortAudio支撑多种音频API,包含ASIO、Core Audio、DirectSound、MME / WDM、ALSA和OSS。PortAudio还包含一个流接口,允许开发人员以相同的方法运用不同的音频API和硬件。
  • openai-api: 供给了多种API服务,包含但不限于天然言语处理、语音转文字、文字转语音、图画生成等。在OpenAI的API文档中,用户能够申请API密钥,并运用API进行开发和测验。
  • tensorflowtts: TensorflowTTS 是一个根据 TensorFlow 的语音组成工具包,它包含了多种语音组成模型和前处理工具,而且支撑多种语音组成使命,例如有人声组成(Vocoder)、语音转换、语音增强等。它能够帮助开发者快速建立语音组成模型,定制自己的语音组成体系。
  • Docker: Docker是一种容器化技术,能够将运用程序及其依靠项打包在一个容器中,以便在任何地方运转。容器是一种轻量级的虚拟化技术,能够供给与传统虚拟机相似的阻隔性和安全性,但占用的资源更少。Docker还供给了一套工具和渠道,使得容器的构建、布置和管理变得愈加简略。
  • SpokenAi:整体运用层,其中有三个库分别是praudio、rocket、ttsclient,对应如下作用
    1. praudio: 封装portaudio,对外供给音频录制和音频播映等接口
    2. rocket: 封装openai-api, 对外供给Chat接口、音频转文字等接口
    3. ttsclient: 供给调用容器化运转的tensorflowtts的接口
  • Console: 终端交互层,用户按提示进行操作,输入信息和进行相关操作

Tips:tensorflowtts 依靠较多,为便利完好,这里采用Docker布置

四.流程规划

接下来,咱们规划一下交互流程

基于ChatGPT制作的一款英语口语练习应用SpokenAi

简略归纳整体流程有三个步骤,一是输入个人信息 二是录音转文字,三是发送音讯,进行对话交互

由于是经过终端拜访,首要监听键盘事件,进行不同操作

如 按W键会开端录音,录音过程中按Q中止录音,待录音翻译完结后,按Ctrl+shift+enter发送音讯

五.开发细节

编程言语: Go 1.6+

SpokenAi运用依靠于portaudio,需求提前装置好portaudio不然编译无法经过

PortAudio

一.PortAudio下载地址:

  1. Windows: www.portaudio.com/download.ht…
  2. MacOS: brew install portaudio
  3. Linux: apt-get install portaudio19-dev

Mac和Linux比较好装置,Windows只能源码编译装置,具体流程如下:

PortAudio Window 装置流程

  1. 下载PortAudio源码:www.portaudio.com/download.ht…
  2. 装置Visual Studio 2019和CMake
  3. 源代码解压缩到 C:\PortAudio 文件夹中
  4. 翻开 CMake,挑选 C:\PortAudio 作为源代码文件夹,挑选一个输出文件夹,点击 Configure 按钮
  5. 在生成选项中,挑选 Visual Studio 16 2019,点击 Finish 按钮
  6. 点击 Generate 按钮
  7. 翻开 Visual Studio,挑选 Open a project or solution,挑选 C:\PortAudio\build\portaudio.sln 文件,点击翻开
  8. 在 Visual Studio 中,右键点击 portaudio_static 项目,挑选 Build,等候编译完结
  9. 在 Visual Studio 中,右键点击 portaudio_static 项目,挑选 Install,等候装置完结
  10. 在环境变量中增加 PortAudio 的途径,例如 C:\Program Files (x86)\PortAudio\bin
  11. 完结装置

PortAudio Window DLLs 装置流程

除此之外,能够直接挑选网上编译好的库,能够从这里github.com/spatialaudi…

在后续编译链接过程中,仍是需求装置gcc, 推荐装置MinGW-w64。

装置完结MinGW后,将下载PortAudio库文件libportaudio-x86_64-w64-mingw32.static.dll 更名成portaudio.dll,放到MinGW ld能搜索到的库途径。

将PortAudio库文件libportaudio-x86_64-w64-mingw32.static.dll 放到Window System32目录下,在运转时程序需求找到该动态库

调用PortAudio的中心代码

  1. 录音程序
func RecordAndSaveWithContext(ctx context.Context, filename string) error {
	portaudio.Initialize()
	defer portaudio.Terminate()
	done := make(chan struct{})
	// 初始化音频录制
	recorder, err := NewAudioRecorder()
	if err != nil {
		return fmt.Errorf("failed to initialize audio recorder: %v", err)
	}
	defer recorder.Stop()
	// 初始化进度条
	progressBar := pb.Full.Start(maxRecordSize)
	progressBar.SetRefreshRate(time.Millisecond * 200) // 设置刷新率
	progressBar.Set(pb.Bytes, true)                    // 显现录制音频的数据量
	// 记录开端时刻
	startTime := time.Now()
	// 创建Context,用于取消录音
	ctxnew, cancel := context.WithCancel(ctx)
	// 敞开协程进行录音
	samples := make([]int32, 0)
	go func() {
		defer close(done)
		for {
			select {
			case <-ctxnew.Done():
				return
			case data := <-recorder.dataCh:
				// 将音频数据追加到samples
				samples = append(samples, data...)
				// 当到达最长录音时刻时,取消录音
				if time.Since(startTime) >= maxRecordDuration {
					cancel()
					break
				}
				// 更新录制音频的数据量
				dataSize := int64(len(samples)) * int64(reflect.TypeOf(samples).Elem().Size())
				progressBar.Add(int(dataSize)) // 更新进度条
				progressBar.SetCurrent(dataSize)
			}
		}
	}()
	// 等候录音完结或接收到中止信号
	<-done
	progressBar.Finish()
	// 保存音频数据到WAV文件
	if err := saveToWavFile(filename, int32SliceToIntSlice(samples)); err != nil {
		return fmt.Errorf("failed to save audio to file: %v", err)
	}
	return nil
}

首要实现功用有:

  • 支撑开端录音和中止录音
  • 最长录制60s的音频,届时取消

2.播映音频

// PlayWavFile 播映指定的WAV文件
func PlayWavFile(filename string) error {
	// 翻开WAV文件
	f, err := os.Open(filename)
	if err != nil {
		return fmt.Errorf("failed to open WAV file: %v", err)
	}
	defer f.Close()
	// 解码WAV文件
	s, format, err := wav.Decode(f)
	if err != nil {
		return fmt.Errorf("failed to decode WAV file: %v", err)
	}
	defer s.Close()
	// 初始化扬声器
	err = speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/10))
	if err != nil {
		return fmt.Errorf("failed to initialize speaker: %v", err)
	}
	// 播映音频
	done := make(chan struct{})
	speaker.Play(beep.Seq(s, beep.Callback(func() {
		close(done)
	})))
	// 等候音频播映完结
	<-done
	return nil
}

语音组成TextToSpeech

现在比较通用的TextToSpeech(TTS)方案有以下几种:

  • Google Cloud Text-to-Speech
  • Amazon Polly
  • Microsoft Azure Text-to-Speech
  • IBM Watson Text to Speech
  • Mozilla TTS
  • Tacotron 2
  • WaveNet
  • TensorFlowTTS

有简略调用云服务的,也有自己装置环境的。调用云服务需求注册账号,按量收费,比较费钱 。决议自己布置,采用TensorFlowTTS,经过构建Docker容器运转该服务。

Dockerfile如下,第一次构建速度会比较慢。

FROM tensorflow/tensorflow:2.6.0
# 装置必要的依靠
RUN apt-get update  &&\
    apt-get install -y libsndfile1
# 装置TensorFlowTTS
RUN pip install -i https://mirrors.aliyun.com/pypi/simple/ TensorFlowTTS flask
# 装置
RUN apt-get install -y git
RUN pip install git+https://github.com/repodiac/german_transliterate.git#egg=german_transliterate
RUN pip install --upgrade numpy numba
# 装置 
ADD tts-server-api.py /app/tts-server-api.py
# 运转REST API服务器
CMD python /app/tts-server-api.py --host 0.0.0.0 --port 5000

假如不想自己自定义,能够直接下载我构建好的服务

docker pull ptonlix/tensorflowtts:1.0.9
docker run -itd -p 5000:5000 --name spokenai-tts ptonlix/tensorflowtts:1.0.9

tts-server-api.py 是启动Flask的API服务的脚本,对外供给/api/tts 文字转语音接口

@app.route('/api/tts', methods=['POST'])
def tts():
    data = request.get_json()
    text = data['text']
    # fastspeech inference
    input_ids = processor.text_to_sequence(text)
    mel_before, mel_after, duration_outputs, _, _ = fastspeech2.inference(
        input_ids=tf.expand_dims(tf.convert_to_tensor(input_ids, dtype=tf.int32), 0),
        speaker_ids=tf.convert_to_tensor([0], dtype=tf.int32),
        speed_ratios=tf.convert_to_tensor([1.0], dtype=tf.float32),
        f0_ratios=tf.convert_to_tensor([1.0], dtype=tf.float32),
        energy_ratios=tf.convert_to_tensor([1.0], dtype=tf.float32),
    )
    # melgan inference
    audio_before = mb_melgan.inference(mel_before)[0, :, 0]
    audio_after = mb_melgan.inference(mel_after)[0, :, 0]
    # save to file
    # Convert audio data to byte stream
    buffer = io.BytesIO()
    sf.write(buffer, audio_after, 22050, format='WAV', subtype='PCM_16')
    audio_bytes = buffer.getvalue()
    # Return audio data as a response with MIME type audio/wav
    return Response(audio_bytes, mimetype='audio/wav')

处理完上述两个关键问题,剩余便是业务代码的编写

[openai]
  [openai.base]
    apikey = ""
    apihost = "https://api.openai.com/v1" 
  [openai.chat]
    chatmodel =  "gpt-3.5-turbo"
    chatmaxtoken = 2048
    chattemperature = 0.7
    chattopp = 1
  [openai.audio]
    audiomodel = "whisper-1"
[file]
  [file.history]
    path = "./data/history/"
  [file.audio]
    [file.audio.record]
      path = "./data/audio/record/"
    [file.audio.play]
      path = "./data/audio/play/"
      enable =  0
      ttshost = "http://127.0.0.1:5000"

用toml装备文件格局, 首要分为两部分

  1. openai装备,首要需求填写自己的apikey和假如走代理则修正apihost地址。其他都是模型装备按需修正即可
  2. file装备,由于是终端版别,采用文件存储的方式较为便利
    • history为谈天上下文存储
    • audio为音频存储
      • record为录音文件存储目录
      • play为言语组成文件存储目录
      • enable 能够选为是否敞开语音组成,默许不敞开,敞开需求运转tensorflowtts。
      • ttshost 为tts api服务地址

六.布置运转

项目地址:github.com/ptonlix/spo…

欢迎Star 、PR 、 Issue 、交流

编译运转

装置portaudio, 参考上节PortAudio流程

# 下载源码
git clone https://github.com/ptonlix/spokenai.git
cd spokenai
# 修正装备文件
edit fat_config.toml
# 编译
go build
# 检查指令
./spokenai -h
# 运转
./spokenai

运转示例

启动:

基于ChatGPT制作的一款英语口语练习应用SpokenAi

基于ChatGPT制作的一款英语口语练习应用SpokenAi

开端对话:

基于ChatGPT制作的一款英语口语练习应用SpokenAi

基于ChatGPT制作的一款英语口语练习应用SpokenAi

后续方案

  • 寻觅志同道合的小伙伴,有意向一起制造一款Ai运用的请联络我!!!
  • 修复Bug,现在发现mac上语音播映一定概率播映失败
  • 编码后端服务和客户端程序