marquesafonso commited on
Commit
228a3b1
·
1 Parent(s): 6d792ca

MAJOR CHANGE: drop srt files, using only srt strings (wip); added moviepy font and color dropdowns + loading spinner (wip)

Browse files
main.py CHANGED
@@ -6,13 +6,22 @@ from utils.zip_response import zip_response
6
  from utils.read_html import read_html
7
 
8
  from fastapi import FastAPI, UploadFile, HTTPException, Form, Depends
 
9
  from fastapi.responses import HTMLResponse, Response
10
  from fastapi.security import HTTPBasic
11
  from pydantic import BaseModel, field_validator
12
 
 
 
 
 
 
 
13
  app = FastAPI()
14
  security = HTTPBasic()
15
  api_configs_file = os.path.abspath("api_config.yml")
 
 
16
 
17
  class MP4Video(BaseModel):
18
  video_file: UploadFile
@@ -30,25 +39,6 @@ class MP4Video(BaseModel):
30
  raise HTTPException(status_code=500, detail='Invalid video file type. Please upload an MP4 file.')
31
  return v
32
 
33
- class SRTFile(BaseModel):
34
- srt_file: Optional[UploadFile] = None
35
-
36
- @property
37
- def filename(self):
38
- return self.srt_file.filename
39
- @property
40
- def file(self):
41
- return self.srt_file.file
42
- @property
43
- def size(self):
44
- return self.srt_file.size
45
-
46
- @field_validator('srt_file')
47
- def validate_srt_file(cls, v):
48
- if v.size > 0 and not v.filename.endswith('.srt'):
49
- raise HTTPException(status_code=422, detail='Invalid subtitle file type. Please upload an SRT file.')
50
- return v
51
-
52
  @app.get("/")
53
  async def root():
54
  html_content = f"""
@@ -73,7 +63,6 @@ async def get_temp_dir():
73
 
74
  @app.post("/process_video/")
75
  async def process_video_api(video_file: MP4Video = Depends(),
76
- srt_file: SRTFile = Depends(),
77
  task: Optional[str] = Form("transcribe"),
78
  model_version: Optional[str] = Form("deepdml/faster-whisper-large-v3-turbo-ct2"),
79
  max_words_per_line: Optional[int] = Form(6),
@@ -93,25 +82,18 @@ async def process_video_api(video_file: MP4Video = Depends(),
93
  finally:
94
  video_file.file.close()
95
  logging.info("Copying SRT UploadFile to the temp_input_path")
96
- if srt_file.size > 0:
97
- with open(os.path.join(temp_dir, f"{video_file.filename.split('.')[0]}.srt"), 'w+b') as temp_srt_file:
98
- try:
99
- shutil.copyfileobj(srt_file.file, temp_srt_file)
100
- finally:
101
- srt_file.file.close()
102
- logging.info("Processing the video...")
103
- output_path, _ = process_video(temp_file.name, temp_srt_file.name, task, model_version, max_words_per_line, fontsize, font, bg_color, text_color, caption_mode)
104
- logging.info("Zipping response...")
105
- with open(os.path.join(temp_dir, f"{video_file.filename.split('.')[0]}.zip"), 'w+b') as temp_zip_file:
106
- zip_file = zip_response(temp_zip_file.name, [output_path, srt_path])
107
- return Response(content = zip_file)
108
- with open(os.path.join(temp_dir, f"{video_file.filename.split('.')[0]}.srt"), 'w+b') as temp_srt_file:
109
  logging.info("Processing the video...")
110
- output_path, srt_path = process_video(temp_file.name, None, task, model_version, max_words_per_line, fontsize, font, bg_color, text_color, caption_mode, api_configs_file)
111
- logging.info("Zipping response...")
112
- with open(os.path.join(temp_dir, f"{video_file.filename.split('.')[0]}.zip"), 'w+b') as temp_zip_file:
113
- zip_file = zip_response(temp_zip_file.name, [output_path, srt_path])
114
- return Response(content = zip_file)
 
 
 
 
 
115
  except Exception as e:
116
  raise HTTPException(status_code=500, detail=str(e))
117
 
 
6
  from utils.read_html import read_html
7
 
8
  from fastapi import FastAPI, UploadFile, HTTPException, Form, Depends
9
+ from fastapi.staticfiles import StaticFiles
10
  from fastapi.responses import HTMLResponse, Response
11
  from fastapi.security import HTTPBasic
12
  from pydantic import BaseModel, field_validator
13
 
14
+ ## THIS IS A BREAKING CHANGE. SRT FILE INPUT DEPRECATED. WIP.
15
+ ## TODO: add word level highlighting option
16
+ ## TODO: separate transcriber from subtitler logic + allow for interactive validation of trancription in-browser
17
+ ## TODO: add video preview component
18
+ ## TODO: improve loading spinner.
19
+
20
  app = FastAPI()
21
  security = HTTPBasic()
22
  api_configs_file = os.path.abspath("api_config.yml")
23
+ static_dir = os.path.join(os.path.dirname(__file__), 'static')
24
+ app.mount("/static", StaticFiles(directory=static_dir), name="static")
25
 
26
  class MP4Video(BaseModel):
27
  video_file: UploadFile
 
39
  raise HTTPException(status_code=500, detail='Invalid video file type. Please upload an MP4 file.')
40
  return v
41
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  @app.get("/")
43
  async def root():
44
  html_content = f"""
 
63
 
64
  @app.post("/process_video/")
65
  async def process_video_api(video_file: MP4Video = Depends(),
 
66
  task: Optional[str] = Form("transcribe"),
67
  model_version: Optional[str] = Form("deepdml/faster-whisper-large-v3-turbo-ct2"),
68
  max_words_per_line: Optional[int] = Form(6),
 
82
  finally:
83
  video_file.file.close()
84
  logging.info("Copying SRT UploadFile to the temp_input_path")
85
+ with open(os.path.join(temp_dir, f"{video_file.filename.split('.')[0]}.srt"), 'w+') as temp_srt_file:
 
 
 
 
 
 
 
 
 
 
 
 
86
  logging.info("Processing the video...")
87
+ output_path, srt_string = process_video(temp_file.name, task, model_version, max_words_per_line, fontsize, font, bg_color, text_color, caption_mode, api_configs_file)
88
+ temp_srt_file.write(srt_string)
89
+ logging.info("Zipping response...")
90
+ with open(os.path.join(temp_dir, f"{video_file.filename.split('.')[0]}.zip"), 'w+b') as temp_zip_file:
91
+ zip_file = zip_response(temp_zip_file.name, [output_path, temp_srt_file.name])
92
+ return Response(
93
+ content = zip_file,
94
+ media_type="application/zip",
95
+ headers={"Content-Disposition": f"attachment; filename={video_file.filename.split('.')[0]}.zip"}
96
+ )
97
  except Exception as e:
98
  raise HTTPException(status_code=500, detail=str(e))
99
 
static/colors.txt ADDED
@@ -0,0 +1,678 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ AliceBlue
2
+ AntiqueWhite
3
+ AntiqueWhite1
4
+ AntiqueWhite2
5
+ AntiqueWhite3
6
+ AntiqueWhite4
7
+ aqua
8
+ aquamarine
9
+ aquamarine1
10
+ aquamarine2
11
+ aquamarine3
12
+ aquamarine4
13
+ azure
14
+ azure1
15
+ azure2
16
+ azure3
17
+ azure4
18
+ beige
19
+ bisque
20
+ bisque1
21
+ bisque2
22
+ bisque3
23
+ bisque4
24
+ black
25
+ BlanchedAlmond
26
+ blue
27
+ blue1
28
+ blue2
29
+ blue3
30
+ blue4
31
+ BlueViolet
32
+ brown
33
+ brown1
34
+ brown2
35
+ brown3
36
+ brown4
37
+ burlywood
38
+ burlywood1
39
+ burlywood2
40
+ burlywood3
41
+ burlywood4
42
+ CadetBlue
43
+ CadetBlue1
44
+ CadetBlue2
45
+ CadetBlue3
46
+ CadetBlue4
47
+ chartreuse
48
+ chartreuse1
49
+ chartreuse2
50
+ chartreuse3
51
+ chartreuse4
52
+ chocolate
53
+ chocolate1
54
+ chocolate2
55
+ chocolate3
56
+ chocolate4
57
+ coral
58
+ coral1
59
+ coral2
60
+ coral3
61
+ coral4
62
+ CornflowerBlue
63
+ cornsilk
64
+ cornsilk1
65
+ cornsilk2
66
+ cornsilk3
67
+ cornsilk4
68
+ crimson
69
+ cyan
70
+ cyan1
71
+ cyan2
72
+ cyan3
73
+ cyan4
74
+ DarkBlue
75
+ DarkCyan
76
+ DarkGoldenrod
77
+ DarkGoldenrod1
78
+ DarkGoldenrod2
79
+ DarkGoldenrod3
80
+ DarkGoldenrod4
81
+ DarkGray
82
+ DarkGreen
83
+ DarkGrey
84
+ DarkKhaki
85
+ DarkMagenta
86
+ DarkOliveGreen
87
+ DarkOliveGreen1
88
+ DarkOliveGreen2
89
+ DarkOliveGreen3
90
+ DarkOliveGreen4
91
+ DarkOrange
92
+ DarkOrange1
93
+ DarkOrange2
94
+ DarkOrange3
95
+ DarkOrange4
96
+ DarkOrchid
97
+ DarkOrchid1
98
+ DarkOrchid2
99
+ DarkOrchid3
100
+ DarkOrchid4
101
+ DarkRed
102
+ DarkSalmon
103
+ DarkSeaGreen
104
+ DarkSeaGreen1
105
+ DarkSeaGreen2
106
+ DarkSeaGreen3
107
+ DarkSeaGreen4
108
+ DarkSlateBlue
109
+ DarkSlateGray
110
+ DarkSlateGray1
111
+ DarkSlateGray2
112
+ DarkSlateGray3
113
+ DarkSlateGray4
114
+ DarkSlateGrey
115
+ DarkTurquoise
116
+ DarkViolet
117
+ DeepPink
118
+ DeepPink1
119
+ DeepPink2
120
+ DeepPink3
121
+ DeepPink4
122
+ DeepSkyBlue
123
+ DeepSkyBlue1
124
+ DeepSkyBlue2
125
+ DeepSkyBlue3
126
+ DeepSkyBlue4
127
+ DimGray
128
+ DimGrey
129
+ DodgerBlue
130
+ DodgerBlue1
131
+ DodgerBlue2
132
+ DodgerBlue3
133
+ DodgerBlue4
134
+ firebrick
135
+ firebrick1
136
+ firebrick2
137
+ firebrick3
138
+ firebrick4
139
+ FloralWhite
140
+ ForestGreen
141
+ fractal
142
+ freeze
143
+ fuchsia
144
+ gainsboro
145
+ GhostWhite
146
+ gold
147
+ gold1
148
+ gold2
149
+ gold3
150
+ gold4
151
+ goldenrod
152
+ goldenrod1
153
+ goldenrod2
154
+ goldenrod3
155
+ goldenrod4
156
+ gray
157
+ gray
158
+ gray0
159
+ gray1
160
+ gray10
161
+ gray100
162
+ gray100
163
+ gray11
164
+ gray12
165
+ gray13
166
+ gray14
167
+ gray15
168
+ gray16
169
+ gray17
170
+ gray18
171
+ gray19
172
+ gray2
173
+ gray20
174
+ gray21
175
+ gray22
176
+ gray23
177
+ gray24
178
+ gray25
179
+ gray26
180
+ gray27
181
+ gray28
182
+ gray29
183
+ gray3
184
+ gray30
185
+ gray31
186
+ gray32
187
+ gray33
188
+ gray34
189
+ gray35
190
+ gray36
191
+ gray37
192
+ gray38
193
+ gray39
194
+ gray4
195
+ gray40
196
+ gray41
197
+ gray42
198
+ gray43
199
+ gray44
200
+ gray45
201
+ gray46
202
+ gray47
203
+ gray48
204
+ gray49
205
+ gray5
206
+ gray50
207
+ gray51
208
+ gray52
209
+ gray53
210
+ gray54
211
+ gray55
212
+ gray56
213
+ gray57
214
+ gray58
215
+ gray59
216
+ gray6
217
+ gray60
218
+ gray61
219
+ gray62
220
+ gray63
221
+ gray64
222
+ gray65
223
+ gray66
224
+ gray67
225
+ gray68
226
+ gray69
227
+ gray7
228
+ gray70
229
+ gray71
230
+ gray72
231
+ gray73
232
+ gray74
233
+ gray75
234
+ gray76
235
+ gray77
236
+ gray78
237
+ gray79
238
+ gray8
239
+ gray80
240
+ gray81
241
+ gray82
242
+ gray83
243
+ gray84
244
+ gray85
245
+ gray86
246
+ gray87
247
+ gray88
248
+ gray89
249
+ gray9
250
+ gray90
251
+ gray91
252
+ gray92
253
+ gray93
254
+ gray94
255
+ gray95
256
+ gray96
257
+ gray97
258
+ gray98
259
+ gray99
260
+ green
261
+ green
262
+ green1
263
+ green2
264
+ green3
265
+ green4
266
+ GreenYellow
267
+ grey
268
+ grey0
269
+ grey1
270
+ grey10
271
+ grey100
272
+ grey11
273
+ grey12
274
+ grey13
275
+ grey14
276
+ grey15
277
+ grey16
278
+ grey17
279
+ grey18
280
+ grey19
281
+ grey2
282
+ grey20
283
+ grey21
284
+ grey22
285
+ grey23
286
+ grey24
287
+ grey25
288
+ grey26
289
+ grey27
290
+ grey28
291
+ grey29
292
+ grey3
293
+ grey30
294
+ grey31
295
+ grey32
296
+ grey33
297
+ grey34
298
+ grey35
299
+ grey36
300
+ grey37
301
+ grey38
302
+ grey39
303
+ grey4
304
+ grey40
305
+ grey41
306
+ grey42
307
+ grey43
308
+ grey44
309
+ grey45
310
+ grey46
311
+ grey47
312
+ grey48
313
+ grey49
314
+ grey5
315
+ grey50
316
+ grey51
317
+ grey52
318
+ grey53
319
+ grey54
320
+ grey55
321
+ grey56
322
+ grey57
323
+ grey58
324
+ grey59
325
+ grey6
326
+ grey60
327
+ grey61
328
+ grey62
329
+ grey63
330
+ grey64
331
+ grey65
332
+ grey66
333
+ grey67
334
+ grey68
335
+ grey69
336
+ grey7
337
+ grey70
338
+ grey71
339
+ grey72
340
+ grey73
341
+ grey74
342
+ grey75
343
+ grey76
344
+ grey77
345
+ grey78
346
+ grey79
347
+ grey8
348
+ grey80
349
+ grey81
350
+ grey82
351
+ grey83
352
+ grey84
353
+ grey85
354
+ grey86
355
+ grey87
356
+ grey88
357
+ grey89
358
+ grey9
359
+ grey90
360
+ grey91
361
+ grey92
362
+ grey93
363
+ grey94
364
+ grey95
365
+ grey96
366
+ grey97
367
+ grey98
368
+ grey99
369
+ honeydew
370
+ honeydew1
371
+ honeydew2
372
+ honeydew3
373
+ honeydew4
374
+ HotPink
375
+ HotPink1
376
+ HotPink2
377
+ HotPink3
378
+ HotPink4
379
+ IndianRed
380
+ IndianRed1
381
+ IndianRed2
382
+ IndianRed3
383
+ IndianRed4
384
+ indigo
385
+ ivory
386
+ ivory1
387
+ ivory2
388
+ ivory3
389
+ ivory4
390
+ khaki
391
+ khaki1
392
+ khaki2
393
+ khaki3
394
+ khaki4
395
+ lavender
396
+ LavenderBlush
397
+ LavenderBlush1
398
+ LavenderBlush2
399
+ LavenderBlush3
400
+ LavenderBlush4
401
+ LawnGreen
402
+ LemonChiffon
403
+ LemonChiffon1
404
+ LemonChiffon2
405
+ LemonChiffon3
406
+ LemonChiffon4
407
+ LightBlue
408
+ LightBlue1
409
+ LightBlue2
410
+ LightBlue3
411
+ LightBlue4
412
+ LightCoral
413
+ LightCyan
414
+ LightCyan1
415
+ LightCyan2
416
+ LightCyan3
417
+ LightCyan4
418
+ LightGoldenrod
419
+ LightGoldenrod1
420
+ LightGoldenrod2
421
+ LightGoldenrod3
422
+ LightGoldenrod4
423
+ LightGoldenrodYellow
424
+ LightGray
425
+ LightGreen
426
+ LightGrey
427
+ LightPink
428
+ LightPink1
429
+ LightPink2
430
+ LightPink3
431
+ LightPink4
432
+ LightSalmon
433
+ LightSalmon1
434
+ LightSalmon2
435
+ LightSalmon3
436
+ LightSalmon4
437
+ LightSeaGreen
438
+ LightSkyBlue
439
+ LightSkyBlue1
440
+ LightSkyBlue2
441
+ LightSkyBlue3
442
+ LightSkyBlue4
443
+ LightSlateBlue
444
+ LightSlateGray
445
+ LightSlateGrey
446
+ LightSteelBlue
447
+ LightSteelBlue1
448
+ LightSteelBlue2
449
+ LightSteelBlue3
450
+ LightSteelBlue4
451
+ LightYellow
452
+ LightYellow1
453
+ LightYellow2
454
+ LightYellow3
455
+ LightYellow4
456
+ lime
457
+ LimeGreen
458
+ linen
459
+ magenta
460
+ magenta1
461
+ magenta2
462
+ magenta3
463
+ magenta4
464
+ maroon
465
+ maroon
466
+ maroon1
467
+ maroon2
468
+ maroon3
469
+ maroon4
470
+ matte
471
+ MediumAquamarine
472
+ MediumBlue
473
+ MediumForestGreen
474
+ MediumGoldenRod
475
+ MediumOrchid
476
+ MediumOrchid1
477
+ MediumOrchid2
478
+ MediumOrchid3
479
+ MediumOrchid4
480
+ MediumPurple
481
+ MediumPurple1
482
+ MediumPurple2
483
+ MediumPurple3
484
+ MediumPurple4
485
+ MediumSeaGreen
486
+ MediumSlateBlue
487
+ MediumSpringGreen
488
+ MediumTurquoise
489
+ MediumVioletRed
490
+ MidnightBlue
491
+ MintCream
492
+ MistyRose
493
+ MistyRose1
494
+ MistyRose2
495
+ MistyRose3
496
+ MistyRose4
497
+ moccasin
498
+ NavajoWhite
499
+ NavajoWhite1
500
+ NavajoWhite2
501
+ NavajoWhite3
502
+ NavajoWhite4
503
+ navy
504
+ NavyBlue
505
+ none
506
+ OldLace
507
+ olive
508
+ OliveDrab
509
+ OliveDrab1
510
+ OliveDrab2
511
+ OliveDrab3
512
+ OliveDrab4
513
+ opaque
514
+ orange
515
+ orange1
516
+ orange2
517
+ orange3
518
+ orange4
519
+ OrangeRed
520
+ OrangeRed1
521
+ OrangeRed2
522
+ OrangeRed3
523
+ OrangeRed4
524
+ orchid
525
+ orchid1
526
+ orchid2
527
+ orchid3
528
+ orchid4
529
+ PaleGoldenrod
530
+ PaleGreen
531
+ PaleGreen1
532
+ PaleGreen2
533
+ PaleGreen3
534
+ PaleGreen4
535
+ PaleTurquoise
536
+ PaleTurquoise1
537
+ PaleTurquoise2
538
+ PaleTurquoise3
539
+ PaleTurquoise4
540
+ PaleVioletRed
541
+ PaleVioletRed1
542
+ PaleVioletRed2
543
+ PaleVioletRed3
544
+ PaleVioletRed4
545
+ PapayaWhip
546
+ PeachPuff
547
+ PeachPuff1
548
+ PeachPuff2
549
+ PeachPuff3
550
+ PeachPuff4
551
+ peru
552
+ pink
553
+ pink1
554
+ pink2
555
+ pink3
556
+ pink4
557
+ plum
558
+ plum1
559
+ plum2
560
+ plum3
561
+ plum4
562
+ PowderBlue
563
+ purple
564
+ purple
565
+ purple1
566
+ purple2
567
+ purple3
568
+ purple4
569
+ red
570
+ red1
571
+ red2
572
+ red3
573
+ red4
574
+ RosyBrown
575
+ RosyBrown1
576
+ RosyBrown2
577
+ RosyBrown3
578
+ RosyBrown4
579
+ RoyalBlue
580
+ RoyalBlue1
581
+ RoyalBlue2
582
+ RoyalBlue3
583
+ RoyalBlue4
584
+ SaddleBrown
585
+ salmon
586
+ salmon1
587
+ salmon2
588
+ salmon3
589
+ salmon4
590
+ SandyBrown
591
+ SeaGreen
592
+ SeaGreen1
593
+ SeaGreen2
594
+ SeaGreen3
595
+ SeaGreen4
596
+ seashell
597
+ seashell1
598
+ seashell2
599
+ seashell3
600
+ seashell4
601
+ sienna
602
+ sienna1
603
+ sienna2
604
+ sienna3
605
+ sienna4
606
+ silver
607
+ SkyBlue
608
+ SkyBlue1
609
+ SkyBlue2
610
+ SkyBlue3
611
+ SkyBlue4
612
+ SlateBlue
613
+ SlateBlue1
614
+ SlateBlue2
615
+ SlateBlue3
616
+ SlateBlue4
617
+ SlateGray
618
+ SlateGray1
619
+ SlateGray2
620
+ SlateGray3
621
+ SlateGray4
622
+ SlateGrey
623
+ snow
624
+ snow1
625
+ snow2
626
+ snow3
627
+ snow4
628
+ SpringGreen
629
+ SpringGreen1
630
+ SpringGreen2
631
+ SpringGreen3
632
+ SpringGreen4
633
+ SteelBlue
634
+ SteelBlue1
635
+ SteelBlue2
636
+ SteelBlue3
637
+ SteelBlue4
638
+ tan
639
+ tan1
640
+ tan2
641
+ tan3
642
+ tan4
643
+ teal
644
+ thistle
645
+ thistle1
646
+ thistle2
647
+ thistle3
648
+ thistle4
649
+ tomato
650
+ tomato1
651
+ tomato2
652
+ tomato3
653
+ tomato4
654
+ transparent
655
+ turquoise
656
+ turquoise1
657
+ turquoise2
658
+ turquoise3
659
+ turquoise4
660
+ violet
661
+ VioletRed
662
+ VioletRed1
663
+ VioletRed2
664
+ VioletRed3
665
+ VioletRed4
666
+ wheat
667
+ wheat1
668
+ wheat2
669
+ wheat3
670
+ wheat4
671
+ white
672
+ WhiteSmoke
673
+ yellow
674
+ yellow1
675
+ yellow2
676
+ yellow3
677
+ yellow4
678
+ YellowGreen
static/fonts.txt ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Courier
2
+ Helvetica-Narrow-BoldOblique
3
+ AvantGarde-Book
4
+ AvantGarde-BookOblique
5
+ AvantGarde-Demi
6
+ AvantGarde-DemiOblique
7
+ Bookman-Demi
8
+ Bookman-DemiItalic
9
+ Bookman-Light
10
+ Bookman-LightItalic
11
+ Courier-Bold
12
+ Courier-BoldOblique
13
+ Courier-Oblique
14
+ fixed
15
+ Helvetica
16
+ Helvetica-Bold
17
+ Helvetica-BoldOblique
18
+ Helvetica-Narrow
19
+ Helvetica-Narrow-Bold
20
+ Helvetica-Narrow-Oblique
21
+ Helvetica-Oblique
22
+ NewCenturySchlbk-Bold
23
+ NewCenturySchlbk-BoldItalic
24
+ NewCenturySchlbk-Italic
25
+ NewCenturySchlbk-Roman
26
+ Palatino-Bold
27
+ Palatino-BoldItalic
28
+ Palatino-Italic
29
+ Palatino-Roman
30
+ Symbol
31
+ Times-Bold
32
+ Times-BoldItalic
33
+ Times-Italic
34
+ Times-Roman
35
+ C059-BdIta
36
+ C059-Bold
37
+ C059-Bold-Italic
38
+ C059-Italic
39
+ C059-Roman
40
+ Century-Schoolbook-L-Bold
41
+ Century-Schoolbook-L-Bold-Italic
42
+ Century-Schoolbook-L-Italic
43
+ Century-Schoolbook-L-Roman
44
+ D050000L
45
+ DejaVu-Sans
46
+ DejaVu-Sans-Bold
47
+ DejaVu-Sans-Mono
48
+ DejaVu-Sans-Mono-Bold
49
+ DejaVu-Serif
50
+ DejaVu-Serif-Bold
51
+ Dingbats
52
+ Droid-Sans-Fallback
53
+ Nimbus-Mono-L
54
+ Nimbus-Mono-L-Bold
55
+ Nimbus-Mono-L-Bold-Oblique
56
+ Nimbus-Mono-L-Regular-Oblique
57
+ Nimbus-Mono-PS
58
+ Nimbus-Mono-PS-Bold
59
+ Nimbus-Mono-PS-Bold-Italic
60
+ Nimbus-Mono-PS-Italic
61
+ Nimbus-Roman
62
+ Nimbus-Roman-Bold
63
+ Nimbus-Roman-Bold-Italic
64
+ Nimbus-Roman-Italic
65
+ Nimbus-Roman-No9-L
66
+ Nimbus-Roman-No9-L-Medium
67
+ Nimbus-Roman-No9-L-Medium-Italic
68
+ Nimbus-Roman-No9-L-Regular-Italic
69
+ Nimbus-Sans
70
+ Nimbus-Sans-Bold
71
+ Nimbus-Sans-Bold-Italic
72
+ Nimbus-Sans-Italic
73
+ Nimbus-Sans-L
74
+ Nimbus-Sans-L-Bold
75
+ Nimbus-Sans-L-Bold-Condensed
76
+ Nimbus-Sans-L-Bold-Condensed-Italic
77
+ Nimbus-Sans-L-Bold-Italic
78
+ Nimbus-Sans-L-Regular-Condensed
79
+ Nimbus-Sans-L-Regular-Condensed-Italic
80
+ Nimbus-Sans-L-Regular-Italic
81
+ Nimbus-Sans-Narrow
82
+ Nimbus-Sans-Narrow-Bold
83
+ Nimbus-Sans-Narrow-Bold-Oblique
84
+ Nimbus-Sans-Narrow-Oblique
85
+ NimbusMonoPS-Bold
86
+ NimbusMonoPS-BoldItalic
87
+ NimbusMonoPS-Italic
88
+ NimbusMonoPS-Regular
89
+ NimbusRoman-Bold
90
+ NimbusRoman-BoldItalic
91
+ NimbusRoman-Italic
92
+ NimbusRoman-Regular
93
+ NimbusSans-Bold
94
+ NimbusSans-BoldItalic
95
+ NimbusSans-Italic
96
+ NimbusSans-Regular
97
+ NimbusSansNarrow-Bold
98
+ NimbusSansNarrow-BoldOblique
99
+ NimbusSansNarrow-Oblique
100
+ NimbusSansNarrow-Regular
101
+ Noto-Mono
102
+ Noto-Sans-Mono-Bold
103
+ Noto-Sans-Mono-Regular
104
+ P052-Bold
105
+ P052-Bold-Italic
106
+ P052-BoldItalic
107
+ P052-Italic
108
+ P052-Roman
109
+ Standard-Symbols-L
110
+ Standard-Symbols-PS
111
+ URW-Bookman-Demi
112
+ URW-Bookman-Demi-Italic
113
+ URW-Bookman-L-Demi-Bold
114
+ URW-Bookman-L-Demi-Bold-Italic
115
+ URW-Bookman-L-Light
116
+ URW-Bookman-L-Light-Italic
117
+ URW-Bookman-Light
118
+ URW-Bookman-Light-Italic
119
+ URW-Chancery-L-Medium-Italic
120
+ URW-Gothic-Book
121
+ URW-Gothic-Book-Oblique
122
+ URW-Gothic-Demi
123
+ URW-Gothic-Demi-Oblique
124
+ URW-Gothic-L-Book
125
+ URW-Gothic-L-Book-Oblique
126
+ URW-Gothic-L-Demi
127
+ URW-Gothic-L-Demi-Oblique
128
+ URW-Palladio-L-Bold
129
+ URW-Palladio-L-Bold-Italic
130
+ URW-Palladio-L-Italic
131
+ URW-Palladio-L-Roman
132
+ URWBookman-Demi
133
+ URWBookman-DemiItalic
134
+ URWBookman-Light
135
+ URWBookman-LightItalic
136
+ URWGothic-Book
137
+ URWGothic-BookOblique
138
+ URWGothic-Demi
139
+ URWGothic-DemiOblique
140
+ Z003-Medium-Italic
141
+ Z003-MediumItalic
static/submit_video.html CHANGED
@@ -151,51 +151,104 @@
151
  </style>
152
  </head>
153
  <body>
154
- <form action="/process_video/" enctype="multipart/form-data" method="post">
155
- <div class="form-wrapper">
156
- <div class="form-group">
157
- <h3>Inputs & Task Selection</h3>
158
- <label for="video_file">Video File</label>
159
- <input type="file" id="video_file" name="video_file"><br>
160
- <label for="srt_file">Subtitles File</label>
161
- <input type="file" id="srt_file" name="srt_file"><br>
162
- <label for="task">Task</label>
163
- <select id="task" name="task">
164
- <option value="transcribe">Transcribe</option>
165
- <option value="translate">Translate</option>
166
- </select>
167
- <label for="model_version">Model Version</label>
168
- <select id="model_version" name="model_version">
169
- <option value="deepdml/faster-whisper-large-v3-turbo-ct2">faster-whisper-large-v3-turbo</option>
170
- <option value="large-v3">large-v3</option>
171
- </select>
172
- </div>
173
- <div class="form-group">
174
- <h3>Visual Parameters</h3>
175
- <label for="max_words_per_line">Max words per line</label>
176
- <input type="number" id="max_words_per_line" name="max_words_per_line" value="6"><br>
177
- <label for="fontsize">Font size</label>
178
- <input type="number" id="fontsize" name="fontsize" value="42"><br>
179
- <label for="font">Font:</label>
180
- <input type="text" id="font" name="font" value="FuturaPTHeavy"><br>
181
- <label for="bg_color">Background color</label>
182
- <input type="text" id="bg_color" name="bg_color" value="#00FFFF00"><br>
183
- <label for="text_color">Text color</label>
184
- <input type="text" id="text_color" name="text_color" value="white"><br>
185
- <label for="caption_mode">Caption mode</label>
186
- <select id="caption_mode" name="caption_mode">
187
- <option value="desktop">Desktop</option>
188
- <option value="mobile">Mobile</option>
189
- </select>
190
- </div>
191
  </div>
192
- <input type="submit" value="Submit">
193
- </form>
194
- <!-- Footer -->
195
- <div class="footer">
196
- <p>Created by:</p>
197
- <a href="https://github.com/marquesafonso" class="github"><i class="fab fa-github fa-3x"></i></a>
198
- <a href="https://www.linkedin.com/in/marquesafonso" class="linkedin"><i class="fab fa-linkedin fa-3x"></i></a>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
  </body>
201
  </html>
 
 
 
151
  </style>
152
  </head>
153
  <body>
154
+ <form id="video-form" action="/process_video/" method="post" enctype="multipart/form-data">
155
+ <div class="form-wrapper">
156
+ <div class="form-group">
157
+ <h3>Inputs & Task Selection</h3>
158
+ <label for="video_file">Video File</label>
159
+ <input type="file" id="video_file" name="video_file"><br>
160
+
161
+ <label for="task">Task</label>
162
+ <select id="task" name="task">
163
+ <option value="transcribe">Transcribe</option>
164
+ <option value="translate">Translate</option>
165
+ </select>
166
+
167
+ <label for="model_version">Model Version</label>
168
+ <select id="model_version" name="model_version">
169
+ <option value="deepdml/faster-whisper-large-v3-turbo-ct2">faster-whisper-large-v3-turbo</option>
170
+ <option value="turbo">turbo</option>
171
+ <option value="large-v3">large-v3</option>
172
+ </select>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
  </div>
174
+
175
+ <div class="form-group">
176
+ <h3>Visual Parameters</h3>
177
+ <label for="max_words_per_line">Max words per line</label>
178
+ <input type="number" id="max_words_per_line" name="max_words_per_line" value="6"><br>
179
+
180
+ <label for="fontsize">Font size</label>
181
+ <input type="number" id="fontsize" name="fontsize" value="42"><br>
182
+
183
+ <label for="font">Font</label>
184
+ <select id="font" name="font">
185
+ <option>Loading fonts...</option>
186
+ </select><br>
187
+
188
+ <label for="bg_color">Background color</label>
189
+ <input type="text" id="bg_color" name="bg_color" value="#00FFFF00"><br>
190
+
191
+ <label for="text_color">Text color</label>
192
+ <select id="text_color" name="text_color">
193
+ <option>Loading colors...</option>
194
+ </select><br>
195
+
196
+ <label for="caption_mode">Caption mode</label>
197
+ <select id="caption_mode" name="caption_mode">
198
+ <option value="desktop">Desktop</option>
199
+ <option value="mobile">Mobile</option>
200
+ </select>
201
+ </div>
202
+ </div>
203
+
204
+ <div id="loading" style="display:none; text-align: center; margin-top: 10px; font-weight: bold;">
205
+ <i class="fas fa-spinner fa-spin"></i> Processing, please wait...
206
  </div>
207
+
208
+ <input type="submit" value="Submit">
209
+ </form>
210
+ <div class="footer">
211
+ <p>Created by:</p>
212
+ <a href="https://github.com/marquesafonso" class="github"><i class="fab fa-github fa-3x"></i></a>
213
+ <a href="https://www.linkedin.com/in/marquesafonso" class="linkedin"><i class="fab fa-linkedin fa-3x"></i></a>
214
+ </div>
215
+ <script>
216
+ // Loading dropdown options
217
+ function populateDropdown(id, url, defaultValue = null) {
218
+ fetch(url)
219
+ .then(response => response.text())
220
+ .then(data => {
221
+ const select = document.getElementById(id);
222
+ select.innerHTML = '';
223
+ const lines = data.split('\n').map(x => x.trim()).filter(Boolean);
224
+
225
+ lines.forEach(item => {
226
+ const opt = document.createElement('option');
227
+ opt.value = item;
228
+ opt.textContent = item;
229
+ if (item === defaultValue) {
230
+ opt.selected = true;
231
+ }
232
+ select.appendChild(opt);
233
+ });
234
+ })
235
+ .catch(error => {
236
+ console.error(`Error loading ${url}:`, error);
237
+ });
238
+ }
239
+ // default font and color:
240
+ const DEFAULT_FONT = "Helvetica";
241
+ const DEFAULT_COLOR = "white";
242
+ // Init dropdowns
243
+ populateDropdown('font', '/static/fonts.txt', DEFAULT_FONT);
244
+ populateDropdown('text_color', '/static/colors.txt', DEFAULT_COLOR);
245
+
246
+ // Show loading spinner on submit
247
+ document.getElementById('video-form').addEventListener('submit', function () {
248
+ document.getElementById('loading').style.display = 'block';
249
+ });
250
+ </script>
251
  </body>
252
  </html>
253
+
254
+
utils/get_moviepy_configs.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ from moviepy.editor import TextClip
2
+
3
+ with open('static/fonts.txt', 'w', encoding='utf-8') as fonts:
4
+ fonts.write("\n".join(TextClip.list('font')))
5
+
6
+ with open('static/colors.txt', 'w', encoding='utf-8') as colors:
7
+ colors_list = [color.decode("utf-8") for color in TextClip.list('color')[3:]]
8
+ colors.write("\n".join(colors_list))
utils/process_video.py CHANGED
@@ -3,7 +3,6 @@ from utils.transcriber import transcriber
3
  from utils.subtitler import subtitler
4
 
5
  def process_video(invideo_file: str,
6
- srt_file: str | None,
7
  task: str,
8
  model_version: str,
9
  max_words_per_line:int,
@@ -17,12 +16,7 @@ def process_video(invideo_file: str,
17
  invideo_path_parts = os.path.normpath(invideo_file).split(os.path.sep)
18
  VIDEO_NAME = os.path.basename(invideo_file)
19
  OUTVIDEO_PATH = os.path.join(os.path.normpath('/'.join(invideo_path_parts[:-1])), f"result_{VIDEO_NAME}")
20
- if srt_file:
21
- logging.info("Subtitling...")
22
- subtitler(invideo_file, srt_file, OUTVIDEO_PATH, fontsize, font, bg_color, text_color, caption_mode)
23
- else:
24
- srt_file = os.path.normpath(f"{invideo_file.split('.')[0]}.srt")
25
- transcriber(invideo_file, srt_file, max_words_per_line, task, model_version, config_file)
26
- logging.info("Subtitling...")
27
- subtitler(invideo_file, srt_file, OUTVIDEO_PATH, fontsize, font, bg_color, text_color, caption_mode)
28
- return OUTVIDEO_PATH, srt_file
 
3
  from utils.subtitler import subtitler
4
 
5
  def process_video(invideo_file: str,
 
6
  task: str,
7
  model_version: str,
8
  max_words_per_line:int,
 
16
  invideo_path_parts = os.path.normpath(invideo_file).split(os.path.sep)
17
  VIDEO_NAME = os.path.basename(invideo_file)
18
  OUTVIDEO_PATH = os.path.join(os.path.normpath('/'.join(invideo_path_parts[:-1])), f"result_{VIDEO_NAME}")
19
+ srt_string = transcriber(invideo_file, max_words_per_line, task, model_version, config_file)
20
+ logging.info("Subtitling...")
21
+ subtitler(invideo_file, srt_string, OUTVIDEO_PATH, fontsize, font, bg_color, text_color, caption_mode)
22
+ return OUTVIDEO_PATH, srt_string
 
 
 
 
 
utils/subtitler.py CHANGED
@@ -1,10 +1,9 @@
1
  from moviepy.editor import VideoFileClip, CompositeVideoClip, TextClip
2
  import os
3
 
4
- def parse_srt(srt_file):
5
- """Parse the SRT file and return a list of (start, end, text) for each subtitle."""
6
- with open(srt_file, "r", encoding='utf-8') as file:
7
- lines = file.readlines()
8
  i = 0
9
  subtitles = []
10
  while i < len(lines):
@@ -29,7 +28,7 @@ def filter_caption_width(caption_mode:str):
29
  return caption_width_ratio, caption_height_ratio
30
 
31
  def subtitler(video_file:str,
32
- srt_path:str,
33
  output_file:str,
34
  fontsize:int,
35
  font: str,
@@ -37,12 +36,11 @@ def subtitler(video_file:str,
37
  text_color:str,
38
  caption_mode:str
39
  ):
40
- """Add subtitles from an SRT file to a video."""
41
  video_file = os.path.abspath(video_file)
42
- srt_path = os.path.abspath(srt_path)
43
  output_file = os.path.abspath(output_file)
44
  clip = VideoFileClip(filename=video_file, target_resolution=None)
45
- subtitles = parse_srt(srt_path)
46
  subtitle_clips = []
47
  caption_width_ratio, caption_height_ratio = filter_caption_width(caption_mode)
48
  for start, end, text in subtitles:
 
1
  from moviepy.editor import VideoFileClip, CompositeVideoClip, TextClip
2
  import os
3
 
4
+ def parse_srt(srt_string):
5
+ """Parse the SRT string and return a list of (start, end, text) for each subtitle."""
6
+ lines = srt_string.split("\n")
 
7
  i = 0
8
  subtitles = []
9
  while i < len(lines):
 
28
  return caption_width_ratio, caption_height_ratio
29
 
30
  def subtitler(video_file:str,
31
+ srt_string:str,
32
  output_file:str,
33
  fontsize:int,
34
  font: str,
 
36
  text_color:str,
37
  caption_mode:str
38
  ):
39
+ """Add subtitles from an SRT string to a video."""
40
  video_file = os.path.abspath(video_file)
 
41
  output_file = os.path.abspath(output_file)
42
  clip = VideoFileClip(filename=video_file, target_resolution=None)
43
+ subtitles = parse_srt(srt_string)
44
  subtitle_clips = []
45
  caption_width_ratio, caption_height_ratio = filter_caption_width(caption_mode)
46
  for start, end, text in subtitles:
utils/transcriber.py CHANGED
@@ -1,19 +1,21 @@
1
  from gradio_client import Client, handle_file
2
  from utils.api_configs import api_configs
3
 
4
- def transcriber(invideo_file:str, srt_file:str,
5
- max_words_per_line:int, task:str, model_version:str,
6
- config_file:str):
 
 
 
7
  HF_TOKEN = api_configs(config_file)["secrets"]["hf-token"]
8
  HF_SPACE = api_configs(config_file)["secrets"]["hf-space"]
9
  client = Client(HF_SPACE, hf_token=HF_TOKEN)
10
  result = client.predict(
11
- video_input=handle_file(invideo_file),
 
12
  max_words_per_line=max_words_per_line,
13
  task=task,
14
  model_version=model_version,
15
  api_name="/predict"
16
  )
17
- with open(srt_file, "w", encoding='utf-8') as file:
18
- file.write(result[0])
19
- return srt_file
 
1
  from gradio_client import Client, handle_file
2
  from utils.api_configs import api_configs
3
 
4
+ def transcriber(invideo_file:str,
5
+ max_words_per_line:int,
6
+ task:str,
7
+ model_version:str,
8
+ config_file:str
9
+ ):
10
  HF_TOKEN = api_configs(config_file)["secrets"]["hf-token"]
11
  HF_SPACE = api_configs(config_file)["secrets"]["hf-space"]
12
  client = Client(HF_SPACE, hf_token=HF_TOKEN)
13
  result = client.predict(
14
+ file_input=handle_file(invideo_file),
15
+ file_type = "video",
16
  max_words_per_line=max_words_per_line,
17
  task=task,
18
  model_version=model_version,
19
  api_name="/predict"
20
  )
21
+ return result[0]