hamza2923 commited on
Commit
b2b8afa
·
verified ·
1 Parent(s): 00d08df

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +123 -0
  2. requirements.txt +3 -0
app.py ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, request, jsonify, Response # Add Response here
2
+ from faster_whisper import WhisperModel
3
+ import torch
4
+ import io
5
+ import time
6
+ import datetime
7
+ from threading import Semaphore
8
+ import os
9
+ from werkzeug.utils import secure_filename
10
+ import tempfile
11
+
12
+ app = Flask(__name__)
13
+
14
+ # Configuration
15
+ MAX_CONCURRENT_REQUESTS = 2 # Adjust based on your server capacity
16
+ MAX_AUDIO_DURATION = 60 * 30 # 30 minutes maximum audio duration (adjust as needed)
17
+ TEMPORARY_FOLDER = tempfile.gettempdir()
18
+ ALLOWED_EXTENSIONS = {'mp3', 'wav', 'ogg', 'm4a', 'flac'}
19
+
20
+ # Device check for faster-whisper
21
+ device = "cuda" if torch.cuda.is_available() else "cpu"
22
+ compute_type = "float16" if device == "cuda" else "int8"
23
+ print(f"Using device: {device} with compute_type: {compute_type}")
24
+
25
+ # Faster Whisper setup with optimized parameters for long audio
26
+ beamsize = 2 # Slightly larger beam size can help with long-form accuracy
27
+ wmodel = WhisperModel(
28
+ "guillaumekln/faster-whisper-small",
29
+ device=device,
30
+ compute_type=compute_type,
31
+ download_root="./model_cache" # Cache model to avoid re-downloading
32
+ )
33
+
34
+ # Concurrency control
35
+ request_semaphore = Semaphore(MAX_CONCURRENT_REQUESTS)
36
+ active_requests = 0
37
+
38
+ def allowed_file(filename):
39
+ return '.' in filename and \
40
+ filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
41
+
42
+ def cleanup_temp_files(file_path):
43
+ """Ensure temporary files are deleted after processing"""
44
+ try:
45
+ if os.path.exists(file_path):
46
+ os.remove(file_path)
47
+ except Exception as e:
48
+ print(f"Error cleaning up temp file {file_path}: {str(e)}")
49
+
50
+ @app.route("/health", methods=["GET"])
51
+ def health_check():
52
+ """Endpoint to check if API is running"""
53
+ return jsonify({
54
+ 'status': 'API is running',
55
+ 'timestamp': datetime.datetime.now().isoformat(),
56
+ 'device': device,
57
+ 'compute_type': compute_type,
58
+ 'active_requests': active_requests,
59
+ 'max_duration_supported': MAX_AUDIO_DURATION
60
+ })
61
+
62
+ @app.route("/status/busy", methods=["GET"])
63
+ def server_busy():
64
+ """Endpoint to check if server is busy"""
65
+ is_busy = active_requests >= MAX_CONCURRENT_REQUESTS
66
+ return jsonify({
67
+ 'is_busy': is_busy,
68
+ 'active_requests': active_requests,
69
+ 'max_capacity': MAX_CONCURRENT_REQUESTS
70
+ })
71
+
72
+ @app.route("/whisper_transcribe", methods=["POST"])
73
+ def whisper_transcribe():
74
+ global active_requests
75
+
76
+ if not request_semaphore.acquire(blocking=False):
77
+ return jsonify({'error': 'Server busy'}), 503
78
+
79
+ active_requests += 1
80
+ start_time = time.time()
81
+ temp_file_path = None
82
+
83
+ try:
84
+ if 'audio' not in request.files:
85
+ return jsonify({'error': 'No file provided'}), 400
86
+
87
+ audio_file = request.files['audio']
88
+ if not (audio_file and allowed_file(audio_file.filename)):
89
+ return jsonify({'error': 'Invalid file format'}), 400
90
+
91
+ temp_file_path = os.path.join(TEMPORARY_FOLDER, secure_filename(audio_file.filename))
92
+ audio_file.save(temp_file_path)
93
+
94
+ segments, _ = wmodel.transcribe(
95
+ temp_file_path,
96
+ beam_size=beamsize,
97
+ vad_filter=True,
98
+ without_timestamps=True, # Ensure timestamps are not included
99
+ compression_ratio_threshold=2.4,
100
+ word_timestamps=False
101
+ )
102
+
103
+ full_text = " ".join(segment.text for segment in segments)
104
+ return jsonify({'transcription': full_text}), 200
105
+
106
+
107
+
108
+ except Exception as e:
109
+ return jsonify({'error': str(e)}), 500
110
+
111
+ finally:
112
+ if temp_file_path:
113
+ cleanup_temp_files(temp_file_path)
114
+ active_requests -= 1
115
+ request_semaphore.release()
116
+ print(f"Processed in {time.time()-start_time:.2f}s (Active: {active_requests})")
117
+
118
+ if __name__ == "__main__":
119
+ # Create temporary folder if it doesn't exist
120
+ if not os.path.exists(TEMPORARY_FOLDER):
121
+ os.makedirs(TEMPORARY_FOLDER)
122
+
123
+ app.run(host="0.0.0.0", port=7860, threaded=True)
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ flask
2
+ faster-whisper
3
+ torch