tudeplom commited on
Commit
475d403
·
verified ·
1 Parent(s): 6357dfa

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +21 -86
app.py CHANGED
@@ -1,18 +1,14 @@
1
  import json
2
  import tempfile
3
  import ffmpeg
 
 
4
  from flask import Flask, request, jsonify
5
  from flask_cors import CORS
6
-
7
-
8
  from vosk import Model, KaldiRecognizer
9
  from flasgger import Swagger
10
 
11
- # Thư mục chứa model
12
-
13
-
14
-
15
-
16
  MODEL_PATH = "model/vosk-model"
17
  print("\u2705 Đang tải model Vosk...")
18
  model = Model(MODEL_PATH)
@@ -24,40 +20,10 @@ Swagger(app)
24
 
25
  @app.route("/")
26
  def home():
27
- """API Home
28
- ---
29
- responses:
30
- 200:
31
- description: API đang chạy
32
- """
33
  return "\u2705 Vosk STT API đang chạy!"
34
 
35
  @app.route("/stt", methods=["POST"])
36
  def stt():
37
- """Chuyển đổi giọng nói thành văn bản (Speech-to-Text)
38
- ---
39
- consumes:
40
- - multipart/form-data
41
- parameters:
42
- - in: formData
43
- name: file
44
- type: file
45
- required: true
46
- description: File âm thanh WebM (sẽ được chuyển đổi sang WAV mono PCM)
47
- responses:
48
- 200:
49
- description: Kết quả chuyển đổi văn bản
50
- schema:
51
- type: object
52
- properties:
53
- text:
54
- type: string
55
- example: "Xin chào thế giới"
56
- 400:
57
- description: Lỗi nếu file âm thanh không hợp lệ hoặc không tìm thấy
58
- 500:
59
- description: Lỗi server nội bộ
60
- """
61
  if "file" not in request.files:
62
  return jsonify({"error": "Không tìm thấy file âm thanh! Vui lòng gửi trường 'file'."}), 400
63
 
@@ -70,50 +36,29 @@ def stt():
70
  webm_path = temp_webm_file.name
71
  audio_file.save(webm_path)
72
 
73
- # Kiểm tra kích thước tệp
74
  if os.path.getsize(webm_path) < 100:
75
  os.remove(webm_path)
76
  return jsonify({"error": "Tệp âm thanh quá nhỏ hoặc rỗng!"}), 400
77
 
78
- # Đường dẫn file WAV tạm thời sau khi chuyển đổi
79
- wav_path = None
80
- wf = None
81
  try:
82
- # Kiểm tra tệp WebM bằng ffprobe trước khi chuyển đổi
83
- try:
84
- probe = ffmpeg.probe(webm_path)
85
- if 'streams' not in probe or not any(s['codec_type'] == 'audio' for s in probe['streams']):
86
- raise ValueError("Tệp không chứa luồng âm thanh hợp lệ!")
87
- except ffmpeg.Error as e:
88
- error_message = e.stderr.decode('utf-8') if e.stderr else str(e)
89
- return jsonify({"error": f"Lỗi kiểm tra tệp WebM: {error_message}"}), 500
90
-
91
- # Chuyển đổi WebM sang WAV mono PCM
92
- wav_path = tempfile.mktemp(suffix=".wav")
93
- stream = ffmpeg.input(webm_path)
94
- stream = ffmpeg.output(
95
- stream,
96
- wav_path,
97
- acodec="pcm_s16le", # PCM 16-bit signed little-endian
98
- ac=1, # Mono
99
- ar=16000, # Tần số mẫu 16kHz, phù hợp với Vosk
100
- format="wav"
101
- )
102
- # Thêm cờ -vn để bỏ qua video nếu có và -y để ghi đè
103
- ffmpeg.run(stream, overwrite_output=True, quiet=True, capture_stdout=True, capture_stderr=True)
104
-
105
- # Mở file WAV đã chuyển đổi
106
  wf = wave.open(wav_path, "rb")
107
 
108
- # Kiểm tra định dạng WAV mono PCM
109
  if wf.getnchannels() != 1 or wf.getsampwidth() != 2 or wf.getcomptype() != "NONE":
110
- return jsonify({"error": "Định dạng WAV sau chuyển đổi không đúng!"}), 400
 
111
 
112
- # Khởi tạo KaldiRecognizer
113
  rec = KaldiRecognizer(model, wf.getframerate())
114
  result_text = ""
115
 
116
- # Đọc và xử lý dữ liệu âm thanh
117
  while True:
118
  data = wf.readframes(4000)
119
  if len(data) == 0:
@@ -123,29 +68,19 @@ def stt():
123
  result_text += result.get("text", "") + " "
124
  else:
125
  partial_result = json.loads(rec.PartialResult())
126
- if partial_result.get("partial", ""):
127
- result_text += partial_result["partial"] + " "
128
 
129
- # Trả về kết quả đã xử lý
130
- final_text = result_text.strip()
131
- if not final_text:
132
- final_text = "Không nh��n diện được nội dung âm thanh."
133
  return jsonify({"text": final_text})
134
 
135
- except ffmpeg.Error as e:
136
- error_message = e.stderr.decode('utf-8') if e.stderr else str(e)
137
- return jsonify({"error": f"Lỗi chuyển đổi âm thanh từ WebM sang WAV: {error_message}"}), 500
138
  except Exception as e:
139
- return jsonify({"error": f"Lỗi xử âm thanh: {str(e)}"}), 500
140
 
141
  finally:
142
- # Đóng file WAV nếu đã mở
143
- if wf is not None:
144
- wf.close()
145
- # Xóa các file tạm
146
- for path in [webm_path, wav_path]:
147
- if path and os.path.exists(path):
148
- os.remove(path)
149
 
150
  if __name__ == "__main__":
151
  app.run(host="0.0.0.0", port=7860, debug=True)
 
1
  import json
2
  import tempfile
3
  import ffmpeg
4
+ import wave # ✅ Fix lỗi thiếu import wave
5
+ import os
6
  from flask import Flask, request, jsonify
7
  from flask_cors import CORS
 
 
8
  from vosk import Model, KaldiRecognizer
9
  from flasgger import Swagger
10
 
11
+ # Load model Vosk
 
 
 
 
12
  MODEL_PATH = "model/vosk-model"
13
  print("\u2705 Đang tải model Vosk...")
14
  model = Model(MODEL_PATH)
 
20
 
21
  @app.route("/")
22
  def home():
 
 
 
 
 
 
23
  return "\u2705 Vosk STT API đang chạy!"
24
 
25
  @app.route("/stt", methods=["POST"])
26
  def stt():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  if "file" not in request.files:
28
  return jsonify({"error": "Không tìm thấy file âm thanh! Vui lòng gửi trường 'file'."}), 400
29
 
 
36
  webm_path = temp_webm_file.name
37
  audio_file.save(webm_path)
38
 
39
+ # Kiểm tra kích thước file
40
  if os.path.getsize(webm_path) < 100:
41
  os.remove(webm_path)
42
  return jsonify({"error": "Tệp âm thanh quá nhỏ hoặc rỗng!"}), 400
43
 
44
+ # Xử tệp WebM -> WAV
45
+ wav_path = tempfile.mktemp(suffix=".wav")
 
46
  try:
47
+ ffmpeg.input(webm_path).output(
48
+ wav_path, acodec="pcm_s16le", ac=1, ar=16000
49
+ ).run(overwrite_output=True, quiet=True)
50
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  wf = wave.open(wav_path, "rb")
52
 
53
+ # Kiểm tra WAV đúng chuẩn không
54
  if wf.getnchannels() != 1 or wf.getsampwidth() != 2 or wf.getcomptype() != "NONE":
55
+ wf.close()
56
+ return jsonify({"error": "Định dạng WAV không hợp lệ!"}), 400
57
 
58
+ # Chạy Vosk để nhận diện giọng nói
59
  rec = KaldiRecognizer(model, wf.getframerate())
60
  result_text = ""
61
 
 
62
  while True:
63
  data = wf.readframes(4000)
64
  if len(data) == 0:
 
68
  result_text += result.get("text", "") + " "
69
  else:
70
  partial_result = json.loads(rec.PartialResult())
71
+ result_text += partial_result.get("partial", "") + " "
 
72
 
73
+ wf.close() # Fix lỗi quên đóng file
74
+
75
+ final_text = result_text.strip() or "Không nhận diện được nội dung âm thanh." # ✅ Fix lỗi Unicode
 
76
  return jsonify({"text": final_text})
77
 
 
 
 
78
  except Exception as e:
79
+ return jsonify({"error": f"Lỗi xử lý: {str(e)}"}), 500
80
 
81
  finally:
82
+ os.remove(webm_path) if os.path.exists(webm_path) else None
83
+ os.remove(wav_path) if os.path.exists(wav_path) else None
 
 
 
 
 
84
 
85
  if __name__ == "__main__":
86
  app.run(host="0.0.0.0", port=7860, debug=True)