-
Notifications
You must be signed in to change notification settings - Fork 234
feat: display image audio and video from url and tensor #1136
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
37 commits
Select commit
Hold shift + click to select a range
943d636
feat: display mesh and pointcloud
e9acd12
chore: update poetry
c91ab6c
fix: mypy
e979c32
fix: add display from param to mesh and pc display
21fb8ab
fix: clean up
75b33d8
fix: mypy
7890194
fix: move display from url to mesh and pc url classes
0129c3a
chore: remove pyglet dependency
322a718
chore: update pyproject toml
05d8461
refactor: copy is notebook function from hubble sdk
0244816
fix: introduce vertices and faces doc
255795c
fix: introduce points and colors class for point cloud
db42712
fix: mypy and tests
dca04ce
docs: add display example to docs
788f834
fix: apply johannes suggestion from review
57fb1e1
fix: apply samis suggestion
3a8dc5e
docs: update docstring
38f771d
fix: only display in notebook
8c31318
docs: update docstring
bbef411
chore: get poetry lock file from feat rewrite v2
b376ddd
docs: update docstrings
016760d
feat: display image from img url and img tensor
f55d811
fix: display from image url and from image tensor
0a23b52
fix: use is notebook from utils instead o f hubble
084921b
feat: audio from url
a949033
feat: display video and add pydub to pyproject toml
62b58ee
wip: remove non notebook
442dd29
fix: all except video tensor
b486b96
fix: mypy check for ipython display
f77d216
fix: mypy check for ipython display
ca948f9
feat: add videobytes
0dc606c
Merge remote-tracking branch 'origin/feat-rewrite-v2' into feat-displ…
f2c0cff
Merge remote-tracking branch 'origin/feat-rewrite-v2' into feat-displ…
48a85ba
chore: poetry lock
9df9df5
fix: clean up
e783c14
Merge branch 'feat-rewrite-v2' into feat-display-img-audio-vid
fe9d3bf
fix: mypy check
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
feat: add videobytes
Signed-off-by: anna-charlotte <[email protected]>
- Loading branch information
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| from io import BytesIO | ||
| from typing import TYPE_CHECKING, Any, NamedTuple, Type, TypeVar | ||
|
|
||
| import numpy as np | ||
| from pydantic import parse_obj_as | ||
| from pydantic.validators import bytes_validator | ||
|
|
||
| from docarray.typing import AudioNdArray, NdArray, VideoNdArray | ||
| from docarray.typing.abstract_type import AbstractType | ||
| from docarray.typing.proto_register import _register_proto | ||
|
|
||
| if TYPE_CHECKING: | ||
| from pydantic.fields import BaseConfig, ModelField | ||
|
|
||
| from docarray.proto import NodeProto | ||
|
|
||
| T = TypeVar('T', bound='VideoBytes') | ||
|
|
||
|
|
||
| class VideoLoadResult(NamedTuple): | ||
| video: VideoNdArray | ||
| audio: AudioNdArray | ||
| key_frame_indices: NdArray | ||
|
|
||
|
|
||
| @_register_proto(proto_type_name='video_bytes') | ||
| class VideoBytes(bytes, AbstractType): | ||
| """ | ||
| Bytes that store a video and that can be load into a video tensor | ||
| """ | ||
|
|
||
| @classmethod | ||
| def validate( | ||
| cls: Type[T], | ||
| value: Any, | ||
| field: 'ModelField', | ||
| config: 'BaseConfig', | ||
| ) -> T: | ||
|
|
||
| value = bytes_validator(value) | ||
| return cls(value) | ||
|
|
||
| @classmethod | ||
| def from_protobuf(cls: Type[T], pb_msg: T) -> T: | ||
| return parse_obj_as(cls, pb_msg) | ||
|
|
||
| def _to_node_protobuf(self: T) -> 'NodeProto': | ||
| from docarray.proto import NodeProto | ||
|
|
||
| return NodeProto(blob=self, type=self._proto_type_name) | ||
|
|
||
| def load(self, **kwargs) -> VideoLoadResult: | ||
| """ | ||
| Load the video from the bytes into a VideoLoadResult object consisting of a | ||
| VideoNdArray (`VideoLoadResult.video`), an AudioNdArray | ||
| (`VideoLoadResult.audio`) and an NdArray containing the key frame indices | ||
| (`VideoLoadResult.key_frame_indices`). | ||
|
|
||
| EXAMPLE USAGE | ||
|
|
||
| .. code-block:: python | ||
|
|
||
| from docarray import BaseDocument | ||
| from docarray.typing import VideoUrl | ||
| import numpy as np | ||
|
|
||
|
|
||
| class MyDoc(BaseDocument): | ||
| video_url: VideoUrl | ||
|
|
||
|
|
||
| doc = MyDoc( | ||
| video_url="https://upload.wikimedia.org/wikipedia/commons/8/80/" | ||
| "Dag_Sebastian_Ahlander_at_G%C3%B6teborg_Book_Fair_2012b.jpg" | ||
| ) | ||
|
|
||
| video, audio, key_frame_indices = doc.video_url.load() | ||
| assert isinstance(video, np.ndarray) | ||
| assert isinstance(audio, np.ndarray) | ||
| assert isinstance(key_frame_indices, np.ndarray) | ||
|
|
||
| :param kwargs: supports all keyword arguments that are being supported by | ||
| av.open() as described in: | ||
| https://pyav.org/docs/stable/api/_globals.html?highlight=open#av.open | ||
| :return: a VideoLoadResult instance with video, audio and keyframe indices | ||
| """ | ||
| import av | ||
|
|
||
| with av.open(BytesIO(self), **kwargs) as container: | ||
| audio_frames = [] | ||
| video_frames = [] | ||
| keyframe_indices = [] | ||
|
|
||
| for frame in container.decode(): | ||
| if type(frame) == av.audio.frame.AudioFrame: | ||
| audio_frames.append(frame.to_ndarray()) | ||
| elif type(frame) == av.video.frame.VideoFrame: | ||
| video_frames.append(frame.to_ndarray(format='rgb24')) | ||
|
|
||
| if frame.key_frame == 1: | ||
| curr_index = len(video_frames) | ||
| keyframe_indices.append(curr_index) | ||
|
|
||
| if len(audio_frames) == 0: | ||
| audio = parse_obj_as(AudioNdArray, np.array(audio_frames)) | ||
| else: | ||
| audio = parse_obj_as(AudioNdArray, np.stack(audio_frames)) | ||
|
|
||
| video = parse_obj_as(VideoNdArray, np.stack(video_frames)) | ||
| indices = parse_obj_as(NdArray, keyframe_indices) | ||
|
|
||
| return VideoLoadResult(video=video, audio=audio, key_frame_indices=indices) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here mypy complains because
"T" has no attribute "save". Why does it no complain though in line 164 (b = self.to_bytes(audio_tensor=audio)), isn'tto_bytes()just a method ofVideoTensorMixinlikesave()?