marquesafonso commited on
Commit
7f3ee84
·
1 Parent(s): 964950d

fix caching and temporary drectory cleanup; add link for new transcription after one is finished

Browse files
Files changed (3) hide show
  1. main.py +13 -9
  2. requirements.txt +0 -0
  3. static/process_settings.html +4 -0
main.py CHANGED
@@ -14,21 +14,22 @@ from fastapi.templating import Jinja2Templates
14
  from fastapi.responses import HTMLResponse, Response, RedirectResponse
15
  from fastapi.security import HTTPBasic
16
  from pydantic import BaseModel, field_validator
17
-
18
 
19
  ## THIS IS A BREAKING CHANGE. SRT FILE INPUT DEPRECATED. WIP.
20
  ## DONE: separate transcriber from subtitler logic. WIP.
21
  ## DONE: improve loading spinner. WIP (with redirect)
22
- ## TODO: fix tempdir cleanup
23
- ## TODO: add transcription preview component + allow for interactive validation of transcription in-browser. WIP
24
  ## TODO: add word level highlighting option
 
25
 
26
  app = FastAPI()
27
  security = HTTPBasic()
28
  static_dir = os.path.join(os.path.dirname(__file__), 'static')
29
  app.mount("/static", StaticFiles(directory=static_dir), name="static")
30
  templates = Jinja2Templates(directory=static_dir)
31
- temp_store = {}
32
 
33
  class MP4Video(BaseModel):
34
  video_file: UploadFile
@@ -81,7 +82,7 @@ async def transcribe_api(video_file: MP4Video = Depends(),
81
  transcription = transcriber(video_path, max_words_per_line, task, model_version)
82
 
83
  uid = str(uuid4())
84
- temp_store[uid] = {"video_path": video_path, "transcription": transcription}
85
  return RedirectResponse(url=f"/process_settings/?uid={uid}", status_code=303)
86
 
87
  except Exception as e:
@@ -89,17 +90,19 @@ async def transcribe_api(video_file: MP4Video = Depends(),
89
 
90
  @app.get("/process_settings/")
91
  async def process_settings(request: Request, uid: str):
92
- data = temp_store.get(uid)
93
  if not data:
94
  raise HTTPException(404, "Data not found")
95
  return templates.TemplateResponse("process_settings.html", {
96
  "request": request,
97
  "transcription": data["transcription"],
98
- "video_path": data["video_path"]
 
99
  })
100
 
101
  @app.post("/process_video/")
102
  async def process_video_api(video_path: str = Form(...),
 
103
  srt_string: str = Form(...),
104
  fontsize: Optional[int] = Form(42),
105
  font: Optional[str] = Form("Helvetica"),
@@ -116,8 +119,6 @@ async def process_video_api(video_path: str = Form(...),
116
  logging.info("Zipping response...")
117
  with open(os.path.join(temp_dir.name, f"{video_path.split('.')[0]}.zip"), 'w+b') as temp_zip_file:
118
  zip_file = zip_response(temp_zip_file.name, [output_path, temp_srt_file.name])
119
- temp_dir.cleanup()
120
- temp_store = {}
121
  return Response(
122
  content = zip_file,
123
  media_type="application/zip",
@@ -125,6 +126,9 @@ async def process_video_api(video_path: str = Form(...),
125
  )
126
  except Exception as e:
127
  raise HTTPException(status_code=500, detail=str(e))
 
 
 
128
 
129
  if __name__ == "__main__":
130
  uvicorn.run(app, host="0.0.0.0", port=8000)
 
14
  from fastapi.responses import HTMLResponse, Response, RedirectResponse
15
  from fastapi.security import HTTPBasic
16
  from pydantic import BaseModel, field_validator
17
+ from cachetools import TTLCache
18
 
19
  ## THIS IS A BREAKING CHANGE. SRT FILE INPUT DEPRECATED. WIP.
20
  ## DONE: separate transcriber from subtitler logic. WIP.
21
  ## DONE: improve loading spinner. WIP (with redirect)
22
+ ## DONE: fix tempdir cleanup
23
+ ## DONE: add transcription preview component + allow for interactive validation of transcription in-browser.
24
  ## TODO: add word level highlighting option
25
+ ## TODO: improve UI
26
 
27
  app = FastAPI()
28
  security = HTTPBasic()
29
  static_dir = os.path.join(os.path.dirname(__file__), 'static')
30
  app.mount("/static", StaticFiles(directory=static_dir), name="static")
31
  templates = Jinja2Templates(directory=static_dir)
32
+ cache = TTLCache(maxsize=1024, ttl=600)
33
 
34
  class MP4Video(BaseModel):
35
  video_file: UploadFile
 
82
  transcription = transcriber(video_path, max_words_per_line, task, model_version)
83
 
84
  uid = str(uuid4())
85
+ cache[uid] = {"video_path": video_path, "transcription": transcription, "temp_dir_path": temp_dir.name}
86
  return RedirectResponse(url=f"/process_settings/?uid={uid}", status_code=303)
87
 
88
  except Exception as e:
 
90
 
91
  @app.get("/process_settings/")
92
  async def process_settings(request: Request, uid: str):
93
+ data = cache.get(uid)
94
  if not data:
95
  raise HTTPException(404, "Data not found")
96
  return templates.TemplateResponse("process_settings.html", {
97
  "request": request,
98
  "transcription": data["transcription"],
99
+ "video_path": data["video_path"],
100
+ "temp_dir_path": data["temp_dir_path"]
101
  })
102
 
103
  @app.post("/process_video/")
104
  async def process_video_api(video_path: str = Form(...),
105
+ temp_dir_path: str = Form(...),
106
  srt_string: str = Form(...),
107
  fontsize: Optional[int] = Form(42),
108
  font: Optional[str] = Form("Helvetica"),
 
119
  logging.info("Zipping response...")
120
  with open(os.path.join(temp_dir.name, f"{video_path.split('.')[0]}.zip"), 'w+b') as temp_zip_file:
121
  zip_file = zip_response(temp_zip_file.name, [output_path, temp_srt_file.name])
 
 
122
  return Response(
123
  content = zip_file,
124
  media_type="application/zip",
 
126
  )
127
  except Exception as e:
128
  raise HTTPException(status_code=500, detail=str(e))
129
+ finally:
130
+ if temp_dir_path and os.path.exists(temp_dir_path):
131
+ shutil.rmtree(temp_dir_path, ignore_errors=True)
132
 
133
  if __name__ == "__main__":
134
  uvicorn.run(app, host="0.0.0.0", port=8000)
requirements.txt CHANGED
Binary files a/requirements.txt and b/requirements.txt differ
 
static/process_settings.html CHANGED
@@ -40,8 +40,12 @@
40
  </select>
41
 
42
  <input type="hidden" name="video_path" value="{{ video_path }}">
 
43
  <input type="submit" value="Render & Download">
44
  </form>
 
 
 
45
  <script>
46
  // Load dropdown options with optional default
47
  function populateDropdown(id, url, defaultValue = null) {
 
40
  </select>
41
 
42
  <input type="hidden" name="video_path" value="{{ video_path }}">
43
+ <input type="hidden" name="temp_dir_path" value="{{ temp_dir_path }}">
44
  <input type="submit" value="Render & Download">
45
  </form>
46
+ <div style="text-align: center; margin-top: 2em;">
47
+ <a href="/transcribe_video">Transcribe Another Video</a>
48
+ </div>
49
  <script>
50
  // Load dropdown options with optional default
51
  function populateDropdown(id, url, defaultValue = null) {