Spaces:
Sleeping
Sleeping
ngxquang
commited on
Commit
·
4c7b93d
1
Parent(s):
25b822d
feat: metadata service
Browse files- .env +6 -0
- Dockerfile +33 -0
- policy.json +13 -0
- requirements.txt +6 -0
- src/__init__.py +0 -0
- src/__pycache__/config.cpython-311.pyc +0 -0
- src/__pycache__/main.cpython-311.pyc +0 -0
- src/config.py +21 -0
- src/itr/__init__.py +0 -0
- src/itr/__pycache__/__init__.cpython-311.pyc +0 -0
- src/itr/__pycache__/router.cpython-311.pyc +0 -0
- src/itr/router.py +115 -0
- src/itr/router/README.md +6 -0
- src/main.py +63 -0
.env
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# PROJECT INFORMATION
|
2 |
+
HOST=0.0.0.0
|
3 |
+
PORT=7860
|
4 |
+
CORS_HEADERS=["*"]
|
5 |
+
CORS_ORIGINS=["*"]
|
6 |
+
POLICY_FILE_PATH="./policy.json"
|
Dockerfile
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
FROM python:3.8-slim
|
2 |
+
|
3 |
+
RUN apt-get update && \
|
4 |
+
apt-get install git bash wget iputils-ping -y && \
|
5 |
+
apt clean && \
|
6 |
+
rm -rf /var/cache/apt/*
|
7 |
+
|
8 |
+
WORKDIR /code
|
9 |
+
|
10 |
+
COPY requirements.txt /code/requirements.txt
|
11 |
+
|
12 |
+
# PYTHONDONTWRITEBYTECODE=1: Disables the creation of .pyc files (compiled bytecode)
|
13 |
+
# PYTHONUNBUFFERED=1: Disables buffering of the standard output stream
|
14 |
+
# PYTHONIOENCODING: specifies the encoding to be used for the standard input, output, and error streams
|
15 |
+
ENV PYTHONDONTWRITEBYTECODE=1 \
|
16 |
+
PYTHONUNBUFFERED=1 \
|
17 |
+
PYTHONIOENCODING=utf-8
|
18 |
+
|
19 |
+
RUN pip install -U pip && \
|
20 |
+
python -m pip install -r /code/requirements.txt
|
21 |
+
|
22 |
+
RUN useradd -m -u 1000 user
|
23 |
+
|
24 |
+
USER user
|
25 |
+
|
26 |
+
ENV HOME=/home/user \
|
27 |
+
PATH=/home/user/.local/bin:$PATH
|
28 |
+
|
29 |
+
WORKDIR $HOME/app
|
30 |
+
|
31 |
+
COPY --chown=user . $HOME/app
|
32 |
+
|
33 |
+
CMD python ./src/main.py
|
policy.json
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"type": "service_account",
|
3 |
+
"project_id": "vinid-playground",
|
4 |
+
"private_key_id": "5546404edff790939b5175043e6b50edd10332ab",
|
5 |
+
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDOBfBeBGUTEliR\nIeLJ5lye2zJ3OCOjmZrvLI6afHVse215ND2MP5OvfLHhjdDhglbLYbNeBUQCHUYl\n2nCjBrMgyOv05dWr/nVWqIvMnAMrm65HC5x1eTT2SPaRq+IXFgjA6sNwnmO9bfIV\n3GYcGXxQvBZyWG1EleG02Ptu0KQ8i0SFgFsplmVfM26iIwQV7HaPuyzXIpWnyGs9\nbKE7Rw2RTnVFhW0rt3mFsPynri6VXB8X9snFcFr/VEBD2+Nr15/aqh/omKvrC5RL\nT1SXH64XezWiVT2dxMw+Ls5ZugiwxK1FhTU2VmRa+QGeT7iclmBp03ZhfaUj/gg2\nE4dJucjjAgMBAAECggEAQ75NLsT4LUC7kaFYTrYqH2wJGI2DnoBcIyf+Dgs9mzms\nog2M7WhcWfhBD18P3475li+eiJxno+BXWAwPPHPwA6g9eg325/KoR6HtMg7ctgKf\nWCoXvMLpqNAOD5E6qweqQjEPqaDTQA7+arTJeJTivTNTmC6+Yy57hHlSl7oQPv2f\nL0Datre9kpEvgqVYi207EO4CF3+JMIaqNR4sSd6CpQnaLuCEyrvds+X3MMCSYR+N\nJoDjs/FeR2q/hDtPaulxmv1M7rR89k9JHMouszjxX4kBtVhKQeMo7JXd8FQgPvyK\nqpVteMhQrYGjE5HSaF3QU01yhv3xWbcoWltUYSNR1QKBgQDqTGjTAQcwo/Ig5Nbj\nta3ZcHeQLyhZ7PICtV6SHGbB8rI1GYPojdQCqF6bj3RPTsr6O/XIKrpc13tkLloR\n+YaGnHtj91CgOf8Iy5Uw5rkG4zfb/vmUxElrzPUESX1QO+GSx9nEJxnoEgvtjobi\nmRtajGiJAKgBzPwT3v+hg3BOdQKBgQDhGxPciFnvLbTO8DWPESunafZaP7z5StOG\nVYa+y8fSvOQ9ExR/6lUBLQaxcJ0BjtTg3Bk26QO+CDAFdH4iObG3JEk9D+VrRYL9\n3PqJ+s6tCxJovSeYjHAHKfrsCvMyVxh1gVJR7SyJna1zOhVIGnD1ZfuNRdajR1IL\ny9ou+67+9wKBgQCsPEleu8W+UvbeiXsS3+6SBqROIOyH1rA9n3iK7kf30WKBuGUI\noqI05fLOZlF5L5H1C/jtEcP4FgvGJHDf/8+NyyDF5vulHZ1GqOneje18i7H3jmOI\nohbbIUsIwMFXJv32+eUy1g+sUv/jvT+Y+jZqhQcfl5Tp5fd04ByJbec0NQKBgQDM\nMBqhBVHGwgfrWjrK7oFRl61uCbjpzHT4umXCdehpAQxrVf5XVYEL0wLqO0M/4Ya5\n/QwmIdFSM+0TVasAcqMAhDqm1997oY8DpcnhFQ8aKhvlxAbBukn4RZ0lNX2KYTR/\nifHY/LFUlyF5jus0/z8Nahd2+y2J6CzFJIFh8sy22wKBgH/flv5SiFZPM21fh3VC\nSC7KOlJBNVrEloGdc91vGH2cDGuMZhJh+YHiOBXzf0751qqqJhGzbpi2tNQn3M+Q\n2Iglw6JU6+i8XMDw5HJszjfp2KYPXKHmoPFVsqQ0U5AkEyglbveLX94CRZt1ON/a\nXgoIt1blT7sM2raf6+Gl+SdM\n-----END PRIVATE KEY-----\n",
|
6 |
+
"client_email": "[email protected]",
|
7 |
+
"client_id": "103848892899493800751",
|
8 |
+
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
9 |
+
"token_uri": "https://oauth2.googleapis.com/token",
|
10 |
+
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
|
11 |
+
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/iac-demo%40vinid-playground.iam.gserviceaccount.com",
|
12 |
+
"universe_domain": "googleapis.com"
|
13 |
+
}
|
requirements.txt
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
fastapi==0.103.1
|
2 |
+
uvicorn==0.23.2
|
3 |
+
pydantic-settings==2.0.3
|
4 |
+
firebase_admin
|
5 |
+
# Project settings, for development only
|
6 |
+
# pre-commit
|
src/__init__.py
ADDED
File without changes
|
src/__pycache__/config.cpython-311.pyc
ADDED
Binary file (1.13 kB). View file
|
|
src/__pycache__/main.cpython-311.pyc
ADDED
Binary file (3.09 kB). View file
|
|
src/config.py
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from pathlib import Path
|
2 |
+
|
3 |
+
from pydantic_settings import BaseSettings
|
4 |
+
|
5 |
+
FILE = Path(__file__)
|
6 |
+
ROOT = FILE.parent.parent
|
7 |
+
|
8 |
+
|
9 |
+
class Settings(BaseSettings):
|
10 |
+
# API SETTINGS
|
11 |
+
HOST: str
|
12 |
+
PORT: int
|
13 |
+
CORS_ORIGINS: list
|
14 |
+
CORS_HEADERS: list
|
15 |
+
POLICY_FILE_PATH: str
|
16 |
+
|
17 |
+
class Config:
|
18 |
+
env_file = ROOT / ".env"
|
19 |
+
|
20 |
+
|
21 |
+
settings = Settings()
|
src/itr/__init__.py
ADDED
File without changes
|
src/itr/__pycache__/__init__.cpython-311.pyc
ADDED
Binary file (200 Bytes). View file
|
|
src/itr/__pycache__/router.cpython-311.pyc
ADDED
Binary file (4.44 kB). View file
|
|
src/itr/router.py
ADDED
@@ -0,0 +1,115 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from fastapi import APIRouter, status, Response, Path
|
2 |
+
from fastapi.responses import JSONResponse, StreamingResponse
|
3 |
+
from pydantic import BaseModel
|
4 |
+
|
5 |
+
# from google.cloud import storage
|
6 |
+
from config import settings
|
7 |
+
import datetime
|
8 |
+
import firebase_admin
|
9 |
+
from firebase_admin import credentials
|
10 |
+
from firebase_admin import storage
|
11 |
+
|
12 |
+
from google.cloud import storage
|
13 |
+
from pathlib import Path
|
14 |
+
|
15 |
+
import numpy as np
|
16 |
+
import csv
|
17 |
+
import json
|
18 |
+
import os
|
19 |
+
|
20 |
+
# cred = credentials.Certificate(settings.POLICY_FILE_PATH)
|
21 |
+
# app = firebase_admin.initialize_app(cred, {'storageBucket': 'cnc-designs.appspot.com'}, name='storage')
|
22 |
+
# bucket = storage.bucket(app=app)
|
23 |
+
|
24 |
+
CWD = Path(__file__).parent
|
25 |
+
|
26 |
+
# client = storage.Client()
|
27 |
+
client = storage.Client.from_service_account_json(
|
28 |
+
os.path.join(CWD.parent.parent, settings.POLICY_FILE_PATH)
|
29 |
+
)
|
30 |
+
bucket = client.bucket("thangtd1")
|
31 |
+
|
32 |
+
router = APIRouter()
|
33 |
+
|
34 |
+
|
35 |
+
@router.get("/{video}/metadata")
|
36 |
+
async def get_length(video: str) -> JSONResponse:
|
37 |
+
print(video)
|
38 |
+
try:
|
39 |
+
path_file = "metadata/" + video + ".json"
|
40 |
+
blob = bucket.blob(path_file)
|
41 |
+
|
42 |
+
metadata = {}
|
43 |
+
|
44 |
+
with blob.open("r") as f:
|
45 |
+
metadata = json.load(f)
|
46 |
+
|
47 |
+
except Exception:
|
48 |
+
return JSONResponse(
|
49 |
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
50 |
+
content={"message": "err"},
|
51 |
+
)
|
52 |
+
|
53 |
+
return JSONResponse(status_code=status.HTTP_200_OK, content=metadata)
|
54 |
+
|
55 |
+
|
56 |
+
@router.get("/{video}/keyframes/list")
|
57 |
+
async def get_list_keyframes(video: str) -> JSONResponse:
|
58 |
+
path_file = "Keyframes/" + video
|
59 |
+
list_keyframes = []
|
60 |
+
meta_data = []
|
61 |
+
|
62 |
+
path_meta_file = "map-keyframes/" + video + ".csv"
|
63 |
+
|
64 |
+
blob = bucket.blob(path_meta_file)
|
65 |
+
with blob.open("r") as f:
|
66 |
+
reader = csv.reader(f)
|
67 |
+
meta_data = list(reader)
|
68 |
+
# print(meta_data[0])
|
69 |
+
meta_data = np.array(meta_data[1:])
|
70 |
+
|
71 |
+
for blob in client.list_blobs("thangtd1", prefix=path_file):
|
72 |
+
list_keyframes.append([str(blob.name)])
|
73 |
+
|
74 |
+
list_keyframes = np.array(list_keyframes)
|
75 |
+
|
76 |
+
list_keyframes = np.append(list_keyframes, meta_data, axis=1)
|
77 |
+
|
78 |
+
return JSONResponse(
|
79 |
+
status_code=status.HTTP_200_OK,
|
80 |
+
content={"list_keyframes": list_keyframes.tolist()},
|
81 |
+
)
|
82 |
+
|
83 |
+
|
84 |
+
@router.get("/stream_video/{bucket_name}/{video_blob_name}")
|
85 |
+
async def stream_video(
|
86 |
+
bucket_name: str,
|
87 |
+
video_blob_name: str,
|
88 |
+
response: Response = None,
|
89 |
+
) -> JSONResponse:
|
90 |
+
path_file = "Video/" + video_blob_name
|
91 |
+
|
92 |
+
# blob = bucket.blob(path_file)
|
93 |
+
|
94 |
+
# url = blob.generate_signed_url(
|
95 |
+
# This URL is valid for 15 minutes
|
96 |
+
# expiration=datetime.timedelta(minutes=15),
|
97 |
+
# Allow GET requests using this URL.
|
98 |
+
# method='GET'
|
99 |
+
# )
|
100 |
+
|
101 |
+
# print(url)
|
102 |
+
|
103 |
+
# return JSONResponse(status_code=status.HTTP_200_OK, content = {"url" : url})
|
104 |
+
|
105 |
+
# if not blob.exists():
|
106 |
+
# return StreamingResponse(
|
107 |
+
# content_generator([b"Video not found"]), media_type="text/plain"
|
108 |
+
# )
|
109 |
+
|
110 |
+
# # Stream the video in chunks
|
111 |
+
# def content_generator():
|
112 |
+
# for chunk in blob.download_as_bytes(start=0, end=blob.size, raw_download=True):
|
113 |
+
# yield chunk
|
114 |
+
|
115 |
+
# return StreamingResponse(content_generator(), media_type="video/mp4")
|
src/itr/router/README.md
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# BEiT-3 Weight and Sentencepiece models
|
2 |
+
|
3 |
+
1. Please download [beit3_base_patch16_384_retrieval.pth](https://conversationhub.blob.core.windows.net/beit-share-public/beit3/f30k_retrieval/beit3_base_patch16_384_f30k_retrieval.pth?sv=2021-10-04&st=2023-06-08T11%3A16%3A02Z&se=2033-06-09T11%3A16%3A00Z&sr=c&sp=r&sig=N4pfCVmSeq4L4tS8QbrFVsX6f6q844eft8xSuXdxU48%3D) and [beit3.spm](https://conversationhub.blob.core.windows.net/beit-share-public/beit3/sentencepiece/beit3.spm?sv=2021-10-04&st=2023-06-08T11%3A16%3A02Z&se=2033-06-09T11%3A16%3A00Z&sr=c&sp=r&sig=N4pfCVmSeq4L4tS8QbrFVsX6f6q844eft8xSuXdxU48%3D) model.
|
4 |
+
|
5 |
+
2. Put those 2 model inside this folder
|
6 |
+
|
src/main.py
ADDED
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
from pathlib import Path
|
3 |
+
|
4 |
+
from config import settings
|
5 |
+
from fastapi import FastAPI, Request, status
|
6 |
+
from fastapi.exceptions import RequestValidationError
|
7 |
+
from fastapi.middleware.cors import CORSMiddleware
|
8 |
+
from fastapi.responses import JSONResponse, RedirectResponse
|
9 |
+
from itr.router import router as router
|
10 |
+
|
11 |
+
import os
|
12 |
+
|
13 |
+
os.environ["KMP_DUPLICATE_LIB_OK"] = "True"
|
14 |
+
|
15 |
+
|
16 |
+
app = FastAPI(title="Metadata API")
|
17 |
+
|
18 |
+
SERVICE_ROOT = Path(__file__).parent.parent
|
19 |
+
|
20 |
+
|
21 |
+
app.add_middleware(
|
22 |
+
CORSMiddleware,
|
23 |
+
allow_origins=["*"],
|
24 |
+
allow_headers=["*"],
|
25 |
+
allow_credentials=True,
|
26 |
+
allow_methods=["*"],
|
27 |
+
)
|
28 |
+
|
29 |
+
|
30 |
+
@app.exception_handler(RequestValidationError)
|
31 |
+
async def validation_exception_handler(request: Request, exc: RequestValidationError):
|
32 |
+
# Get the original 'detail' list of errors
|
33 |
+
details = exc.errors()
|
34 |
+
error_details = []
|
35 |
+
|
36 |
+
for error in details:
|
37 |
+
error_details.append({"error": f"{error['msg']} {str(error['loc'])}"})
|
38 |
+
return JSONResponse(content={"message": error_details})
|
39 |
+
|
40 |
+
|
41 |
+
@app.on_event("startup")
|
42 |
+
async def startup_event():
|
43 |
+
pass
|
44 |
+
|
45 |
+
|
46 |
+
@app.get("/", include_in_schema=False)
|
47 |
+
async def root() -> None:
|
48 |
+
return RedirectResponse("/docs")
|
49 |
+
|
50 |
+
|
51 |
+
@app.get("/health", status_code=status.HTTP_200_OK, tags=["health"])
|
52 |
+
async def perform_healthcheck() -> None:
|
53 |
+
return JSONResponse(content={"message": "success"})
|
54 |
+
|
55 |
+
|
56 |
+
app.include_router(router)
|
57 |
+
|
58 |
+
|
59 |
+
# Start API
|
60 |
+
if __name__ == "__main__":
|
61 |
+
import uvicorn
|
62 |
+
|
63 |
+
uvicorn.run("main:app", host=settings.HOST, port=settings.PORT, reload=True)
|