API Chuyển giọng nói thành văn bản [STT] của Google là một cách dễ dàng để tích hợp tính năng nhận dạng giọng nói vào ứng dụng của bạn. Ý tưởng của dịch vụ rất đơn giản, nó nhận luồng âm thanh và phản hồi bằng văn bản được nhận dạng. Tính đến thời điểm viết bài, 60 phút nhận dạng giọng nói đầu tiên mỗi tháng là miễn phí, vì vậy bạn có thể dùng thử mà không mất bất kỳ chi phí nào. Mỗi phút vượt quá giới hạn có giá khoảng $0. 006, thời gian được làm tròn đến 15 giây
điều kiện tiên quyết
Để làm theo hướng dẫn này, bạn phải bật Speech-to-Text
- Mở bảng điều khiển GCP https. // bảng điều khiển. đám mây. Google. com/
- Chọn hoặc tạo một dự án mới
- Tìm kiếm “Cloud Speech-to-Text API” và kích hoạt nó
- Tìm kiếm “Tài khoản dịch vụ” và tạo tài khoản dịch vụ mới
- Thêm khóa vào tài khoản dịch vụ, chọn định dạng JSON, tải xuống và lưu tệp khóa một cách an toàn
Có thể gửi luồng âm thanh trực tiếp từ trình duyệt, nhưng theo như tôi biết, không có cách nào để cho phép khách hàng [trình duyệt] sử dụng tài khoản của chúng tôi mà không để lộ thông tin đăng nhập dịch vụ. Do đó, chúng tôi sẽ gửi một luồng âm thanh từ trình duyệt qua ổ cắm web đến phần phụ trợ, sau đó chuyển hướng nó đến STT và gửi lại phản hồi
Ở phía máy khách, chúng tôi đang sử dụng Bản mô tả mà không có phụ thuộc bổ sung và ở phần phụ trợ, nó sẽ được định cấu hình http4 với heo vòi. Đối với các cuộc gọi STT, chúng tôi sẽ sử dụng thư viện do Google cung cấp
API chuyển giọng nói thành văn bảnAPI là điểm trung tâm trong giải pháp của chúng tôi, vì vậy, trước tiên chúng tôi phải hiểu cách chúng tôi có thể sử dụng dịch vụ và những yêu cầu hoặc hạn chế nào mà nó ngụ ý đối với phần còn lại của giải pháp
Tài liệu mô tả 3 kịch bản sử dụng điển hình. phiên âm tệp ngắn, phiên âm tệp dài và phiên âm đầu vào luồng âm thanh. Chúng tôi quan tâm đến kịch bản thứ 3 vì chúng tôi muốn nhận ra bài phát biểu của người dùng một cách nhanh chóng
Để đạt được kết quả nhận dạng giọng nói tốt nhất, tài liệu đề xuất các tính năng sau của luồng âm thanh
- lấy mẫu ở 16 kHz
- Định dạng mẫu có chữ ký 16-bit
- Nén không mất dữ liệu
- kênh đơn
- Độ dài 100 mili giây của đoạn âm thanh trong mỗi yêu cầu trong luồng
Ngoài ra, bất kỳ quá trình xử lý trước nào như kiểm soát khuếch đại, giảm nhiễu hoặc lấy mẫu lại đều không được khuyến khích
trình duyệt webLựa chọn phổ biến để ghi âm thanh [và video] trong trình duyệt là MediaStream Recording API. Thật không may, nó chỉ hỗ trợ các định dạng nén và tệ hơn, các định dạng được hỗ trợ phụ thuộc vào trình duyệt và nền tảng. Lựa chọn tốt hơn là Web Audio API, có thể được sử dụng để xử lý luồng âm thanh tùy chỉnh. Cả hai công nghệ đều được xây dựng trên Media Capture và Streams cung cấp quyền truy cập vào thiết bị âm thanh của khách hàng
Trước tiên, chúng tôi phải có được một tay cầm cho luồng âm thanh của micrô của người dùng bằng Media Capture và Streams API
const sampleRate = 16000const stream = navigator.mediaDevices.getUserMedia[{
audio: {
deviceId: "default",
sampleRate: sampleRate,
sampleSize: 16,
channelCount: 1
},
video: false
}]
Ở đây, chúng tôi sử dụng thiết bị “mặc định”, mặc dù có thể liệt kê các thiết bị khả dụng và chọn thiết bị cụ thể. Chúng tôi cũng đặt các tham số cần thiết của luồng
Tiếp theo, chúng tôi sẽ xử lý luồng bằng API âm thanh trên web. API này cho phép chúng tôi xây dựng một mạng lưới các nút xử lý âm thanh. API cung cấp một tập hợp các nút cho các tác vụ xử lý chung. Chúng tôi quan tâm đến hai trong số họ
- MediaStreamAudioSourceNode — kết nối luồng phương tiện với mạng
- AudioWorkletNode — cho phép xử lý tùy chỉnh luồng âm thanh
Tất cả các nút tồn tại trong AudioContext mà chúng ta phải tạo trước
const audioContext = new window.AudioContext[{sampleRate: sampleRate}]
Sau đó, chúng ta có thể tạo MediaStreamAudioSourceNode từ luồng thu được trước đó
const source: MediaStreamAudioSourceNode = audioContext.createMediaStreamSource[stream]
Việc tạo nút worklet phức tạp hơn một chút. Nút worklet phải thực hiện công việc của nó trong một luồng riêng biệt. Để đạt được điều đó, Web Audio API sử dụng Worker API. May mắn thay, API xử lý hầu hết quy trình. Chúng ta phải làm 2 việc
- tạo tập lệnh xử lý và đăng ký nó dưới một tên
- tạo nút worklet trong ngữ cảnh chính bằng tên đã đăng ký
Nút xử lý của chúng tôi chịu trách nhiệm cho 2 nhiệm vụ
- chuyển mã luồng
- kết hợp các khung thành các đoạn âm thanh 100 ms
Các nút của Web Audio API xử lý luồng âm thanh trong các khung có độ dài 128 mẫu. Một khung hình như vậy được đặc tả gọi là lượng tử kết xuất. Mỗi mẫu được biểu thị bằng một số thực 32 bit, vì vậy việc chuyển mã chỉ đơn giản là ánh xạ lại một mẫu thực 32 bit thành một mẫu đã ký 16 bit
Nguồn đầy đủ của tập lệnh xử lý
const quantumSize = 128
class TestProcessor extends AudioWorkletProcessor {
constructor[options] {
super[]
this.quantaPerFrame = 12
this.quantaCount = 0
this.frame = new Int16Array[quantumSize * this.quantaPerFrame]
}
process[inputs, outputs, parameters] {
const offset = quantumSize * this.quantaCount
inputs[0][0].forEach[[sample, idx] => this.frame[offset + idx] = Math.floor[sample * 0x7fff]]
this.quantaCount = this.quantaCount + 1
if [this.quantaCount === this.quantaPerFrame] {
this.port.postMessage[this.frame]
this.quantaCount = 0
}
return true
}
}
registerProcessor['pcm-worker', TestProcessor]
Số lượng tử kết xuất trong mỗi đoạn luồng là 12, vì vậy độ dài của đoạn sẽ là. [1/16 kHz]*128*12 = 96 mili giây
Mẫu số float 32 bit nằm trong phạm vi [-1;1]. Chúng tôi cần một số trong phạm vi [-32,768;32,767]. Để chuyển mã chúng ta cần nhân mẫu đầu vào với 32,768 và làm tròn kết quả. môn Toán. tầng [mẫu * 0x7fff]
Sau khi toàn bộ đoạn được hoàn thành, nó sẽ được gửi đến ngữ cảnh chính bởi cổng của worker. đây. Hải cảng. postMessage[cái này. khung]. Chúng tôi sẽ sớm xem nó được nhận ở đầu bên kia như thế nào
Trước khi tạo nút worklet, chúng ta phải đăng ký tập lệnh worklet vào ngữ cảnh âm thanh của mình
audioContext.audioWorklet.addModule['/pcmWorker.js']
Bây giờ chúng ta có thể tạo nút worklet trong luồng chính và kết nối nó với nút nguồn âm thanh của luồng
const pcmWorker = new AudioWorkletNode[audioContext, 'pcm-worker', {
outputChannelCount: [1]
}]
source.connect[pcmWorker]
WebSocketĐể định tuyến luồng âm thanh từ nút worklet đến phần phụ trợ, chúng ta phải tạo kết nối WebSocket
const conn = new WebSocket["ws://localhost:8080/ws/stt"]
và sau đó chúng tôi có thể chuyển hướng luồng âm thanh từ nhân viên PCM sang kết nối [chúng tôi sử dụng cổng của AudioWorkletNode để nhận dữ liệu từ tập lệnh xử lý]
pcmWorker.port.onmessage = event => conn.send[event.data]
pcmWorker.port.start[]
Phụ trợChúng tôi sẽ bắt đầu triển khai phụ trợ với điểm cuối WebSocket. Định nghĩa điểm cuối trong heo vòi
________số 8để tạo tuyến http4s, chúng tôi phải cung cấp handleWebSocket fs2 Ống chuyển đổi luồng đầu vào của WebSocketFrame thành luồng đầu ra của WebSocketFrame
wsEndpoint.toRoutes[_ => Task.pure[Right[handleWebSocket]]]
Trước khi chúng tôi bắt đầu gửi luồng âm thanh tới STT, chúng tôi phải tạo SpeechClient và thiết lập kết nối gRPC
const audioContext = new window.AudioContext[{sampleRate: sampleRate}]
0Máy chủ RecognitionObserver của chúng tôi sẽ nhận phản hồi từ STT và đẩy nó vào Hàng đợi fs2 sau khi chuyển sang JSON đơn giản
const audioContext = new window.AudioContext[{sampleRate: sampleRate}]
1Tin nhắn đầu tiên được gửi đến STT sau khi kết nối phải là cấu hình. Chúng tôi phải cung cấp các tham số của luồng âm thanh [mã hóa và tỷ lệ mẫu] và chúng tôi có thể định cấu hình một số tham số của quy trình nhận dạng như mô hình nhận dạng, ngôn ngữ hoặc liệu chúng tôi có muốn nhận kết quả tạm thời hay không
const audioContext = new window.AudioContext[{sampleRate: sampleRate}]
2Gửi cấu hình
const audioContext = new window.AudioContext[{sampleRate: sampleRate}]
3Sau đó, chúng tôi có thể bắt đầu gửi các đoạn luồng âm thanh tới STT gói chúng vào StreamingRecognizeRequest
const audioContext = new window.AudioContext[{sampleRate: sampleRate}]
4Và cuối cùng, xử lý Ống WebSocket kết nối WebSocket với luồng STT
const audioContext = new window.AudioContext[{sampleRate: sampleRate}]
5Ví dụ làm việcVí dụ làm việc có thể được tìm thấy ở đây. https. //github. com/gobio/bootzooka-speech-to-text
Nó dựa trên Bootzooka của SoftwareMill, hãy xem tài liệu về cách khởi động ứng dụng. Hãy nhớ đặt biến môi trường GOOGLE_APPLICATION_CREDENTIALS trỏ đến khóa JSON của tài khoản dịch vụ đã tải xuống. Ví dụ này chỉ chứa các yếu tố cần thiết để nó hoạt động, cụ thể là nó thiếu cách xử lý lỗi thích hợp