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 @@ Logo -

VideoDB Python Client

+

VideoDB Python SDK

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):