elismasilva commited on
Commit
ea19e8c
·
verified ·
1 Parent(s): 1359adf

Update space.py

Browse files
Files changed (1) hide show
  1. space.py +222 -222
space.py CHANGED
@@ -1,222 +1,222 @@
1
-
2
- import gradio as gr
3
- from app import demo as app
4
- import os
5
-
6
- _docs = {'VideoSlider': {'description': 'A custom Gradio component to display a side-by-side video comparison with a slider.\nIt can be used as both an input (uploading two videos) and an output (displaying two videos).', 'members': {'__init__': {'value': {'type': 'typing.Union[\n typing.Tuple[str | pathlib.Path, str | pathlib.Path],\n typing.Callable,\n NoneType,\n][\n typing.Tuple[str | pathlib.Path, str | pathlib.Path][\n str | pathlib.Path, str | pathlib.Path\n ],\n Callable,\n None,\n]', 'default': 'None', 'description': 'A tuple of two video file paths or URLs to display initially.'}, 'height': {'type': 'int | None', 'default': 'None', 'description': 'The height of the component in pixels.'}, 'width': {'type': 'int | None', 'default': 'None', 'description': 'The width of the component in pixels.'}, 'label': {'type': 'str | None', 'default': 'None', 'description': 'The label for this component.'}, 'every': {'type': 'float | None', 'default': 'None', 'description': None}, 'show_label': {'type': 'bool | None', 'default': 'None', 'description': None}, 'container': {'type': 'bool', 'default': 'True', 'description': None}, 'scale': {'type': 'int | None', 'default': 'None', 'description': None}, 'min_width': {'type': 'int', 'default': '160', 'description': None}, 'interactive': {'type': 'bool | None', 'default': 'None', 'description': 'If False, the component will be in display-only mode.'}, 'visible': {'type': 'bool', 'default': 'True', 'description': None}, 'elem_id': {'type': 'str | None', 'default': 'None', 'description': None}, 'elem_classes': {'type': 'typing.Union[typing.List[str], str, NoneType][\n typing.List[str][str], str, None\n]', 'default': 'None', 'description': None}, 'position': {'type': 'int', 'default': '50', 'description': 'The initial position of the slider, from 0 to 100.'}, 'show_download_button': {'type': 'bool', 'default': 'True', 'description': None}, 'show_fullscreen_button': {'type': 'bool', 'default': 'True', 'description': None}, 'autoplay': {'type': 'bool', 'default': 'False', 'description': 'If True, the videos will start playing automatically.'}, 'loop': {'type': 'bool', 'default': 'False', 'description': 'If True, the videos will loop when they finish.'}}, 'postprocess': {'value': {'type': 'typing.Optional[\n typing.Tuple[\n str | pathlib.Path | None, str | pathlib.Path | None\n ]\n][\n typing.Tuple[\n str | pathlib.Path | None, str | pathlib.Path | None\n ][str | pathlib.Path | None, str | pathlib.Path | None],\n None,\n]', 'description': None}}, 'preprocess': {'return': {'type': 'typing.Optional[\n typing.Tuple[\n str | pathlib.Path | None, str | pathlib.Path | None\n ]\n][\n typing.Tuple[\n str | pathlib.Path | None, str | pathlib.Path | None\n ][str | pathlib.Path | None, str | pathlib.Path | None],\n None,\n]', 'description': None}, 'value': None}}, 'events': {'change': {'type': None, 'default': None, 'description': 'Triggered when the value of the VideoSlider changes either because of user input (e.g. a user types in a textbox) OR because of a function update (e.g. an image receives a value from the output of an event trigger). See `.input()` for a listener that is only triggered by user input.'}, 'upload': {'type': None, 'default': None, 'description': 'This listener is triggered when the user uploads a file into the VideoSlider.'}, 'clear': {'type': None, 'default': None, 'description': 'This listener is triggered when the user clears the VideoSlider using the clear button for the component.'}}}, '__meta__': {'additional_interfaces': {}, 'user_fn_refs': {'VideoSlider': []}}}
7
-
8
- abs_path = os.path.join(os.path.dirname(__file__), "css.css")
9
-
10
- with gr.Blocks(
11
- css=abs_path,
12
- theme=gr.themes.Default(
13
- font_mono=[
14
- gr.themes.GoogleFont("Inconsolata"),
15
- "monospace",
16
- ],
17
- ),
18
- ) as demo:
19
- gr.Markdown(
20
- """
21
- # `gradio_videoslider`
22
-
23
- <div style="display: flex; gap: 7px;">
24
- <img alt="Static Badge" src="https://img.shields.io/badge/version%20-%200.0.1%20-%20orange">
25
- </div>
26
-
27
- VideoSlider Component for Gradio
28
- """, elem_classes=["md-custom"], header_links=True)
29
- app.render()
30
- gr.Markdown(
31
- """
32
- ## Installation
33
-
34
- ```bash
35
- pip install gradio_videoslider
36
- ```
37
-
38
- ## Usage
39
-
40
- ```python
41
- # In demo/app.py
42
- import gradio as gr
43
- from gradio_videoslider import VideoSlider
44
- import os
45
-
46
- # --- 1. DEFINE THE PATHS TO YOUR LOCAL VIDEOS ---
47
- #
48
- # IMPORTANT: Replace the values below with the paths to YOUR video files.
49
- #
50
- # Option A: Relative Path (if the video is in the same folder as this app.py)
51
- # video_path_1 = "video_antes.mp4"
52
- # video_path_2 = "video_depois.mp4"
53
- #
54
- # Option B: Absolute Path (the full path to the file on your computer)
55
- # Example for Windows:
56
- # video_path_1 = "C:\\Users\\YourName\\Videos\\my_video_1.mp4"
57
- #
58
- # Example for Linux/macOS:
59
- # video_path_1 = "/home/yourname/videos/my_video_1.mp4"
60
-
61
- # Set your file paths here:
62
- video_path_1 = "examples/SampleVideo 720x480.mp4"
63
- video_path_2 = "examples/SampleVideo 1280x720.mp4"
64
-
65
-
66
- # --- 2. FUNCTION FOR THE UPLOAD EXAMPLE (remains the same) ---
67
- def process_uploaded_videos(video_inputs):
68
- \"\"\"This function handles the uploaded videos.\"\"\"
69
- print("Received videos from upload:", video_inputs)
70
- return video_inputs
71
-
72
-
73
- # --- 3. GRADIO INTERFACE ---
74
- with gr.Blocks() as demo:
75
- gr.Markdown("# Video Slider Component Usage Examples")
76
- gr.Markdown("<span>💻 <a href='https://github.com/DEVAIEXP/gradio_component_videoslider'>Component GitHub Code</a></span>")
77
-
78
- with gr.Tabs():
79
- # --- TAB 1: UPLOAD EXAMPLE ---
80
- with gr.TabItem("1. Compare via Upload"):
81
- gr.Markdown("## Upload two videos to compare them side-by-side.")
82
- video_slider_input = VideoSlider(label="Your Videos", height=400, width=700)
83
- video_slider_output = VideoSlider(
84
- label="Video comparision",
85
- interactive=False,
86
- autoplay=True,
87
- loop=True,
88
- height=400,
89
- width=700
90
- )
91
- submit_btn = gr.Button("Submit")
92
- submit_btn.click(
93
- fn=process_uploaded_videos,
94
- inputs=[video_slider_input],
95
- outputs=[video_slider_output]
96
- )
97
-
98
- # --- TAB 2: LOCAL FILE EXAMPLE ---
99
- with gr.TabItem("2. Compare Local Files"):
100
- gr.Markdown("## Example with videos pre-loaded from your local disk.")
101
-
102
- # This is the key part: we pass a tuple of your local file paths to the `value` parameter.
103
- VideoSlider(
104
- label="Video comparision",
105
- value=(video_path_1, video_path_2),
106
- interactive=False,
107
- autoplay=True,
108
- loop=True,
109
- height=400,
110
- width=700
111
- )
112
-
113
- # Optional: A check to give a helpful error message if files are not found.
114
- if not os.path.exists(video_path_1) or not os.path.exists(video_path_2):
115
- print("---")
116
- print(f"WARNING: Could not find one or both video files.")
117
- print(f"Please make sure these paths are correct in your app.py file:")
118
- print(f" - '{os.path.abspath(video_path_1)}'")
119
- print(f" - '{os.path.abspath(video_path_2)}'")
120
- print("---")
121
-
122
- if __name__ == '__main__':
123
- demo.launch()
124
-
125
- ```
126
- """, elem_classes=["md-custom"], header_links=True)
127
-
128
-
129
- gr.Markdown("""
130
- ## `VideoSlider`
131
-
132
- ### Initialization
133
- """, elem_classes=["md-custom"], header_links=True)
134
-
135
- gr.ParamViewer(value=_docs["VideoSlider"]["members"]["__init__"], linkify=[])
136
-
137
-
138
- gr.Markdown("### Events")
139
- gr.ParamViewer(value=_docs["VideoSlider"]["events"], linkify=['Event'])
140
-
141
-
142
-
143
-
144
- gr.Markdown("""
145
-
146
- ### User function
147
-
148
- The impact on the users predict function varies depending on whether the component is used as an input or output for an event (or both).
149
-
150
- - When used as an Input, the component only impacts the input signature of the user function.
151
- - When used as an output, the component only impacts the return signature of the user function.
152
-
153
- The code snippet below is accurate in cases where the component is used as both an input and an output.
154
-
155
-
156
-
157
- ```python
158
- def predict(
159
- value: typing.Optional[
160
- typing.Tuple[
161
- str | pathlib.Path | None, str | pathlib.Path | None
162
- ]
163
- ][
164
- typing.Tuple[
165
- str | pathlib.Path | None, str | pathlib.Path | None
166
- ][str | pathlib.Path | None, str | pathlib.Path | None],
167
- None,
168
- ]
169
- ) -> typing.Optional[
170
- typing.Tuple[
171
- str | pathlib.Path | None, str | pathlib.Path | None
172
- ]
173
- ][
174
- typing.Tuple[
175
- str | pathlib.Path | None, str | pathlib.Path | None
176
- ][str | pathlib.Path | None, str | pathlib.Path | None],
177
- None,
178
- ]:
179
- return value
180
- ```
181
- """, elem_classes=["md-custom", "VideoSlider-user-fn"], header_links=True)
182
-
183
-
184
-
185
-
186
- demo.load(None, js=r"""function() {
187
- const refs = {};
188
- const user_fn_refs = {
189
- VideoSlider: [], };
190
- requestAnimationFrame(() => {
191
-
192
- Object.entries(user_fn_refs).forEach(([key, refs]) => {
193
- if (refs.length > 0) {
194
- const el = document.querySelector(`.${key}-user-fn`);
195
- if (!el) return;
196
- refs.forEach(ref => {
197
- el.innerHTML = el.innerHTML.replace(
198
- new RegExp("\\b"+ref+"\\b", "g"),
199
- `<a href="#h-${ref.toLowerCase()}">${ref}</a>`
200
- );
201
- })
202
- }
203
- })
204
-
205
- Object.entries(refs).forEach(([key, refs]) => {
206
- if (refs.length > 0) {
207
- const el = document.querySelector(`.${key}`);
208
- if (!el) return;
209
- refs.forEach(ref => {
210
- el.innerHTML = el.innerHTML.replace(
211
- new RegExp("\\b"+ref+"\\b", "g"),
212
- `<a href="#h-${ref.toLowerCase()}">${ref}</a>`
213
- );
214
- })
215
- }
216
- })
217
- })
218
- }
219
-
220
- """)
221
-
222
- demo.launch()
 
1
+
2
+ import gradio as gr
3
+ from app import demo as app
4
+ import os
5
+
6
+ _docs = {'VideoSlider': {'description': 'A custom Gradio component to display a side-by-side video comparison with a slider.\nIt can be used as both an input (uploading two videos) and an output (displaying two videos).', 'members': {'__init__': {'value': {'type': 'typing.Union[\n typing.Tuple[str | pathlib.Path, str | pathlib.Path],\n typing.Callable,\n NoneType,\n][\n typing.Tuple[str | pathlib.Path, str | pathlib.Path][\n str | pathlib.Path, str | pathlib.Path\n ],\n Callable,\n None,\n]', 'default': 'None', 'description': 'A tuple of two video file paths or URLs to display initially.'}, 'height': {'type': 'int | None', 'default': 'None', 'description': 'The height of the component in pixels.'}, 'width': {'type': 'int | None', 'default': 'None', 'description': 'The width of the component in pixels.'}, 'label': {'type': 'str | None', 'default': 'None', 'description': 'The label for this component.'}, 'every': {'type': 'float | None', 'default': 'None', 'description': None}, 'show_label': {'type': 'bool | None', 'default': 'None', 'description': None}, 'container': {'type': 'bool', 'default': 'True', 'description': None}, 'scale': {'type': 'int | None', 'default': 'None', 'description': None}, 'min_width': {'type': 'int', 'default': '160', 'description': None}, 'interactive': {'type': 'bool | None', 'default': 'None', 'description': 'If False, the component will be in display-only mode.'}, 'visible': {'type': 'bool', 'default': 'True', 'description': None}, 'elem_id': {'type': 'str | None', 'default': 'None', 'description': None}, 'elem_classes': {'type': 'typing.Union[typing.List[str], str, NoneType][\n typing.List[str][str], str, None\n]', 'default': 'None', 'description': None}, 'position': {'type': 'int', 'default': '50', 'description': 'The initial position of the slider, from 0 to 100.'}, 'show_download_button': {'type': 'bool', 'default': 'True', 'description': None}, 'show_fullscreen_button': {'type': 'bool', 'default': 'True', 'description': None}, 'autoplay': {'type': 'bool', 'default': 'False', 'description': 'If True, the videos will start playing automatically.'}, 'loop': {'type': 'bool', 'default': 'False', 'description': 'If True, the videos will loop when they finish.'}}, 'postprocess': {'value': {'type': 'typing.Optional[\n typing.Tuple[\n str | pathlib.Path | None, str | pathlib.Path | None\n ]\n][\n typing.Tuple[\n str | pathlib.Path | None, str | pathlib.Path | None\n ][str | pathlib.Path | None, str | pathlib.Path | None],\n None,\n]', 'description': None}}, 'preprocess': {'return': {'type': 'typing.Optional[\n typing.Tuple[\n str | pathlib.Path | None, str | pathlib.Path | None\n ]\n][\n typing.Tuple[\n str | pathlib.Path | None, str | pathlib.Path | None\n ][str | pathlib.Path | None, str | pathlib.Path | None],\n None,\n]', 'description': None}, 'value': None}}, 'events': {'change': {'type': None, 'default': None, 'description': 'Triggered when the value of the VideoSlider changes either because of user input (e.g. a user types in a textbox) OR because of a function update (e.g. an image receives a value from the output of an event trigger). See `.input()` for a listener that is only triggered by user input.'}, 'upload': {'type': None, 'default': None, 'description': 'This listener is triggered when the user uploads a file into the VideoSlider.'}, 'clear': {'type': None, 'default': None, 'description': 'This listener is triggered when the user clears the VideoSlider using the clear button for the component.'}}}, '__meta__': {'additional_interfaces': {}, 'user_fn_refs': {'VideoSlider': []}}}
7
+
8
+ abs_path = os.path.join(os.path.dirname(__file__), "css.css")
9
+
10
+ with gr.Blocks(
11
+ css=abs_path,
12
+ theme=gr.themes.Default(
13
+ font_mono=[
14
+ gr.themes.GoogleFont("Inconsolata"),
15
+ "monospace",
16
+ ],
17
+ ),
18
+ ) as demo:
19
+ gr.Markdown(
20
+ """
21
+ # `gradio_videoslider`
22
+
23
+ <div style="display: flex; gap: 7px;">
24
+ <img alt="Static Badge" src="https://img.shields.io/badge/version%20-%200.0.1%20-%20orange">
25
+ </div>
26
+
27
+ VideoSlider Component for Gradio
28
+ """, elem_classes=["md-custom"], header_links=True)
29
+ app.render()
30
+ gr.Markdown(
31
+ """
32
+ ## Installation
33
+
34
+ ```bash
35
+ pip install gradio_videoslider
36
+ ```
37
+
38
+ ## Usage
39
+
40
+ ```python
41
+ # In demo/app.py
42
+ import gradio as gr
43
+ from gradio_videoslider import VideoSlider
44
+ import os
45
+
46
+ # --- 1. DEFINE THE PATHS TO YOUR LOCAL VIDEOS ---
47
+ #
48
+ # IMPORTANT: Replace the values below with the paths to YOUR video files.
49
+ #
50
+ # Option A: Relative Path (if the video is in the same folder as this app.py)
51
+ # video_path_1 = "video_antes.mp4"
52
+ # video_path_2 = "video_depois.mp4"
53
+ #
54
+ # Option B: Absolute Path (the full path to the file on your computer)
55
+ # Example for Windows:
56
+ # video_path_1 = "C:\\Users\\YourName\\Videos\\my_video_1.mp4"
57
+ #
58
+ # Example for Linux/macOS:
59
+ # video_path_1 = "/home/yourname/videos/my_video_1.mp4"
60
+
61
+ # Set your file paths here:
62
+ video_path_1 = "src/examples/Samplevideo 720x480.mp4"
63
+ video_path_2 = "src/examples/SampleVideo 1280x720.mp4"
64
+
65
+
66
+ # --- 2. FUNCTION FOR THE UPLOAD EXAMPLE (remains the same) ---
67
+ def process_uploaded_videos(video_inputs):
68
+ \"\"\"This function handles the uploaded videos.\"\"\"
69
+ print("Received videos from upload:", video_inputs)
70
+ return video_inputs
71
+
72
+
73
+ # --- 3. GRADIO INTERFACE ---
74
+ with gr.Blocks() as demo:
75
+ gr.Markdown("# Video Slider Component Usage Examples")
76
+ gr.Markdown("<span>💻 <a href='https://github.com/DEVAIEXP/gradio_component_videoslider'>Component GitHub Code</a></span>")
77
+
78
+ with gr.Tabs():
79
+ # --- TAB 1: UPLOAD EXAMPLE ---
80
+ with gr.TabItem("1. Compare via Upload"):
81
+ gr.Markdown("## Upload two videos to compare them side-by-side.")
82
+ video_slider_input = VideoSlider(label="Your Videos", height=400, width=700)
83
+ video_slider_output = VideoSlider(
84
+ label="Video comparision",
85
+ interactive=False,
86
+ autoplay=True,
87
+ loop=True,
88
+ height=400,
89
+ width=700
90
+ )
91
+ submit_btn = gr.Button("Submit")
92
+ submit_btn.click(
93
+ fn=process_uploaded_videos,
94
+ inputs=[video_slider_input],
95
+ outputs=[video_slider_output]
96
+ )
97
+
98
+ # --- TAB 2: LOCAL FILE EXAMPLE ---
99
+ with gr.TabItem("2. Compare Local Files"):
100
+ gr.Markdown("## Example with videos pre-loaded from your local disk.")
101
+
102
+ # This is the key part: we pass a tuple of your local file paths to the `value` parameter.
103
+ VideoSlider(
104
+ label="Video comparision",
105
+ value=(video_path_1, video_path_2),
106
+ interactive=False,
107
+ autoplay=True,
108
+ loop=True,
109
+ height=400,
110
+ width=700
111
+ )
112
+
113
+ # Optional: A check to give a helpful error message if files are not found.
114
+ if not os.path.exists(video_path_1) or not os.path.exists(video_path_2):
115
+ print("---")
116
+ print(f"WARNING: Could not find one or both video files.")
117
+ print(f"Please make sure these paths are correct in your app.py file:")
118
+ print(f" - '{os.path.abspath(video_path_1)}'")
119
+ print(f" - '{os.path.abspath(video_path_2)}'")
120
+ print("---")
121
+
122
+ if __name__ == '__main__':
123
+ demo.launch()
124
+
125
+ ```
126
+ """, elem_classes=["md-custom"], header_links=True)
127
+
128
+
129
+ gr.Markdown("""
130
+ ## `VideoSlider`
131
+
132
+ ### Initialization
133
+ """, elem_classes=["md-custom"], header_links=True)
134
+
135
+ gr.ParamViewer(value=_docs["VideoSlider"]["members"]["__init__"], linkify=[])
136
+
137
+
138
+ gr.Markdown("### Events")
139
+ gr.ParamViewer(value=_docs["VideoSlider"]["events"], linkify=['Event'])
140
+
141
+
142
+
143
+
144
+ gr.Markdown("""
145
+
146
+ ### User function
147
+
148
+ The impact on the users predict function varies depending on whether the component is used as an input or output for an event (or both).
149
+
150
+ - When used as an Input, the component only impacts the input signature of the user function.
151
+ - When used as an output, the component only impacts the return signature of the user function.
152
+
153
+ The code snippet below is accurate in cases where the component is used as both an input and an output.
154
+
155
+
156
+
157
+ ```python
158
+ def predict(
159
+ value: typing.Optional[
160
+ typing.Tuple[
161
+ str | pathlib.Path | None, str | pathlib.Path | None
162
+ ]
163
+ ][
164
+ typing.Tuple[
165
+ str | pathlib.Path | None, str | pathlib.Path | None
166
+ ][str | pathlib.Path | None, str | pathlib.Path | None],
167
+ None,
168
+ ]
169
+ ) -> typing.Optional[
170
+ typing.Tuple[
171
+ str | pathlib.Path | None, str | pathlib.Path | None
172
+ ]
173
+ ][
174
+ typing.Tuple[
175
+ str | pathlib.Path | None, str | pathlib.Path | None
176
+ ][str | pathlib.Path | None, str | pathlib.Path | None],
177
+ None,
178
+ ]:
179
+ return value
180
+ ```
181
+ """, elem_classes=["md-custom", "VideoSlider-user-fn"], header_links=True)
182
+
183
+
184
+
185
+
186
+ demo.load(None, js=r"""function() {
187
+ const refs = {};
188
+ const user_fn_refs = {
189
+ VideoSlider: [], };
190
+ requestAnimationFrame(() => {
191
+
192
+ Object.entries(user_fn_refs).forEach(([key, refs]) => {
193
+ if (refs.length > 0) {
194
+ const el = document.querySelector(`.${key}-user-fn`);
195
+ if (!el) return;
196
+ refs.forEach(ref => {
197
+ el.innerHTML = el.innerHTML.replace(
198
+ new RegExp("\\b"+ref+"\\b", "g"),
199
+ `<a href="#h-${ref.toLowerCase()}">${ref}</a>`
200
+ );
201
+ })
202
+ }
203
+ })
204
+
205
+ Object.entries(refs).forEach(([key, refs]) => {
206
+ if (refs.length > 0) {
207
+ const el = document.querySelector(`.${key}`);
208
+ if (!el) return;
209
+ refs.forEach(ref => {
210
+ el.innerHTML = el.innerHTML.replace(
211
+ new RegExp("\\b"+ref+"\\b", "g"),
212
+ `<a href="#h-${ref.toLowerCase()}">${ref}</a>`
213
+ );
214
+ })
215
+ }
216
+ })
217
+ })
218
+ }
219
+
220
+ """)
221
+
222
+ demo.launch()