IZERE HIRWA Roger commited on
Commit
4e1bce5
·
1 Parent(s): dfbe201
Files changed (4) hide show
  1. Dockerfile +0 -9
  2. app.py +4 -2
  3. templates/index.html +174 -3
  4. templates/static/css/style.css +0 -93
Dockerfile CHANGED
@@ -30,15 +30,6 @@ RUN wget -P /app/SadTalker/checkpoints \
30
  # Copy application files
31
  COPY . .
32
 
33
- # Create necessary directories with proper structure
34
- RUN mkdir -p /app/static/uploads && chmod -R 777 /app/static/uploads
35
- RUN mkdir -p /app/static/css && chmod -R 777 /app/static/css
36
- RUN mkdir -p /app/static/js && chmod -R 777 /app/static/js
37
- RUN mkdir -p /app/templates && chmod -R 777 /app/templates
38
-
39
- # Ensure static files are copied correctly
40
- COPY templates/ /app/templates/
41
-
42
  # Add SadTalker to Python path
43
  ENV PYTHONPATH="${PYTHONPATH}:/app/SadTalker/src"
44
 
 
30
  # Copy application files
31
  COPY . .
32
 
 
 
 
 
 
 
 
 
 
33
  # Add SadTalker to Python path
34
  ENV PYTHONPATH="${PYTHONPATH}:/app/SadTalker/src"
35
 
app.py CHANGED
@@ -4,7 +4,8 @@ sys.path.append('/app/SadTalker/src')
4
 
5
  from flask import Flask, render_template, request, jsonify, send_from_directory
6
 
7
- app = Flask(__name__, static_folder='static', static_url_path='/static')
 
8
 
9
  # Initialize SadTalker with proper import
10
  try:
@@ -46,7 +47,7 @@ def generate():
46
  # Text-to-Speech (using gTTS)
47
  from gtts import gTTS
48
  tts = gTTS(text=text, lang='en')
49
-
50
  tts.save(audio_path)
51
 
52
  # Generate video (CPU optimized)
@@ -72,6 +73,7 @@ def generate():
72
  @app.route('/debug/static')
73
  def debug_static():
74
  static_files = []
 
75
  for root, dirs, files in os.walk('static'):
76
  for file in files:
77
  static_files.append(os.path.join(root, file))
 
4
 
5
  from flask import Flask, render_template, request, jsonify, send_from_directory
6
 
7
+ # app = Flask(__name__, static_folder='static', static_url_path='/static')
8
+ app = Flask(__name__)
9
 
10
  # Initialize SadTalker with proper import
11
  try:
 
47
  # Text-to-Speech (using gTTS)
48
  from gtts import gTTS
49
  tts = gTTS(text=text, lang='en')
50
+
51
  tts.save(audio_path)
52
 
53
  # Generate video (CPU optimized)
 
73
  @app.route('/debug/static')
74
  def debug_static():
75
  static_files = []
76
+
77
  for root, dirs, files in os.walk('static'):
78
  for file in files:
79
  static_files.append(os.path.join(root, file))
templates/index.html CHANGED
@@ -11,7 +11,101 @@
11
  <link href="https://fonts.googleapis.com/css2?family=Nunito:wght@200;300;400;600;700;800;900&display=swap" rel="stylesheet">
12
 
13
  <!-- Custom CSS -->
14
- <link href="{{ url_for('static', filename='css/style.css') }}" rel="stylesheet">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  </head>
16
  <body>
17
  <div class="container py-5">
@@ -68,7 +162,84 @@
68
  <!-- Bootstrap JS -->
69
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
70
 
71
- <!-- Custom JS -->
72
- <script src="{{ url_for('static', filename='js/scripts.js') }}"></script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  </body>
74
  </html>
 
11
  <link href="https://fonts.googleapis.com/css2?family=Nunito:wght@200;300;400;600;700;800;900&display=swap" rel="stylesheet">
12
 
13
  <!-- Custom CSS -->
14
+ <style>
15
+ /* Custom Bootstrap overrides */
16
+ :root {
17
+ --primary-color: #4e73df;
18
+ --secondary-color: #858796;
19
+ --success-color: #1cc88a;
20
+ }
21
+
22
+ body {
23
+ background-color: #f8f9fc;
24
+ font-family: 'Nunito', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
25
+ }
26
+
27
+ .card {
28
+ border: none;
29
+ border-radius: 0.35rem;
30
+ box-shadow: 0 0.15rem 1.75rem 0 rgba(58, 59, 69, 0.15);
31
+ }
32
+
33
+ .card-header {
34
+ background-color: var(--primary-color);
35
+ border-bottom: none;
36
+ }
37
+
38
+ .btn-primary {
39
+ background-color: var(--primary-color);
40
+ border-color: var(--primary-color);
41
+ }
42
+
43
+ .btn-primary:hover {
44
+ background-color: #2e59d9;
45
+ border-color: #2653d4;
46
+ }
47
+
48
+ /* Upload area styling */
49
+ .upload-area {
50
+ border: 2px dashed #d1d3e2;
51
+ border-radius: 0.35rem;
52
+ padding: 2rem;
53
+ text-align: center;
54
+ margin-bottom: 1.5rem;
55
+ cursor: pointer;
56
+ transition: all 0.3s;
57
+ }
58
+
59
+ .upload-area:hover {
60
+ border-color: var(--primary-color);
61
+ background-color: rgba(78, 115, 223, 0.05);
62
+ }
63
+
64
+ .upload-area i {
65
+ font-size: 3rem;
66
+ color: var(--secondary-color);
67
+ margin-bottom: 1rem;
68
+ }
69
+
70
+ /* Video result styling */
71
+ #result {
72
+ transition: all 0.3s;
73
+ }
74
+
75
+ #outputVideo {
76
+ border-radius: 0.35rem;
77
+ background-color: #000;
78
+ }
79
+
80
+ /* Loading spinner */
81
+ .spinner-border {
82
+ width: 1.2rem;
83
+ height: 1.2rem;
84
+ border-width: 0.15em;
85
+ }
86
+
87
+ /* Responsive adjustments */
88
+ @media (max-width: 768px) {
89
+ .card-body {
90
+ padding: 1.25rem;
91
+ }
92
+
93
+ .upload-area {
94
+ padding: 1.5rem;
95
+ }
96
+ }
97
+
98
+ /* Animation for processing state */
99
+ @keyframes pulse {
100
+ 0% { opacity: 0.6; }
101
+ 50% { opacity: 1; }
102
+ 100% { opacity: 0.6; }
103
+ }
104
+
105
+ .processing {
106
+ animation: pulse 1.5s infinite;
107
+ }
108
+ </style>
109
  </head>
110
  <body>
111
  <div class="container py-5">
 
162
  <!-- Bootstrap JS -->
163
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
164
 
165
+ <script>
166
+ // Debug: Check if script is loaded
167
+ console.log('Scripts.js loaded successfully');
168
+
169
+ document.addEventListener('DOMContentLoaded', function() {
170
+ console.log('DOM loaded, initializing form handler');
171
+
172
+ const form = document.getElementById('avatarForm');
173
+ if (!form) {
174
+ console.error('Avatar form not found!');
175
+ return;
176
+ }
177
+
178
+ form.addEventListener('submit', async (e) => {
179
+ e.preventDefault();
180
+ console.log('Form submitted');
181
+
182
+ const imageInput = document.getElementById('imageInput');
183
+ const textInput = document.getElementById('textInput');
184
+
185
+ if (!imageInput.files[0]) {
186
+ alert('Please select an image');
187
+ return;
188
+ }
189
+
190
+ if (!textInput.value.trim()) {
191
+ alert('Please enter some text');
192
+ return;
193
+ }
194
+
195
+ const formData = new FormData();
196
+ formData.append('image', imageInput.files[0]);
197
+ formData.append('text', textInput.value);
198
+
199
+ // Show loading state
200
+ const btn = document.querySelector('button[type="submit"]');
201
+ btn.disabled = true;
202
+ btn.innerHTML = '<span class="spinner-border spinner-border-sm me-2" role="status"></span> Processing...';
203
+
204
+ try {
205
+ console.log('Sending request to /generate');
206
+ const response = await fetch('/generate', {
207
+ method: 'POST',
208
+ body: formData
209
+ });
210
+
211
+ if (!response.ok) {
212
+ throw new Error(`HTTP error! status: ${response.status}`);
213
+ }
214
+
215
+ const data = await response.json();
216
+ console.log('Response received:', data);
217
+
218
+ if (data.error) {
219
+ throw new Error(data.error);
220
+ }
221
+
222
+ // Display result
223
+ const video = document.getElementById('outputVideo');
224
+ video.src = data.video;
225
+ document.getElementById('result').classList.remove('d-none');
226
+
227
+ // Set up download
228
+ document.getElementById('downloadBtn').onclick = () => {
229
+ const a = document.createElement('a');
230
+ a.href = data.video;
231
+ a.download = 'talking_avatar.mp4';
232
+ a.click();
233
+ };
234
+ } catch (error) {
235
+ console.error('Error:', error);
236
+ alert('Error: ' + error.message);
237
+ } finally {
238
+ btn.disabled = false;
239
+ btn.innerHTML = '<i class="fas fa-magic me-2"></i>Generate Video';
240
+ }
241
+ });
242
+ });
243
+ </script>
244
  </body>
245
  </html>
templates/static/css/style.css CHANGED
@@ -1,93 +0,0 @@
1
- /* Custom Bootstrap overrides */
2
- :root {
3
- --primary-color: #4e73df;
4
- --secondary-color: #858796;
5
- --success-color: #1cc88a;
6
- }
7
-
8
- body {
9
- background-color: #f8f9fc;
10
- font-family: 'Nunito', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
11
- }
12
-
13
- .card {
14
- border: none;
15
- border-radius: 0.35rem;
16
- box-shadow: 0 0.15rem 1.75rem 0 rgba(58, 59, 69, 0.15);
17
- }
18
-
19
- .card-header {
20
- background-color: var(--primary-color);
21
- border-bottom: none;
22
- }
23
-
24
- .btn-primary {
25
- background-color: var(--primary-color);
26
- border-color: var(--primary-color);
27
- }
28
-
29
- .btn-primary:hover {
30
- background-color: #2e59d9;
31
- border-color: #2653d4;
32
- }
33
-
34
- /* Upload area styling */
35
- .upload-area {
36
- border: 2px dashed #d1d3e2;
37
- border-radius: 0.35rem;
38
- padding: 2rem;
39
- text-align: center;
40
- margin-bottom: 1.5rem;
41
- cursor: pointer;
42
- transition: all 0.3s;
43
- }
44
-
45
- .upload-area:hover {
46
- border-color: var(--primary-color);
47
- background-color: rgba(78, 115, 223, 0.05);
48
- }
49
-
50
- .upload-area i {
51
- font-size: 3rem;
52
- color: var(--secondary-color);
53
- margin-bottom: 1rem;
54
- }
55
-
56
- /* Video result styling */
57
- #result {
58
- transition: all 0.3s;
59
- }
60
-
61
- #outputVideo {
62
- border-radius: 0.35rem;
63
- background-color: #000;
64
- }
65
-
66
- /* Loading spinner */
67
- .spinner-border {
68
- width: 1.2rem;
69
- height: 1.2rem;
70
- border-width: 0.15em;
71
- }
72
-
73
- /* Responsive adjustments */
74
- @media (max-width: 768px) {
75
- .card-body {
76
- padding: 1.25rem;
77
- }
78
-
79
- .upload-area {
80
- padding: 1.5rem;
81
- }
82
- }
83
-
84
- /* Animation for processing state */
85
- @keyframes pulse {
86
- 0% { opacity: 0.6; }
87
- 50% { opacity: 1; }
88
- 100% { opacity: 0.6; }
89
- }
90
-
91
- .processing {
92
- animation: pulse 1.5s infinite;
93
- }