Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(videos): backend features for reviewing video #115

Merged
merged 24 commits into from
Nov 24, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
46a0630
feat(back-end): implemented 2 methods of signalling next.js that vid …
MyStackOverflows Nov 13, 2023
d89380b
feat(back-end): fix processes being tracked regardless of is_stateless
MyStackOverflows Nov 14, 2023
412487c
feat(back-end): fix broken filepath in test
MyStackOverflows Nov 14, 2023
9fa577b
Merge branch 'develop' into gh-77-video-review-backend
MyStackOverflows Nov 21, 2023
bc8e500
feat(back-end): modified response flow with quart run_sync()
MyStackOverflows Nov 21, 2023
58ad2a9
feat(videos): implement review comments
MyStackOverflows Nov 22, 2023
bd9f084
feat(videos): fix infinitely running tests due to running tracker.mai…
MyStackOverflows Nov 22, 2023
cf83a40
Merge branch 'develop' into gh-77-video-review-backend
MyStackOverflows Nov 22, 2023
cd8c005
Merge branch 'develop' into gh-77-video-review-backend
MyStackOverflows Nov 22, 2023
adcdc85
feat(videos): simplified logic
MyStackOverflows Nov 22, 2023
5f4295e
feat(videos): implement review comments
MyStackOverflows Nov 22, 2023
93077df
feat(videos): implement review comments
MyStackOverflows Nov 22, 2023
2a60120
feat(videos): implement review comments
MyStackOverflows Nov 22, 2023
a51f0dc
feat(videos): fix bug in prune()
MyStackOverflows Nov 22, 2023
41b048a
feat(videos): simplify /process_status
MyStackOverflows Nov 23, 2023
b00d924
feat(videos): fix process_tracker again
MyStackOverflows Nov 23, 2023
c7d860c
feat(videos): add environment variable config for process tracking
MyStackOverflows Nov 23, 2023
6f5094a
feat(videos): fix env variable name in process_tracker.py
MyStackOverflows Nov 23, 2023
d45f461
fix(videos): add failsafe for undefined env variable
MyStackOverflows Nov 23, 2023
acff84a
feat(videos): implement review comments
MyStackOverflows Nov 23, 2023
a8f9771
feat(videos): fix pruner process hanging on server shutdown
MyStackOverflows Nov 23, 2023
587bb24
feat(videos): set uvicorn lifespan explicitly on
MyStackOverflows Nov 23, 2023
5384447
Merge branch 'develop' into gh-77-video-review-backend
MyStackOverflows Nov 24, 2023
42d780e
feat(videos): add Thuan's code for terminating processes
MyStackOverflows Nov 24, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/video-processing/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ run: setup-run ## Run the video processing server as a standalone container.
-e AWS_DEFAULT_REGION="ca-central-1" \
-e PRIVACYPAL_INPUT_VIDEO_DIR="$(PRIVACYPAL_INPUT_VIDEO_DIR)" \
-e PRIVACYPAL_OUTPUT_VIDEO_DIR="$(PRIVACYPAL_OUTPUT_VIDEO_DIR)" \
-e VIDPROC_IS_STATELESS="true" \
MyStackOverflows marked this conversation as resolved.
Show resolved Hide resolved
-v "$(LOCAL_INPUT_DIR)":"$(PRIVACYPAL_INPUT_VIDEO_DIR)":z \
-v "$(LOCAL_OUTPUT_DIR)":"$(PRIVACYPAL_OUTPUT_VIDEO_DIR)":z \
-it --rm $(VID_PROCESS_IMAGE) 2>&1 | tee $(LOG_FILE)
Expand Down
1 change: 1 addition & 0 deletions app/video-processing/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ opencv-python-headless==4.8.1.78
flask==3.0.0
quart==0.19.3
uvicorn==0.24.0.post1
requests==2.22.0
35 changes: 32 additions & 3 deletions app/video-processing/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@

app = Quart(__name__)
vp = VideoProcessor()
processes = {} # key:value is of the form str:mp.Process
is_stateless = False
try:
is_stateless = True if str(os.environ["VIDPROC_IS_STATELESS"]) == "true" else False # if env variable not defined, will raise KeyError
except:pass

@app.route("/process_video", methods=["POST"])
async def handle_request():
Expand All @@ -14,12 +19,36 @@ async def handle_request():
final = f"{out_path}/{file[:-4]}-processed{file[-4:]}"
if not app.testing: # if we're running Flask unit tests, don't run the video processing method
process = mp.Process(target=vp.process_INTERPOLATE, args=(f"{input_path}/{file}", final)) # define a new process pointing to process_INTERPOLATE
if is_stateless:
processes[file] = process
process.start() # start the process on another thread
tthvo marked this conversation as resolved.
Show resolved Hide resolved
print(f"Process started on {file}")
return "Success: file exists"
return "Success: file exists", 200
else:
return "Error: file not found"
return "Error: request must be of type POST"
return "Error: file not found", 200
MyStackOverflows marked this conversation as resolved.
Show resolved Hide resolved
return "Error: request must be of type POST", 405

@app.route("/check_finished", methods=["POST"])
MyStackOverflows marked this conversation as resolved.
Show resolved Hide resolved
async def return_status():
if is_stateless: # only enable this route if we're running in stateless mode
MyStackOverflows marked this conversation as resolved.
Show resolved Hide resolved
if request.method == "POST":
file = (await request.data).decode()
process: mp.Process
try:
process = processes[file]
except KeyError:
return "Invalid filename", 200 # shouldn't ever happen, but just in case
MyStackOverflows marked this conversation as resolved.
Show resolved Hide resolved

if process.is_alive():
return "false", 200 # return false to the request for "is the video finished processing"
else:
processes.pop(file) # remove the process from the dictionary
tthvo marked this conversation as resolved.
Show resolved Hide resolved
return "true", 200 # return true
else:
return "Error: request must be of type POST", 405
else:
print("Not running in stateless mode, returning 404")
return "", 404
MyStackOverflows marked this conversation as resolved.
Show resolved Hide resolved

@app.route("/health", methods=["GET"])
async def return_health():
Expand Down
11 changes: 9 additions & 2 deletions app/video-processing/video_processor.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import cv2 as cv, os, time, multiprocessing as mp, numpy as np, subprocess as sp, random, boto3
import cv2 as cv, os, time, multiprocessing as mp, numpy as np, subprocess as sp, random, boto3, requests

class VideoProcessor:
client: boto3.client
is_stateless: bool
def __init__(self):
self.client = boto3.client("rekognition") # request a client of the type 'rekognition' from aws services
self.is_stateless = False
try:
self.is_stateless = True if str(os.environ["VIDPROC_IS_STATELESS"]) == "true" else False # if env variable not defined, will raise KeyError
except:pass

def blur_frame(self, img, rects: list, r: int = 50):
def blur_frame(self, img, rects: list, r: int = 25):
"""
Loads an image and applies a blur on all regions specified by `rects`.
`img` is an opencv image (ie essentially an np array).
Expand Down Expand Up @@ -165,6 +170,8 @@ def process_INTERPOLATE(self, src: str, out: str, keyframe_interval: float = 0.5
p.wait()
os.remove(tmp)
print(f"Done processing {src}.")
if not self.is_stateless:
requests.post("http://localhost:8080/some/nextjs/api/route", out) # post to a next.js api route with the output filename to signify processing completion

tthvo marked this conversation as resolved.
Show resolved Hide resolved
MyStackOverflows marked this conversation as resolved.
Show resolved Hide resolved
def img_to_bytes(self, img) -> bytes:
"""
Expand Down
Loading