diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
new file mode 100644
index 0000000..76a9a02
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -0,0 +1,79 @@
+name: Bug report
+description: Create a report to help us improve
+labels: ['bug']
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Thanks for taking the time to fill out this bug report!
+ - type: checkboxes
+ attributes:
+ label: Confirm this is a new bug report
+ description: >
+ Select the checkboxes that apply to this bug report. If you're not sure about any of these, don't worry! We'll help you figure it out.
+ options:
+ - label: Possible new bug in VideoDB Python Client
+ required: false
+ - label: Potential new bug in VideoDB API
+ required: false
+ - label: I've checked the current issues, and there's no record of this bug
+ required: true
+ - type: textarea
+ attributes:
+ label: Current Behavior
+ description: >
+ A clear and concise description of what the bug is.
+ placeholder: >
+ I intended to perform action X, but unexpectedly encountered outcome Y.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Expected Behavior
+ description: >
+ A clear and concise description of what you expected to happen.
+ placeholder: >
+ I expected outcome Y to occur.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Steps to Reproduce
+ description: >
+ Steps to reproduce the behavior:
+ placeholder: |
+ 1. Fetch a '...'
+ 2. Update the '....'
+ 3. See error
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Relevant Logs and/or Screenshots
+ description: >
+ If applicable, add logs and/or screenshots to help explain your problem.
+ validations:
+ required: false
+ - type: textarea
+ attributes:
+ label: Environment
+ description: |
+ Please complete the following information:
+ eg:
+ - OS: Ubuntu 20.04
+ - Python: 3.9.1
+ - Videodb: 0.0.1
+ value: |
+ - OS:
+ - Python:
+ - Videodb:
+ validations:
+ required: false
+ - type: textarea
+ attributes:
+ label: Additional Context
+ description: >
+ Add any other context about the problem here.
+ validations:
+ required: false
+
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
new file mode 100644
index 0000000..3a217cc
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -0,0 +1,48 @@
+name: Feature
+description: Submit a proposal/request for a new feature
+labels: ['enhancement']
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Thanks for taking the time to fill out this feature request!
+ - type: checkboxes
+ attributes:
+ label: Confirm this is a new feature request
+ description: >
+ Select the checkboxes that apply to this feature request. If you're not sure about any of these, don't worry! We'll help you figure it out.
+ options:
+ - label: Possible new feature in VideoDB Python Client
+ required: false
+ - label: Potential new feature in VideoDB API
+ required: false
+ - label: I've checked the current issues, and there's no record of this feature request
+ required: true
+ - type: textarea
+ attributes:
+ label: Describe the feature
+ description: >
+ A clear and concise description of what the feature is and why it's needed.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Describe the solution you'd like
+ description: |
+ A clear and concise description of what you want to happen.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Describe alternatives you've considered
+ description: >
+ A clear and concise description of any alternative solutions or features you've considered.
+ validations:
+ required: false
+ - type: textarea
+ attributes:
+ label: Additional Context
+ description: >
+ Add any other context about the feature request here.
+ validations:
+ required: false
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 0000000..f913b20
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,24 @@
+## Pull Request
+
+**Description:**
+Describe the purpose of this pull request.
+
+**Changes:**
+- [ ] Feature A
+- [ ] Bugfix B
+
+**Related Issues:**
+- Closes #123
+- Addresses #456
+
+**Testing:**
+Describe any testing steps that have been taken or are necessary.
+Make sure to take in account any existing code change that require some feature to be re-tested.
+
+
+**Checklist:**
+- [ ] Code follows project coding standards
+- [ ] Tests have been added or updated
+- [ ] Code Review
+- [ ] Manual test after merge
+- [ ] All checks passed
\ No newline at end of file
diff --git a/README.md b/README.md
index 7b84481..574b97b 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@
-
Video Database for your AI Applications @@ -34,8 +34,8 @@
-# VideoDB Python Client -The VideoDB Python client is a python package that allows you to interact with the VideoDB which is a serverless database that lets you manage video as intelligent data, not files. It is secure, scalable & optimized for AI- applications and LLM integrations. +# VideoDB Python SDK +VideoDB Python SDK allows you to interact with the VideoDB serverless database. Manage videos as intelligent data, not files. It's scalable, cost efficient & optimized for AI applications and LLM integration. ## Quick Start ### Creating a Connection -To create a new connection you need to get API key from [VideoDB console](https://console.videodb.io). You can directly upload from youtube, any public url, S3 bucket or local file path. A default collection is created when you create a new connection. +Get API key from [VideoDB console](https://console.videodb.io). Free for first 50 uploads. _(No credit card required)_ ```python import videodb - -# create a new connection to the VideoDB conn = videodb.connect(api_key="YOUR_API_KEY") +``` +## Working with a single Video -# upload to the default collection using the video url returns a Video object -video = conn.upload(url="https://www.youtube.com/") +--- -# upload to the default collection using the local file path returns a Video object -video = conn.upload(file_path="path/to/video.mp4") +β¬οΈ **Uploading a Video** -# get the stream url for the video -stream_url = video.generate_stream() +Now that you have established a connection to VideoDB, you can upload your videos using `conn.upload()` +You can directly upload from `youtube`, `any public url`, `S3 bucket` or `local file path`. A default collection is created when you create a new connection. -``` - -### Getting a Collection -To get a collection, use the `get_collection` method on the established database connection object. This method returns a `Collection` object. +`upload` method returns a `Video` object. ```python -import videodb +# Upload a video by url +video = conn.upload(url="https://www.youtube.com/watch?v=WDv4AWk0J3U") -# create a connection to the VideoDB -conn = videodb.connect(api_key="YOUR_API_KEY") +# Upload a video from file system +video_f = conn.upload(file_path="./my_video.mp4") + +``` -# get the default collection -collection = conn.get_collection() +### πΊ Viewing your video -# Upload a video to the collection returns a Video object -video = collection.upload(url="https://www.youtube.com/") +Your video is instantly available for viewing 720p resolution β‘οΈ -# async upload -collection.upload(url="https://www.youtube.com/", callback_url="https://yourdomain.com/callback") +* Generate a streamable url for video using video.generate_stream() +* Preview the video using video.play(). This will open the video in your default browser/notebook -# get all the videos in the collection returns a list of Video objects -videos = collection.get_videos() +```python +video.generate_stream() +video.play() +``` -# get a video from the collection returns a Video object -video = collection.get_video("video_id") +### βοΈ Stream Sections of videos -# delete the video from the collection -collection.delete_video("video_id") +You can easily clip specific sections of a video by passing timeline of start and end sections. +It accepts seconds. For example, Hereβs we are streaming only first `10 seconds` and then `120` to `140 second` of a video +```python +stream_link = video.generate_stream(timeline=[[0,10], [120,140]]) +play_stream(stream_link) ``` -### Multi Modal Indexing +### π Searching inside a video -#### Spoken words indexing +To search bits inside a video β you have to index the video first. This can be done by a simple command. +_Indexing may take some time for longer videos._ ```python -import videodb +video.index_spoken_words() +result = video.search("Morning Sunlight") +result.play() +video.get_transcript() +``` +`Videodb` is launching more indexes in upcoming versions. +Currently it offers semantic index - Index by spoken words. -# create a connection to the VideoDB and get the default collection -conn = videodb.connect(api_key="YOUR_API_KEY") -collection = conn.get_collection() +In future you can also index videos using: +1. **Scene** - Visual concepts and events. +2. **Faces**. +3. **Specific domain Index** like Football, Baseball, Drone footage, Cricket etc. -# get the video from the collection -video = collection.get_video("video_id") +### Viewing Search Results : -# index the video for semantic search -video.index_spoken_words() +`video.search()` will return a `SearchResults` object, which contains the sections/shots of videos which semantically match your search query -# search relevant moment in video and stream resultant video clip instantly. -# returns a SearchResults object -# for searching the video, the video must be indexed please use index_spoken_words() before searching -# optional parameters: -# - type: Optional[str] to specify the type of search. default is "semantic" -# - result_threshold: Optional[int] to specify the number of results to return. default is 5 -# - score_threshold: Optional[float] to specify the score threshold for the results. default is 0.2 -result = video.search("what is videodb?") -# get stream url of the result -stream_url = result.compile() -# get shots of the result returns a list of Shot objects -shots = result.get_shots() -# get stream url of the shot -short_stream_url = shots[0].compile() - -# search relevant moment in collections and stream resultant video clip instantly. -# returns a SearchResults object -result = collection.search("what is videodb?") -# get stream url of the result -stream_url = result.compile() -# get shots of the result returns a list of Shot objects -shots = result.get_shots() -# get stream url of the shot -short_stream_url = shots[0].generate_stream() +* `result.get_shots()` Returns a list of Shot that matched search query +* `result.play()` Returns a playable url for video (similar to video.play() you can open this link in browser, or embed it into your website using iframe) -``` +## RAG: Search inside Multiple Videos + +--- + +`VideoDB` can store and search inside multiple videos with ease. By default, videos are uploaded to your default collection. + +### π Using Collection to upload multiple Videos -### Video Object Methods ```python -import videodb +# Get the default collection +coll = conn.get_collection() -# create a connection to the VideoDB, get the default collection and get a video -conn = videodb.connect(api_key="YOUR_API_KEY") -collection = conn.get_collection() -video = collection.get_video("video_id") +# Upload Videos to a collection +coll.upload(url="https://www.youtube.com/watch?v=lsODSDmY4CY") +coll.upload(url="https://www.youtube.com/watch?v=vZ4kOr38JhY") +coll.upload(url="https://www.youtube.com/watch?v=uak_dXHh6s4") +``` +* `conn.get_collection()` : Returns Collection object, the default collection +* `coll.get_videos()` : Returns list of Video, all videos in collections +* `coll.get_video(video_id)`: Returns Video, respective video object from given `video_id` +* `coll.delete_video(video_id)`: Deletes the video from Collection -# get the stream url of the dynamically curated video based on the given timeline sequence -# optional parameters: -# - timeline: Optional[list[tuple[int, int]] to specify the start and end time of the video -stream_url = video.generate_stream(timeline=[(0, 10), (30, 40)]) +### π Search inside collection -# get thumbnail url of the video -thumbnail_url = video.generate_thumbnail() +You can simply Index all the videos in a collection and use +search method on collection to find relevant results. +Here we are indexing spoken content of a +collection and performing semantic search. +```python +# Index all videos in collection +for video in coll.get_videos(): + video.index_spoken_words() -# get transcript of the video -# optional parameters: -# - force: Optional[bool] to force get the transcript. default is False -transcript = video.get_transcript() +# search in the collection of videos +results = coll.search(query = "What is Dopamine?") +results.play() +``` +The result here has all the matching bits in a single stream from your collection. You can use these results in your application right away. + +### π Explore the Video object -# get transcript text of the video -# optional parameters: -# - force: Optional[bool] to force get the transcript text. default is False -transcript_text = video.get_transcript_text() +There are multiple methods available on a Video Object, that can be helpful for your use-case. -# add subtitle to the video and get the stream url of the video with subtitle -stream_url = video.add_subtitle() +**Access Transcript** +```python +# words with timestamps +text_json = video.get_transcript() +text = video.get_transcript_text() +print(text) +``` -# delete the video from the collection -video.delete() +**Add Subtitle to a video** +It returns a new stream instantly with subtitle added into the video. +```python +new_stream = video.add_subtitle() +play_stream(new_stream) ``` +**Get Thumbnail of Video:** - -## Roadmap +`video.generate_thumbnail()`: Returns a thumbnail image of video. -See the [open issues](https://github.com/video-db/videodb-python/issues) for a list of proposed features (and known issues). +**Delete a video:** +`video.delete()`: Delete a video. +Checkout more examples and tutorials π [Build with VideoDB](https://docs.videodb.io/build-with-videodb-35) to explore what you can +build with `VideoDB` + +--- + +## Roadmap +- Adding More Indexes : `Face`, `Scene`, `Security`, `Events`, and `Sports` +- Give prompt support to generate thumbnails using GenAI. +- Give prompt support to access content. +- Give prompt support to edit videos. +- See the [open issues](https://github.com/video-db/videodb-python/issues) for a list of proposed features (and known issues). + +--- ## Contributing @@ -195,11 +215,7 @@ Contributions are what make the open source community such an amazing place to b 4. Push to the Branch (`git push origin feature/AmazingFeature`) 5. Open a Pull Request - -## License - -Distributed under the MIT License. See `LICENSE` for more information. - +--- diff --git a/setup.py b/setup.py index 6756694..86ef2b4 100644 --- a/setup.py +++ b/setup.py @@ -21,9 +21,9 @@ def get_version(): setup( name="videodb", version=get_version(), - author="Videodb", + author="videodb", author_email="contact@videodb.io", - description="Videodb Python client", + description="VideoDB Python SDK", long_description=long_description, long_description_content_type="text/markdown", url="https://github.com/video-db/videodb-python", @@ -33,5 +33,9 @@ def get_version(): "requests>=2.25.1", "backoff>=2.2.1", ], - + classifiers=[ + "Intended Audience :: Developers", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.9", + ], ) diff --git a/videodb/__init__.py b/videodb/__init__.py index 2318106..b5f18f4 100644 --- a/videodb/__init__.py +++ b/videodb/__init__.py @@ -16,7 +16,7 @@ logger: logging.Logger = logging.getLogger("videodb") -__version__ = "0.0.1" +__version__ = "0.0.2" __author__ = "videodb" __all__ = [ diff --git a/videodb/_constants.py b/videodb/_constants.py index 2ad2d8a..9911271 100644 --- a/videodb/_constants.py +++ b/videodb/_constants.py @@ -2,7 +2,7 @@ VIDEO_DB_API: str = "https://api.videodb.io" -PLAYER_URL: str = "https://console.videodb.io/player" + class SearchType: diff --git a/videodb/_utils/_video.py b/videodb/_utils/_video.py index b5b0bf9..9cdb012 100644 --- a/videodb/_utils/_video.py +++ b/videodb/_utils/_video.py @@ -1,6 +1,5 @@ import webbrowser as web - -from videodb._constants import PLAYER_URL +PLAYER_URL: str = "https://console.videodb.io/player" def play_stream(url: str):