Blocks-Components

- move video component
This commit is contained in:
Ömer Faruk Özdemir 2022-03-15 11:59:18 +03:00
parent 921d0b03cf
commit cf32e0097c
3 changed files with 176 additions and 136 deletions

View File

@ -11,6 +11,7 @@ from typing import Any, Dict, List, Optional, Tuple
import numpy as np
import PIL
from ffmpy import FFmpeg
from gradio import processing_utils, test_data
from gradio.blocks import Block
@ -507,7 +508,7 @@ class Slider(Component):
if step is None:
difference = maximum - minimum
power = math.floor(math.log10(difference) - 2)
step = 10**power
step = 10 ** power
self.step = step
self.default = minimum if default is None else default
self.test_input = self.default
@ -931,6 +932,7 @@ class Image(Component):
):
"""
Parameters:
default(str): IGNORED
shape (Tuple[int, int]): (width, height) shape to crop and resize image to; if None, matches input image size.
image_mode (str): "RGB" if color, or "L" if black and white.
invert_colors (bool): whether to invert the image as a preprocessing step.
@ -1210,3 +1212,122 @@ class Image(Component):
def restore_flagged(self, dir, data, encryption_key):
return self.restore_flagged_file(dir, data, encryption_key)["data"]
class Video(Component):
"""
Component creates a video file upload that is converted to a file path.
Input type: filepath
Output type: filepath
Demos: video_flip
"""
def __init__(
self,
default="",
*,
type: Optional[str] = None,
source: str = "upload",
label: Optional[str] = None,
optional: bool = False,
):
"""
Parameters:
default (str): IGNORED
type (str): Type of video format to be returned by component, such as 'avi' or 'mp4'. Use 'mp4' to ensure browser playability. If set to None, video will keep uploaded format.
source (str): Source of video. "upload" creates a box where user can drop an video file, "webcam" allows user to record a video from their webcam.
label (str): component name in interface.
optional (bool): If True, the interface can be submitted with no uploaded video, in which case the input value is None.
"""
self.type = type
self.source = source
super().__init__(label=label, optional=optional)
@classmethod
def get_shortcut_implementations(cls):
return {
"video": {},
"playable_video": {"type": "mp4"},
}
def get_template_context(self):
return {
"source": self.source,
"optional": self.optional,
**super().get_template_context(),
}
def preprocess_example(self, x):
return {"name": x, "data": None, "is_example": True}
def preprocess(self, x: Dict[str, str] | None) -> str | None:
"""
Parameters:
x (Dict[name: str, data: str]): JSON object with filename as 'name' property and base64 data as 'data' property
Returns:
(str): file path to video
"""
if x is None:
return x
file_name, file_data, is_example = (
x["name"],
x["data"],
x.get("is_example", False),
)
if is_example:
file = processing_utils.create_tmp_copy_of_file(file_name)
else:
file = processing_utils.decode_base64_to_file(
file_data, file_path=file_name
)
file_name = file.name
uploaded_format = file_name.split(".")[-1].lower()
if self.type is not None and uploaded_format != self.type:
output_file_name = file_name[0: file_name.rindex(".") + 1] + self.type
ff = FFmpeg(inputs={file_name: None}, outputs={output_file_name: None})
ff.run()
return output_file_name
else:
return file_name
def serialize(self, x, called_directly):
raise NotImplementedError()
def save_flagged(self, dir, label, data, encryption_key):
"""
Returns: (str) path to video file
"""
return self.save_flagged_file(
dir, label, None if data is None else data["data"], encryption_key
)
# TODO: Might need to converge these two
# Output save_flagged:
# return self.save_flagged_file(dir, label, data["data"], encryption_key)
def generate_sample(self):
return test_data.BASE64_VIDEO
def postprocess(self, y):
"""
Parameters:
y (str): path to video
Returns:
(str): base64 url data
"""
returned_format = y.split(".")[-1].lower()
if self.type is not None and returned_format != self.type:
output_file_name = y[0: y.rindex(".") + 1] + self.type
ff = FFmpeg(inputs={y: None}, outputs={output_file_name: None})
ff.run()
y = output_file_name
return {
"name": os.path.basename(y),
"data": processing_utils.encode_file_to_base64(y),
}
def deserialize(self, x):
return processing_utils.decode_base64_to_file(x).name
def restore_flagged(self, dir, data, encryption_key):
return self.restore_flagged_file(dir, data, encryption_key)

View File

@ -278,6 +278,10 @@ class Image(Image):
label (str): component name in interface.
optional (bool): If True, the interface can be submitted with no uploaded image, in which case the input value is None.
"""
warnings.warn(
"Usage of gradio.inputs is deprecated, and will not be supported in the future, please import your component from gradio.components",
DeprecationWarning,
)
super().__init__(
shape=shape,
image_mode=image_mode,
@ -290,6 +294,35 @@ class Image(Image):
)
class Video(Component):
"""
Component creates a video file upload that is converted to a file path.
Input type: filepath
Demos: video_flip
"""
def __init__(
self,
type: Optional[str] = None,
source: str = "upload",
label: Optional[str] = None,
optional: bool = False,
):
"""
Parameters:
type (str): Type of video format to be returned by component, such as 'avi' or 'mp4'. If set to None, video will keep uploaded format.
source (str): Source of video. "upload" creates a box where user can drop an video file, "webcam" allows user to record a video from their webcam.
label (str): component name in interface.
optional (bool): If True, the interface can be submitted with no uploaded video, in which case the input value is None.
"""
warnings.warn(
"Usage of gradio.inputs is deprecated, and will not be supported in the future, please import your components from gradio.components",
DeprecationWarning,
)
super().__init__(type=type, source=source, label=label, optional=optional)
class InputComponent(Component):
"""
Input Component. All input components subclass this.
@ -373,92 +406,6 @@ class InputComponent(Component):
}
class Video(InputComponent):
"""
Component creates a video file upload that is converted to a file path.
Input type: filepath
Demos: video_flip
"""
def __init__(
self,
type: Optional[str] = None,
source: str = "upload",
label: Optional[str] = None,
optional: bool = False,
):
"""
Parameters:
type (str): Type of video format to be returned by component, such as 'avi' or 'mp4'. If set to None, video will keep uploaded format.
source (str): Source of video. "upload" creates a box where user can drop an video file, "webcam" allows user to record a video from their webcam.
label (str): component name in interface.
optional (bool): If True, the interface can be submitted with no uploaded video, in which case the input value is None.
"""
self.type = type
self.source = source
super().__init__(label, optional=optional)
@classmethod
def get_shortcut_implementations(cls):
return {
"video": {},
}
def get_template_context(self):
return {
"source": self.source,
"optional": self.optional,
**super().get_template_context(),
}
def preprocess_example(self, x):
return {"name": x, "data": None, "is_example": True}
def preprocess(self, x: Dict[str, str] | None) -> str | None:
"""
Parameters:
x (Dict[name: str, data: str]): JSON object with filename as 'name' property and base64 data as 'data' property
Returns:
(str): file path to video
"""
if x is None:
return x
file_name, file_data, is_example = (
x["name"],
x["data"],
x.get("is_example", False),
)
if is_example:
file = processing_utils.create_tmp_copy_of_file(file_name)
else:
file = processing_utils.decode_base64_to_file(
file_data, file_path=file_name
)
file_name = file.name
uploaded_format = file_name.split(".")[-1].lower()
if self.type is not None and uploaded_format != self.type:
output_file_name = file_name[0 : file_name.rindex(".") + 1] + self.type
ff = FFmpeg(inputs={file_name: None}, outputs={output_file_name: None})
ff.run()
return output_file_name
else:
return file_name
def serialize(self, x, called_directly):
raise NotImplementedError()
def save_flagged(self, dir, label, data, encryption_key):
"""
Returns: (str) path to video file
"""
return self.save_flagged_file(
dir, label, None if data is None else data["data"], encryption_key
)
def generate_sample(self):
return test_data.BASE64_VIDEO
class Audio(InputComponent):
"""
Component accepts audio input files.

View File

@ -21,7 +21,7 @@ import PIL
from ffmpy import FFmpeg
from gradio import processing_utils
from gradio.components import Component, Image, Textbox
from gradio.components import Component, Image, Textbox, Video
if TYPE_CHECKING: # Only import for type checking (is False at runtime).
from gradio import Interface
@ -65,6 +65,26 @@ class Image(Image):
super().__init__(label=label, type=type, plot=plot)
class Video(Video):
"""
Used for video output.
Output type: filepath
Demos: video_flip
"""
def __init__(self, type: Optional[str] = None, label: Optional[str] = None):
"""
Parameters:
type (str): Type of video format to be passed to component, such as 'avi' or 'mp4'. Use 'mp4' to ensure browser playability. If set to None, video will keep returned format.
label (str): component name in interface.
"""
warnings.warn(
"Usage of gradio.outputs is deprecated, and will not be supported in the future, please import your components from gradio.components",
DeprecationWarning,
)
super().__init__(label=label, type=type)
class OutputComponent(Component):
"""
Output Component. All output components subclass this.
@ -191,54 +211,6 @@ class Label(OutputComponent):
return data
class Video(OutputComponent):
"""
Used for video output.
Output type: filepath
Demos: video_flip
"""
def __init__(self, type: Optional[str] = None, label: Optional[str] = None):
"""
Parameters:
type (str): Type of video format to be passed to component, such as 'avi' or 'mp4'. Use 'mp4' to ensure browser playability. If set to None, video will keep returned format.
label (str): component name in interface.
"""
self.type = type
super().__init__(label)
@classmethod
def get_shortcut_implementations(cls):
return {"video": {}, "playable_video": {"type": "mp4"}}
def postprocess(self, y):
"""
Parameters:
y (str): path to video
Returns:
(str): base64 url data
"""
returned_format = y.split(".")[-1].lower()
if self.type is not None and returned_format != self.type:
output_file_name = y[0 : y.rindex(".") + 1] + self.type
ff = FFmpeg(inputs={y: None}, outputs={output_file_name: None})
ff.run()
y = output_file_name
return {
"name": os.path.basename(y),
"data": processing_utils.encode_file_to_base64(y),
}
def deserialize(self, x):
return processing_utils.decode_base64_to_file(x).name
def save_flagged(self, dir, label, data, encryption_key):
return self.save_flagged_file(dir, label, data["data"], encryption_key)
def restore_flagged(self, dir, data, encryption_key):
return self.restore_flagged_file(dir, data, encryption_key)
class KeyValues(OutputComponent):
"""
Component displays a table representing values for multiple fields.