Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
8e79b15
feat: add timelinev2
ankit-v2-3 Jun 23, 2025
a8fdf4e
fix: fit
ankit-v2-3 Jun 23, 2025
1e4a5f6
build: update v
ankit-v2-3 Jun 23, 2025
2b51bfc
fix: image asset
ankit-v2-3 Jun 26, 2025
2940995
feat: add audio asset
ankit-v2-3 Jul 2, 2025
2672b72
fix: asset enum
ankit-v2-3 Jul 2, 2025
3537e39
feat: add text asset
ankit-v2-3 Jul 8, 2025
ac78d55
fix: volume range
ankit-v2-3 Jul 17, 2025
fcf4796
feat: add caption asset
ankit-v2-3 Aug 5, 2025
9d5a6b0
fix: caption animation
ankit-v2-3 Aug 5, 2025
92dc137
fix: border style
ankit-v2-3 Aug 5, 2025
339e3a0
feat: add timeline download
ankit-v2-3 Aug 18, 2025
5027f9a
fix: position enum
ankit-v2-3 Sep 4, 2025
b28968a
fix: border style enum
ankit-v2-3 Sep 8, 2025
b15ab4f
docs: add docstrings
ankit-v2-3 Nov 21, 2025
33a271f
feat: increase api gateway timeout
ankit-v2-3 Dec 5, 2025
c379a86
feat: add editor
ankit-v2-3 Dec 10, 2025
2c3d152
fix: asset start
ankit-v2-3 Dec 12, 2025
092100d
docs: add docstrings
ankit-v2-3 Dec 12, 2025
7dee62d
Merge branch 'main' into ankit/add-videodb-editor
ankit-v2-3 Dec 12, 2025
8282460
fix: ci/cd
ankit-v2-3 Dec 12, 2025
d340301
fix: ci/cd
ankit-v2-3 Dec 12, 2025
f3af108
fix: ci/cd
ankit-v2-3 Dec 12, 2025
cc7e2b9
fix: ci/cd
ankit-v2-3 Dec 12, 2025
9bb1f56
docs: add docstings
ankit-v2-3 Dec 12, 2025
c1518c0
fix: ci/cd
ankit-v2-3 Dec 12, 2025
0d3a546
feat: add base64 ass string
ankit-v2-3 Dec 15, 2025
2889cb9
fix: Fit Enum
ankit-v2-3 Dec 24, 2025
1f325b1
Add reframe, smart vertical reframe and download functionality for vi…
ashish-spext Dec 25, 2025
4054df1
Add support for audio transcription and remove not required segmenter…
ashish-spext Dec 25, 2025
de2e32a
build: update version
ankit-v2-3 Dec 26, 2025
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 .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install setuptools==68.0.0
pip install -r requirements.txt
pip install -r requirements-dev.txt

Expand Down
4 changes: 3 additions & 1 deletion videodb/__about__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"""About information for videodb sdk"""

__version__ = "0.2.16"


__version__ = "0.3.0"
__title__ = "videodb"
__author__ = "videodb"
__email__ = "contact@videodb.io"
Expand Down
7 changes: 7 additions & 0 deletions videodb/_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ class Workflows:
add_subtitles = "add_subtitles"


class ReframeMode:
simple = "simple"
smart = "smart"


class SemanticSearchDefaultValues:
result_threshold = 5
score_threshold = 0.2
Expand Down Expand Up @@ -84,6 +89,8 @@ class ApiPath:
transcode = "transcode"
meeting = "meeting"
record = "record"
editor = "editor"
reframe = "reframe"


class Status:
Expand Down
97 changes: 97 additions & 0 deletions videodb/audio.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from typing import Dict, List, Union
from videodb._constants import (
ApiPath,
Segmenter,
)


Expand All @@ -10,6 +12,8 @@ class Audio:
:ivar str collection_id: ID of the collection this audio belongs to
:ivar str name: Name of the audio file
:ivar float length: Duration of the audio in seconds
:ivar list transcript: Timestamped transcript segments
:ivar str transcript_text: Full transcript text
"""

def __init__(
Expand All @@ -20,6 +24,8 @@ def __init__(
self.collection_id = collection_id
self.name = kwargs.get("name", None)
self.length = kwargs.get("length", None)
self.transcript = kwargs.get("transcript", None)
self.transcript_text = kwargs.get("transcript_text", None)

def __repr__(self) -> str:
return (
Expand All @@ -43,6 +49,97 @@ def generate_url(self) -> str:
)
return url_data.get("signed_url", None)

def _fetch_transcript(
self,
start: int = None,
end: int = None,
segmenter: str = Segmenter.word,
length: int = 1,
force: bool = None,
) -> None:
if self.transcript and not force and not start and not end:
return
transcript_data = self._connection.get(
path=f"{ApiPath.audio}/{self.id}/{ApiPath.transcription}",
params={
"start": start,
"end": end,
"segmenter": segmenter,
"length": length,
"force": "true" if force else "false",
},
show_progress=True,
)
self.transcript = transcript_data.get("word_timestamps", [])
self.transcript_text = transcript_data.get("text", "")

def get_transcript(
self,
start: int = None,
end: int = None,
segmenter: Segmenter = Segmenter.word,
length: int = 1,
force: bool = None,
) -> List[Dict[str, Union[float, str]]]:
"""Get timestamped transcript segments for the audio.

:param int start: Start time in seconds
:param int end: End time in seconds
:param Segmenter segmenter: Segmentation type (:class:`Segmenter.word`,
:class:`Segmenter.sentence`, :class:`Segmenter.time`)
:param int length: Length of segments when using time segmenter
:param bool force: Force fetch new transcript
:return: List of dicts with keys: start (float), end (float), text (str)
:rtype: List[Dict[str, Union[float, str]]]
"""
self._fetch_transcript(
start=start, end=end, segmenter=segmenter, length=length, force=force
)
return self.transcript

def get_transcript_text(
self,
start: int = None,
end: int = None,
) -> str:
"""Get plain text transcript for the audio.

:param int start: Start time in seconds to get transcript from
:param int end: End time in seconds to get transcript until
:param bool force: Force fetch new transcript
:return: Full transcript text as string
:rtype: str
"""
self._fetch_transcript(start=start, end=end)
return self.transcript_text

def generate_transcript(
self,
force: bool = None,
language_code: str = None,
) -> dict:
"""Generate transcript for the audio.

:param bool force: Force generate new transcript
:param str language_code: Language code of the spoken audio. If not provided, language is automatically detected.
:return: Success dict if transcript generated or already exists
:rtype: dict
"""
transcript_data = self._connection.post(
path=f"{ApiPath.audio}/{self.id}/{ApiPath.transcription}",
data={
"force": True if force else False,
"language_code": language_code,
},
)
transcript = transcript_data.get("word_timestamps", [])
if transcript:
return {
"success": True,
"message": "Transcript generated successfully",
}
return transcript_data

def delete(self) -> None:
"""Delete the audio.

Expand Down
Loading