EllenBeta commited on
Commit
7c7d4ab
·
verified ·
1 Parent(s): bbcc1b1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +130 -91
app.py CHANGED
@@ -1,129 +1,168 @@
1
  from flask import Flask, request, jsonify, render_template
2
- from datetime import datetime, timedelta
3
  from flask_cors import CORS
4
  from TTS.api import TTS
5
  import os
6
  import base64
7
- from helper import save_audio, generate_random_filename, save_to_dataset_repo, video_to_audio, validate_audio_file, ensure_wav_format
 
 
 
 
 
 
 
8
  import wave
9
- import requests
10
 
11
  app = Flask(__name__)
12
  CORS(app)
13
  os.environ["COQUI_TOS_AGREED"] = "1"
14
 
15
  device = "cpu"
16
-
17
  tts = TTS("tts_models/multilingual/multi-dataset/xtts_v2").to(device)
18
-
19
  active_tasks = {}
20
 
 
 
 
21
 
22
  @app.route("/")
23
  def greet_html():
24
  return render_template("home.html")
25
-
 
26
  @app.route("/sign-in")
27
  def sign_in():
28
- return render_template("sign_in.html")
 
29
 
30
  @app.route("/user_dash")
31
  def user_dash():
32
- user_id = request.args.get("user_id")
33
- if user_id:
34
- return render_template("u_dash.html", user_id=user_id)
35
-
36
- @app.route("/generate_voice", methods=['POST'])
 
 
37
  def generate_voice():
38
- try:
39
- data = request.get_json()
40
- if not data:
41
- return jsonify({'error': 'No JSON body'}), 400
42
- video = data.get('video')
43
- text = data.get('text')
44
- audio_base64 = data.get('audio')
45
- task_id = data.get('task_id')
46
- user_id = data.get('user_id')
47
- if not user_id:
48
- return jsonify({'error': 'you are required to signin before you could usw this Ai'})
49
- if not text:
50
- return jsonify({'error': 'please input a prompt'})
51
- if task_id in active_tasks:
52
- return jsonify({'error': f'There is already an active tasks for {task_id}'}), 409
53
- active_tasks[task_id]={
54
- "user_id": user_id,
55
- "status": "Processing",
56
- "created_at": datetime.now(),
57
- }
58
- process_vox(user_id, text, video, audio_base64, task_id)
59
- return jsonify({'message': 'Processing started', 'task_id': task_id}), 202
60
- except Exception as e:
61
- return jsonify({'error': str(e)}), 500
62
-
 
 
 
 
 
 
63
  def process_vox(user_id, text, video, audio_base64, task_id):
64
- temp_audio_path=None
65
- try:
66
- if audio_base64:
67
- if audio_base64.startswith('data:audio/'):
68
- audio_base64=audio_base64.split(',', 1)[1]
69
- temp_audio_path = f'/tmp/temp_ref_{task_id}.wav'
70
- with open(temp_audio_path, 'wb') as f:
71
- f.write(base64.b64decode(audio_base64))
72
- elif video:
73
- temp_audio_path = video_to_audio(video, output_path=temp_audio_path)
74
- temp_audio_path = ensure_wav_format(temp_audio_path)
75
-
76
- valid, msg = validate_audio_file(temp_audio_path, MAX_AUDIO_SIZE_MB)
77
- if not valid:
78
- raise Exception(f"Invalid audio file: {msg}")
79
- result_file= clone(text, temp_audio_path)
80
- out_dir = "user_audios"
81
-
82
- os.makedirs(out_dir, exist_ok=True)
83
- file_name = generate_random_filename("mp3")
84
- file_path = os.path.join(out_dir, file_name)
85
-
86
- with open(result_file, 'rb') as src, open(file_path, 'wb') as dst:
87
- dst.write(src.read())
88
-
89
- with wave.open(file_path, 'rb') as wf:
90
- dura = wf.getnframes() / float(wf.getframerate())
91
- duration=f"{dura:.2f}"
92
- title=text[:20]
93
- # Upload + save metadata
94
- audio_url = save_to_dataset_repo(file_path, f"user/data/audios/{file_name}", file_name)
95
- active_tasks[task_id].update({'status': 'completed', 'audio_url': audio_url, 'completion_time': datetime.now()})
96
- save_audio(user_id, audio_url, title or "Audio", text, duration)
97
- except Exception as e:
98
- active_tasks[task_id] = {'status': 'failed', 'error': str(e), 'completion_time': datetime.now()}
99
- finally:
100
- if os.path.exists(temp_audio_path):
101
- os.remove(temp_audio_path)
102
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  def clone(text, audio):
104
- tts.tts_to_file(text=text, speaker_wav=audio, language="en", file_path="./output.wav")
105
- return "./output.wav"
106
-
107
- @app.route('/task_status')
 
108
  def task_status():
109
  task_id = request.args.get("task_id")
110
  if not task_id:
111
- return jsonify({'error': 'task_id parameter is required'}), 400
112
-
113
  if task_id not in active_tasks:
114
- return jsonify({'status': 'not found'}), 404
115
 
116
  task = active_tasks[task_id]
117
  response_data = {
118
- 'status': task['status'],
119
- 'start_time': task.get('created_at').isoformat() if task.get('created_at') else None
120
  }
121
 
122
- if task['status'] == 'completed':
123
- response_data['audio_url'] = task.get('audio_url')
124
- response_data['completion_time'] = task.get('completion_time').isoformat() if task.get('completion_time') else None
125
- elif task['status'] == 'failed':
126
- response_data['error'] = task.get('error')
127
- response_data['completion_time'] = task.get('completion_time').isoformat() if task.get('completion_time') else None
 
 
 
 
128
 
129
  return jsonify(response_data)
 
1
  from flask import Flask, request, jsonify, render_template
2
+ from datetime import datetime
3
  from flask_cors import CORS
4
  from TTS.api import TTS
5
  import os
6
  import base64
7
+ from helper import (
8
+ save_audio,
9
+ generate_random_filename,
10
+ save_to_dataset_repo,
11
+ video_to_audio,
12
+ validate_audio_file,
13
+ ensure_wav_format,
14
+ )
15
  import wave
 
16
 
17
  app = Flask(__name__)
18
  CORS(app)
19
  os.environ["COQUI_TOS_AGREED"] = "1"
20
 
21
  device = "cpu"
 
22
  tts = TTS("tts_models/multilingual/multi-dataset/xtts_v2").to(device)
 
23
  active_tasks = {}
24
 
25
+ # Optional: set your max audio size (MB)
26
+ MAX_AUDIO_SIZE_MB = 15
27
+
28
 
29
  @app.route("/")
30
  def greet_html():
31
  return render_template("home.html")
32
+
33
+
34
  @app.route("/sign-in")
35
  def sign_in():
36
+ return render_template("sign_in.html")
37
+
38
 
39
  @app.route("/user_dash")
40
  def user_dash():
41
+ user_id = request.args.get("user_id")
42
+ if user_id:
43
+ return render_template("u_dash.html", user_id=user_id)
44
+ return jsonify({"error": "Missing user_id"}), 400
45
+
46
+
47
+ @app.route("/generate_voice", methods=["POST"])
48
  def generate_voice():
49
+ try:
50
+ data = request.get_json()
51
+ if not data:
52
+ return jsonify({"error": "No JSON body"}), 400
53
+
54
+ video = data.get("video")
55
+ text = data.get("text")
56
+ audio_base64 = data.get("audio")
57
+ task_id = data.get("task_id")
58
+ user_id = data.get("user_id")
59
+
60
+ if not user_id:
61
+ return jsonify({"error": "You must sign in before using this AI"}), 401
62
+ if not text:
63
+ return jsonify({"error": "Please input a prompt"}), 400
64
+ if task_id in active_tasks:
65
+ return jsonify({"error": f"There is already an active task for {task_id}"}), 409
66
+
67
+ active_tasks[task_id] = {
68
+ "user_id": user_id,
69
+ "status": "Processing",
70
+ "created_at": datetime.now(),
71
+ }
72
+
73
+ process_vox(user_id, text, video, audio_base64, task_id)
74
+ return jsonify({"message": "Processing started", "task_id": task_id}), 202
75
+
76
+ except Exception as e:
77
+ return jsonify({"error": str(e)}), 500
78
+
79
+
80
  def process_vox(user_id, text, video, audio_base64, task_id):
81
+ temp_audio_path = None
82
+ try:
83
+ # Handle audio or video input
84
+ if audio_base64:
85
+ if audio_base64.startswith("data:audio/"):
86
+ audio_base64 = audio_base64.split(",", 1)[1]
87
+ temp_audio_path = f"/tmp/temp_ref_{task_id}.wav"
88
+ with open(temp_audio_path, "wb") as f:
89
+ f.write(base64.b64decode(audio_base64))
90
+ elif video:
91
+ temp_audio_path = video_to_audio(video, output_path=temp_audio_path)
92
+
93
+ temp_audio_path = ensure_wav_format(temp_audio_path)
94
+
95
+ valid, msg = validate_audio_file(temp_audio_path, MAX_AUDIO_SIZE_MB)
96
+ if not valid:
97
+ raise Exception(f"Invalid audio file: {msg}")
98
+
99
+ result_file = clone(text, temp_audio_path)
100
+ out_dir = "user_audios"
101
+ os.makedirs(out_dir, exist_ok=True)
102
+
103
+ file_name = generate_random_filename("mp3")
104
+ file_path = os.path.join(out_dir, file_name)
105
+
106
+ with open(result_file, "rb") as src, open(file_path, "wb") as dst:
107
+ dst.write(src.read())
108
+
109
+ with wave.open(file_path, "rb") as wf:
110
+ dura = wf.getnframes() / float(wf.getframerate())
111
+ duration = f"{dura:.2f}"
112
+ title = text[:20]
113
+
114
+ # Upload + save metadata
115
+ audio_url = save_to_dataset_repo(file_path, f"user/data/audios/{file_name}", file_name)
116
+ active_tasks[task_id].update(
117
+ {
118
+ "status": "completed",
119
+ "audio_url": audio_url,
120
+ "completion_time": datetime.now(),
121
+ }
122
+ )
123
+ save_audio(user_id, audio_url, title or "Audio", text, duration)
124
+
125
+ except Exception as e:
126
+ active_tasks[task_id] = {
127
+ "status": "failed",
128
+ "error": str(e),
129
+ "completion_time": datetime.now(),
130
+ }
131
+
132
+ finally:
133
+ if temp_audio_path and os.path.exists(temp_audio_path):
134
+ os.remove(temp_audio_path)
135
+
136
+
137
  def clone(text, audio):
138
+ tts.tts_to_file(text=text, speaker_wav=audio, language="en", file_path="./output.wav")
139
+ return "./output.wav"
140
+
141
+
142
+ @app.route("/task_status")
143
  def task_status():
144
  task_id = request.args.get("task_id")
145
  if not task_id:
146
+ return jsonify({"error": "task_id parameter is required"}), 400
147
+
148
  if task_id not in active_tasks:
149
+ return jsonify({"status": "not found"}), 404
150
 
151
  task = active_tasks[task_id]
152
  response_data = {
153
+ "status": task["status"],
154
+ "start_time": task.get("created_at").isoformat() if task.get("created_at") else None,
155
  }
156
 
157
+ if task["status"] == "completed":
158
+ response_data["audio_url"] = task.get("audio_url")
159
+ response_data["completion_time"] = (
160
+ task.get("completion_time").isoformat() if task.get("completion_time") else None
161
+ )
162
+ elif task["status"] == "failed":
163
+ response_data["error"] = task.get("error")
164
+ response_data["completion_time"] = (
165
+ task.get("completion_time").isoformat() if task.get("completion_time") else None
166
+ )
167
 
168
  return jsonify(response_data)