File size: 4,637 Bytes
23590ba edcef16 475d403 b7dec53 d114f5b 4164780 d114f5b 4164780 b7dec53 65f7061 b7dec53 c80867b 07478ab 250b797 65f7061 d114f5b 65f7061 d114f5b b7dec53 d114f5b 65f7061 d114f5b b7dec53 4164780 b7dec53 65f7061 b7dec53 d114f5b b7dec53 d114f5b b7dec53 65f7061 b7dec53 d114f5b b90ae45 d114f5b b7dec53 d114f5b 65f7061 475d403 b7dec53 d114f5b 65f7061 4164780 65f7061 4164780 65f7061 b7dec53 981b713 9225a67 6357dfa |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
import json
import tempfile
import ffmpeg
import os
import wave # ✅ Fix lỗi thiếu import wave
from flask import Flask, request, jsonify
from flask_cors import CORS
from vosk import Model, KaldiRecognizer
from flasgger import Swagger
# Khởi tạo Flask app trước khi sử dụng
app = Flask(__name__)
CORS(app)
Swagger(app)
# Load model Vosk
MODEL_PATH = "model/vosk-model"
print("\u2705 Đang tải model Vosk...")
model = Model(MODEL_PATH)
@app.route("/")
def home():
"""API Home
---
responses:
200:
description: API đang chạy
"""
return "\u2705 Vosk STT API đang chạy!"
@app.route("/stt", methods=["POST"])
def stt():
"""Chuyển đổi giọng nói thành văn bản (Speech-to-Text)
---
consumes:
- multipart/form-data
parameters:
- in: formData
name: file
type: file
required: true
description: File âm thanh WebM (sẽ được chuyển đổi sang WAV mono PCM)
responses:
200:
description: Kết quả chuyển đổi văn bản
schema:
type: object
properties:
text:
type: string
example: "Xin chào thế giới"
400:
description: Lỗi nếu file âm thanh không hợp lệ hoặc không tìm thấy
500:
description: Lỗi server nội bộ
"""
if "file" not in request.files:
return jsonify({"error": "Không tìm thấy file âm thanh! Vui lòng gửi trường 'file'."}), 400
audio_file = request.files["file"]
if audio_file.filename == "":
return jsonify({"error": "Không có file được chọn!"}), 400
# Lưu file WebM tạm thời
with tempfile.NamedTemporaryFile(suffix=".webm", delete=False) as temp_webm_file:
webm_path = temp_webm_file.name
audio_file.save(webm_path)
# Kiểm tra kích thước tệp
if os.path.getsize(webm_path) < 100:
os.remove(webm_path)
return jsonify({"error": "Tệp âm thanh quá nhỏ hoặc rỗng!"}), 400
# Xử lý tệp WebM -> WAV
wav_path = tempfile.mktemp(suffix=".wav")
try:
# Kiểm tra tệp WebM có chứa audio hợp lệ không
try:
probe = ffmpeg.probe(webm_path)
if 'streams' not in probe or not any(s['codec_type'] == 'audio' for s in probe['streams']):
raise ValueError("Tệp không chứa luồng âm thanh hợp lệ!")
except ffmpeg.Error as e:
error_message = e.stderr.decode('utf-8') if e.stderr else str(e)
return jsonify({"error": f"Lỗi kiểm tra tệp WebM: {error_message}"}), 500
# Chuyển đổi WebM sang WAV mono PCM
ffmpeg.input(webm_path).output(
wav_path, acodec="pcm_s16le", ac=1, ar=16000
).run(overwrite_output=True, quiet=True)
# Mở file WAV
wf = wave.open(wav_path, "rb")
# Kiểm tra định dạng WAV có hợp lệ không
if wf.getnchannels() != 1 or wf.getsampwidth() != 2 or wf.getcomptype() != "NONE":
wf.close()
os.remove(wav_path)
return jsonify({"error": "Định dạng WAV không hợp lệ!"}), 400
# Chạy Vosk để nhận diện giọng nói
rec = KaldiRecognizer(model, wf.getframerate())
result_text = ""
while True:
data = wf.readframes(4000)
if len(data) == 0:
break
if rec.AcceptWaveform(data):
result = json.loads(rec.Result())
result_text += result.get("text", "") + " "
else:
partial_result = json.loads(rec.PartialResult())
if partial_result.get("partial", ""):
result_text += partial_result["partial"] + " "
wf.close() # ✅ Đóng file WAV
final_text = result_text.strip() or "Không nhận diện được nội dung âm thanh." # ✅ Fix lỗi Unicode
return jsonify({"text": final_text})
except ffmpeg.Error as e:
error_message = e.stderr.decode('utf-8') if e.stderr else str(e)
return jsonify({"error": f"Lỗi chuyển đổi âm thanh từ WebM sang WAV: {error_message}"}), 500
except Exception as e:
return jsonify({"error": f"Lỗi xử lý âm thanh: {str(e)}"}), 500
finally:
# Xóa các file tạm
if os.path.exists(webm_path):
os.remove(webm_path)
if os.path.exists(wav_path):
os.remove(wav_path)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=7860, debug=True)
|