Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
22 changes: 11 additions & 11 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,31 @@
import os
from setuptools import setup, find_packages

ROOT = os.path.dirname(__file__)
ROOT = os.path.dirname(os.path.abspath(__file__))


# Read in the package version per recommendations from:
# https://packaging.python.org/guides/single-sourcing-package-version/
def get_version():
with open(os.path.join(ROOT, "videodb", "__init__.py")) as f:
for line in f.readlines():
if line.startswith("__version__"):
return line.split("=")[1].strip().strip('''"''')

about_path = os.path.join(ROOT, "videodb", "__about__.py")
about = {}
with open(about_path) as fp:
exec(fp.read(), about)


# read the contents of README file
long_description = open(os.path.join(ROOT, "README.md"), "r", encoding="utf-8").read()


setup(
name="videodb",
version=get_version(),
author="videodb",
author_email="[email protected]",
name=about["__title__"],
version=about["__version__"],
author=about["__author__"],
author_email=about["__email__"],
description="VideoDB Python SDK",
long_description=long_description,
long_description_content_type="text/markdown",
url="https://github.com/video-db/videodb-python",
url=about["__url__"],
packages=find_packages(exclude=["tests", "tests.*"]),
python_requires=">=3.8",
install_requires=[
Expand Down
8 changes: 8 additions & 0 deletions videodb/__about__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
""" About information for videodb sdk"""


__version__ = "0.2.0"
__title__ = "videodb"
__author__ = "videodb"
__email__ = "[email protected]"
__url__ = "https://github.com/video-db/videodb-python"
4 changes: 2 additions & 2 deletions videodb/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from videodb._utils._video import play_stream
from videodb._constants import (
VIDEO_DB_API,
SceneExtractionType,
MediaType,
SearchType,
SubtitleAlignment,
Expand All @@ -24,8 +25,6 @@

logger: logging.Logger = logging.getLogger("videodb")

__version__ = "0.1.2"
__author__ = "videodb"

__all__ = [
"VideodbError",
Expand All @@ -39,6 +38,7 @@
"SubtitleBorderStyle",
"SubtitleStyle",
"TextStyle",
"SceneExtractionType",
]


Expand Down
7 changes: 7 additions & 0 deletions videodb/_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ class IndexType:
scene = "scene"


class SceneExtractionType:
scene_based = "scene"
time_based = "time"


class Workflows:
add_subtitles = "add_subtitles"

Expand Down Expand Up @@ -51,6 +56,8 @@ class ApiPath:
billing = "billing"
usage = "usage"
invoices = "invoices"
scenes = "scenes"
scene = "scene"


class Status:
Expand Down
13 changes: 10 additions & 3 deletions videodb/_utils/_http_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from videodb.exceptions import (
AuthenticationError,
InvalidRequestError,
RequestTimeoutError,
)

logger = logging.getLogger(__name__)
Expand All @@ -31,6 +32,7 @@ def __init__(
self,
api_key: str,
base_url: str,
version: str,
max_retries: Optional[int] = HttpClientDefaultValues.max_retries,
) -> None:
"""Create a new http client instance
Expand All @@ -49,8 +51,13 @@ def __init__(
adapter = HTTPAdapter(max_retries=retries)
self.session.mount("http://", adapter)
self.session.mount("https://", adapter)
self.version = version
self.session.headers.update(
{"x-access-token": api_key, "Content-Type": "application/json"}
{
"x-access-token": api_key,
"x-videodb-client": f"videodb-python/{self.version}",
"Content-Type": "application/json",
}
)
self.base_url = base_url
self.show_progress = False
Expand Down Expand Up @@ -109,8 +116,8 @@ def _handle_request_error(self, e: requests.exceptions.RequestException) -> None
) from None

elif isinstance(e, requests.exceptions.Timeout):
raise InvalidRequestError(
"Invalid request: Request timed out", e.response
raise RequestTimeoutError(
"Timeout error: Request timed out", e.response
) from None

elif isinstance(e, requests.exceptions.ConnectionError):
Expand Down
4 changes: 2 additions & 2 deletions videodb/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
Union,
List,
)

from videodb.__about__ import __version__
from videodb._constants import (
ApiPath,
)
Expand All @@ -28,7 +28,7 @@ def __init__(self, api_key: str, base_url: str) -> None:
self.api_key = api_key
self.base_url = base_url
self.collection_id = "default"
super().__init__(api_key, base_url)
super().__init__(api_key=api_key, base_url=base_url, version=__version__)

def get_collection(self, collection_id: Optional[str] = "default") -> Collection:
collection_data = self.get(path=f"{ApiPath.collection}/{collection_id}")
Expand Down
4 changes: 2 additions & 2 deletions videodb/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ def search(
query: str,
search_type: Optional[str] = SearchType.semantic,
result_threshold: Optional[int] = None,
score_threshold: Optional[int] = None,
dynamic_score_percentage: Optional[int] = None,
score_threshold: Optional[float] = None,
dynamic_score_percentage: Optional[float] = None,
) -> SearchResult:
search = SearchFactory(self._connection).get_search(search_type)
return search.search_inside_collection(
Expand Down
10 changes: 10 additions & 0 deletions videodb/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ def __init__(self, message, response=None):
self.response = response


class RequestTimeoutError(VideodbError):
"""
Raised when a request times out.
"""

def __init__(self, message, response=None):
super(RequestTimeoutError, self).__init__(message)
self.response = response


class SearchError(VideodbError):
"""
Raised when a search is invalid.
Expand Down
39 changes: 39 additions & 0 deletions videodb/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,42 @@ def __repr__(self) -> str:

def delete(self) -> None:
self._connection.delete(f"{ApiPath.image}/{self.id}")


class Frame(Image):
def __init__(
self,
_connection,
id: str,
video_id: str,
scene_id: str,
url: str,
frame_time: float,
description: str,
):
super().__init__(_connection=_connection, id=id, collection_id=None, url=url)
self.scene_id = scene_id
self.video_id = video_id
self.frame_time = frame_time
self.description = description

def __repr__(self) -> str:
return (
f"Frame("
f"id={self.id}, "
f"video_id={self.video_id}, "
f"scene_id={self.scene_id}, "
f"url={self.url}, "
f"frame_time={self.frame_time}, "
f"description={self.description})"
)

def to_json(self):
return {
"id": self.id,
"video_id": self.video_id,
"scene_id": self.scene_id,
"url": self.url,
"frame_time": self.frame_time,
"description": self.description,
}
74 changes: 74 additions & 0 deletions videodb/scene.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
from typing import List

from videodb._constants import ApiPath

from videodb.image import Frame


class Scene:
def __init__(
self,
video_id: str,
start: float,
end: float,
description: str,
id: str = None,
frames: List[Frame] = [],
):
self.id = id
self.video_id = video_id
self.start = start
self.end = end
self.frames: List[Frame] = frames
self.description = description

def __repr__(self) -> str:
return (
f"Scene("
f"id={self.id}, "
f"video_id={self.video_id}, "
f"start={self.start}, "
f"end={self.end}, "
f"frames={self.frames}, "
f"description={self.description})"
)

def to_json(self):
return {
"id": self.id,
"video_id": self.video_id,
"start": self.start,
"end": self.end,
"frames": [frame.to_json() for frame in self.frames],
"description": self.description,
}


class SceneCollection:
def __init__(
self,
_connection,
id: str,
video_id: str,
config: dict,
scenes: List[Scene],
) -> None:
self._connection = _connection
self.id = id
self.video_id = video_id
self.config: dict = config
self.scenes: List[Scene] = scenes

def __repr__(self) -> str:
return (
f"SceneCollection("
f"id={self.id}, "
f"video_id={self.video_id}, "
f"config={self.config}, "
f"scenes={self.scenes})"
)

def delete(self) -> None:
self._connection.delete(
path=f"{ApiPath.video}/{self.video_id}/{ApiPath.scenes}/{self.id}"
)
22 changes: 14 additions & 8 deletions videodb/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ def search_inside_video(
video_id: str,
query: str,
result_threshold: Optional[int] = None,
score_threshold: Optional[int] = None,
dynamic_score_percentage: Optional[int] = None,
score_threshold: Optional[float] = None,
dynamic_score_percentage: Optional[float] = None,
**kwargs,
):
search_data = self._connection.post(
Expand All @@ -123,6 +123,8 @@ def search_inside_video(
or SemanticSearchDefaultValues.score_threshold,
"result_threshold": result_threshold
or SemanticSearchDefaultValues.result_threshold,
"dynamic_score_percentage": dynamic_score_percentage,
**kwargs,
},
)
return SearchResult(self._connection, **search_data)
Expand All @@ -132,8 +134,8 @@ def search_inside_collection(
collection_id: str,
query: str,
result_threshold: Optional[int] = None,
score_threshold: Optional[int] = None,
dynamic_score_percentage: Optional[int] = None,
score_threshold: Optional[float] = None,
dynamic_score_percentage: Optional[float] = None,
**kwargs,
):
search_data = self._connection.post(
Expand All @@ -145,6 +147,8 @@ def search_inside_collection(
or SemanticSearchDefaultValues.score_threshold,
"result_threshold": result_threshold
or SemanticSearchDefaultValues.result_threshold,
"dynamic_score_percentage": dynamic_score_percentage,
**kwargs,
},
)
return SearchResult(self._connection, **search_data)
Expand All @@ -159,8 +163,8 @@ def search_inside_video(
video_id: str,
query: str,
result_threshold: Optional[int] = None,
score_threshold: Optional[int] = None,
dynamic_score_percentage: Optional[int] = None,
score_threshold: Optional[float] = None,
dynamic_score_percentage: Optional[float] = None,
**kwargs,
):
search_data = self._connection.post(
Expand All @@ -187,8 +191,8 @@ def search_inside_video(
video_id: str,
query: str,
result_threshold: Optional[int] = None,
score_threshold: Optional[int] = None,
dynamic_score_percentage: Optional[int] = None,
score_threshold: Optional[float] = None,
dynamic_score_percentage: Optional[float] = None,
**kwargs,
):
search_data = self._connection.post(
Expand All @@ -198,6 +202,8 @@ def search_inside_video(
"query": query,
"score_threshold": score_threshold,
"result_threshold": result_threshold,
"dynamic_score_percentage": dynamic_score_percentage,
**kwargs,
},
)
return SearchResult(self._connection, **search_data)
Expand Down
Loading