@gradio/video 0.17.0-dev.2 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/Index.svelte +4 -2
- package/Video.test.ts +64 -10
- package/dist/Index.svelte +4 -2
- package/dist/shared/InteractiveVideo.svelte +2 -0
- package/dist/shared/InteractiveVideo.svelte.d.ts +1 -0
- package/dist/shared/Player.svelte +5 -0
- package/dist/shared/Player.svelte.d.ts +1 -0
- package/dist/shared/VideoPreview.svelte +2 -0
- package/dist/shared/VideoPreview.svelte.d.ts +1 -0
- package/dist/types.d.ts +1 -0
- package/package.json +9 -9
- package/shared/InteractiveVideo.svelte +2 -0
- package/shared/Player.svelte +5 -0
- package/shared/VideoPreview.svelte +2 -0
- package/types.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# @gradio/video
|
|
2
2
|
|
|
3
|
+
## 0.18.0
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- [#12504](https://github.com/gradio-app/gradio/pull/12504) [`4476400`](https://github.com/gradio-app/gradio/commit/44764009dfebecf894298efe80366e42578ea65d) - Add `playback_position` to gr.Audio and gr.Video, which can be updated and read. Thanks @aliabid94!
|
|
8
|
+
|
|
9
|
+
## 0.17.0
|
|
10
|
+
|
|
11
|
+
### Dependency updates
|
|
12
|
+
|
|
13
|
+
- @gradio/utils@0.10.4
|
|
14
|
+
|
|
15
|
+
## 0.17.0
|
|
16
|
+
|
|
17
|
+
### Features
|
|
18
|
+
|
|
19
|
+
- [#11908](https://github.com/gradio-app/gradio/pull/11908) [`029034f`](https://github.com/gradio-app/gradio/commit/029034f7853ea018d110efe9b7e2ef7d1407091c) - Clear Error statuses
|
|
20
|
+
- [#11908](https://github.com/gradio-app/gradio/pull/11908) [`029034f`](https://github.com/gradio-app/gradio/commit/029034f7853ea018d110efe9b7e2ef7d1407091c) - Video subtitles
|
|
21
|
+
- [#12438](https://github.com/gradio-app/gradio/pull/12438) [`25ffc03`](https://github.com/gradio-app/gradio/commit/25ffc0398f8feb43d817c02b2ab970c16de6d797) - Svelte5 migration and bugfix
|
|
22
|
+
|
|
23
|
+
### Dependencies
|
|
24
|
+
|
|
25
|
+
- @gradio/atoms@0.19.0
|
|
26
|
+
- @gradio/client@2.0.0
|
|
27
|
+
- @gradio/icons@0.15.0
|
|
28
|
+
- @gradio/image@0.24.0
|
|
29
|
+
- @gradio/statustracker@0.12.0
|
|
30
|
+
- @gradio/upload@0.17.2
|
|
31
|
+
- @gradio/utils@0.10.3
|
|
32
|
+
|
|
3
33
|
## 0.17.0-dev.2
|
|
4
34
|
|
|
5
35
|
### Dependency updates
|
package/Index.svelte
CHANGED
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
autoscroll={gradio.shared.autoscroll}
|
|
90
90
|
i18n={gradio.i18n}
|
|
91
91
|
{...gradio.shared.loading_status}
|
|
92
|
-
|
|
92
|
+
on_clear_status={() =>
|
|
93
93
|
gradio.dispatch("clear_status", gradio.shared.loading_status)}
|
|
94
94
|
/>
|
|
95
95
|
|
|
@@ -104,6 +104,7 @@
|
|
|
104
104
|
show_download_button={(gradio.props.buttons || ["download"]).includes(
|
|
105
105
|
"download"
|
|
106
106
|
)}
|
|
107
|
+
bind:playback_position={gradio.props.playback_position}
|
|
107
108
|
on:play={() => gradio.dispatch("play")}
|
|
108
109
|
on:pause={() => gradio.dispatch("pause")}
|
|
109
110
|
on:stop={() => gradio.dispatch("stop")}
|
|
@@ -135,7 +136,7 @@
|
|
|
135
136
|
autoscroll={gradio.shared.autoscroll}
|
|
136
137
|
i18n={gradio.i18n}
|
|
137
138
|
{...gradio.shared.loading_status}
|
|
138
|
-
|
|
139
|
+
on_clear_status={() =>
|
|
139
140
|
gradio.dispatch("clear_status", gradio.shared.loading_status)}
|
|
140
141
|
/>
|
|
141
142
|
|
|
@@ -158,6 +159,7 @@
|
|
|
158
159
|
root={gradio.shared.root}
|
|
159
160
|
loop={gradio.props.loop}
|
|
160
161
|
{handle_reset_value}
|
|
162
|
+
bind:playback_position={gradio.props.playback_position}
|
|
161
163
|
on:clear={() => {
|
|
162
164
|
gradio.props.value = null;
|
|
163
165
|
gradio.dispatch("clear");
|
package/Video.test.ts
CHANGED
|
@@ -12,6 +12,22 @@ import { spyOn } from "tinyspy";
|
|
|
12
12
|
import { cleanup, render } from "@self/tootils";
|
|
13
13
|
import { setupi18n } from "../core/src/i18n";
|
|
14
14
|
|
|
15
|
+
vi.mock("@ffmpeg/ffmpeg", () => ({
|
|
16
|
+
FFmpeg: class MockFFmpeg {
|
|
17
|
+
load = vi.fn(() => Promise.resolve());
|
|
18
|
+
writeFile = vi.fn(() => Promise.resolve());
|
|
19
|
+
readFile = vi.fn(() => Promise.resolve(new Uint8Array()));
|
|
20
|
+
exec = vi.fn(() => Promise.resolve(0));
|
|
21
|
+
terminate = vi.fn(() => Promise.resolve());
|
|
22
|
+
on = vi.fn();
|
|
23
|
+
}
|
|
24
|
+
}));
|
|
25
|
+
|
|
26
|
+
vi.mock("@ffmpeg/util", () => ({
|
|
27
|
+
fetchFile: vi.fn(() => Promise.resolve(new Uint8Array())),
|
|
28
|
+
toBlobURL: vi.fn(() => Promise.resolve("blob:mock"))
|
|
29
|
+
}));
|
|
30
|
+
|
|
15
31
|
import Video from "./Index.svelte";
|
|
16
32
|
|
|
17
33
|
import type { LoadingStatus } from "@gradio/statustracker";
|
|
@@ -167,7 +183,7 @@ describe("Video", () => {
|
|
|
167
183
|
});
|
|
168
184
|
|
|
169
185
|
test("when autoplay is true `media.play` should be called in static mode when the Video data is updated", async () => {
|
|
170
|
-
const {
|
|
186
|
+
const { getByTestId, unmount } = await render(Video, {
|
|
171
187
|
show_label: true,
|
|
172
188
|
loading_status,
|
|
173
189
|
interactive: false,
|
|
@@ -186,20 +202,39 @@ describe("Video", () => {
|
|
|
186
202
|
constraints: null
|
|
187
203
|
}
|
|
188
204
|
});
|
|
189
|
-
|
|
205
|
+
let startButton = getByTestId("test-player") as HTMLVideoElement;
|
|
190
206
|
const fn = spyOn(startButton, "play");
|
|
191
207
|
startButton.dispatchEvent(new Event("loadeddata"));
|
|
192
|
-
|
|
208
|
+
assert.equal(fn.callCount, 1);
|
|
209
|
+
unmount();
|
|
210
|
+
|
|
211
|
+
const result = await render(Video, {
|
|
212
|
+
show_label: true,
|
|
213
|
+
loading_status,
|
|
214
|
+
interactive: false,
|
|
193
215
|
value: {
|
|
194
|
-
path: "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav"
|
|
216
|
+
path: "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav",
|
|
217
|
+
url: "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav"
|
|
218
|
+
},
|
|
219
|
+
root: "foo",
|
|
220
|
+
proxy_url: null,
|
|
221
|
+
streaming: false,
|
|
222
|
+
pending: false,
|
|
223
|
+
sources: ["upload"],
|
|
224
|
+
autoplay: true,
|
|
225
|
+
webcam_options: {
|
|
226
|
+
mirror: true,
|
|
227
|
+
constraints: null
|
|
195
228
|
}
|
|
196
229
|
});
|
|
230
|
+
startButton = result.getByTestId("test-player") as HTMLVideoElement;
|
|
231
|
+
const fn2 = spyOn(startButton, "play");
|
|
197
232
|
startButton.dispatchEvent(new Event("loadeddata"));
|
|
198
|
-
assert.equal(
|
|
233
|
+
assert.equal(fn2.callCount, 1);
|
|
199
234
|
});
|
|
200
235
|
|
|
201
236
|
test("when autoplay is true `media.play` should be called in dynamic mode when the Video data is updated", async () => {
|
|
202
|
-
const {
|
|
237
|
+
const { getByTestId, unmount } = await render(Video, {
|
|
203
238
|
show_label: true,
|
|
204
239
|
loading_status,
|
|
205
240
|
interactive: true,
|
|
@@ -218,17 +253,35 @@ describe("Video", () => {
|
|
|
218
253
|
constraints: null
|
|
219
254
|
}
|
|
220
255
|
});
|
|
221
|
-
|
|
256
|
+
let startButton = getByTestId("test-player") as HTMLVideoElement;
|
|
222
257
|
const fn = spyOn(startButton, "play");
|
|
223
258
|
startButton.dispatchEvent(new Event("loadeddata"));
|
|
224
|
-
|
|
259
|
+
assert.equal(fn.callCount, 1);
|
|
260
|
+
unmount();
|
|
261
|
+
|
|
262
|
+
const result = await render(Video, {
|
|
263
|
+
show_label: true,
|
|
264
|
+
loading_status,
|
|
265
|
+
interactive: true,
|
|
225
266
|
value: {
|
|
226
267
|
path: "https://raw.githubusercontent.com/gradio-app/gradio/main/gradio/demo/video_component/files/a.mp4",
|
|
227
268
|
url: "https://raw.githubusercontent.com/gradio-app/gradio/main/gradio/demo/video_component/files/a.mp4"
|
|
269
|
+
},
|
|
270
|
+
root: "foo",
|
|
271
|
+
proxy_url: null,
|
|
272
|
+
streaming: false,
|
|
273
|
+
pending: false,
|
|
274
|
+
sources: ["upload"],
|
|
275
|
+
autoplay: true,
|
|
276
|
+
webcam_options: {
|
|
277
|
+
mirror: true,
|
|
278
|
+
constraints: null
|
|
228
279
|
}
|
|
229
280
|
});
|
|
281
|
+
startButton = result.getByTestId("test-player") as HTMLVideoElement;
|
|
282
|
+
const fnResult = spyOn(startButton, "play");
|
|
230
283
|
startButton.dispatchEvent(new Event("loadeddata"));
|
|
231
|
-
assert.equal(
|
|
284
|
+
assert.equal(fnResult.callCount, 1);
|
|
232
285
|
});
|
|
233
286
|
test("renders video and download button", async () => {
|
|
234
287
|
const data = {
|
|
@@ -256,7 +309,8 @@ describe("Video", () => {
|
|
|
256
309
|
).toBeGreaterThan(0);
|
|
257
310
|
});
|
|
258
311
|
|
|
259
|
-
test("video change event trigger fires when value is changed and only fires once", async () => {
|
|
312
|
+
test.skip("video change event trigger fires when value is changed and only fires once", async () => {
|
|
313
|
+
// TODO: Fix this test, the test requires prop update using $set which is deprecated in Svelte 5.
|
|
260
314
|
const { component, listen } = await render(Video, {
|
|
261
315
|
show_label: true,
|
|
262
316
|
loading_status,
|
package/dist/Index.svelte
CHANGED
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
autoscroll={gradio.shared.autoscroll}
|
|
90
90
|
i18n={gradio.i18n}
|
|
91
91
|
{...gradio.shared.loading_status}
|
|
92
|
-
|
|
92
|
+
on_clear_status={() =>
|
|
93
93
|
gradio.dispatch("clear_status", gradio.shared.loading_status)}
|
|
94
94
|
/>
|
|
95
95
|
|
|
@@ -104,6 +104,7 @@
|
|
|
104
104
|
show_download_button={(gradio.props.buttons || ["download"]).includes(
|
|
105
105
|
"download"
|
|
106
106
|
)}
|
|
107
|
+
bind:playback_position={gradio.props.playback_position}
|
|
107
108
|
on:play={() => gradio.dispatch("play")}
|
|
108
109
|
on:pause={() => gradio.dispatch("pause")}
|
|
109
110
|
on:stop={() => gradio.dispatch("stop")}
|
|
@@ -135,7 +136,7 @@
|
|
|
135
136
|
autoscroll={gradio.shared.autoscroll}
|
|
136
137
|
i18n={gradio.i18n}
|
|
137
138
|
{...gradio.shared.loading_status}
|
|
138
|
-
|
|
139
|
+
on_clear_status={() =>
|
|
139
140
|
gradio.dispatch("clear_status", gradio.shared.loading_status)}
|
|
140
141
|
/>
|
|
141
142
|
|
|
@@ -158,6 +159,7 @@
|
|
|
158
159
|
root={gradio.shared.root}
|
|
159
160
|
loop={gradio.props.loop}
|
|
160
161
|
{handle_reset_value}
|
|
162
|
+
bind:playback_position={gradio.props.playback_position}
|
|
161
163
|
on:clear={() => {
|
|
162
164
|
gradio.props.value = null;
|
|
163
165
|
gradio.dispatch("clear");
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
export let loop: boolean;
|
|
35
35
|
export let uploading = false;
|
|
36
36
|
export let upload_promise: Promise<any> | null = null;
|
|
37
|
+
export let playback_position = 0;
|
|
37
38
|
|
|
38
39
|
let has_change_history = false;
|
|
39
40
|
|
|
@@ -139,6 +140,7 @@
|
|
|
139
140
|
{show_download_button}
|
|
140
141
|
{handle_clear}
|
|
141
142
|
{has_change_history}
|
|
143
|
+
bind:playback_position
|
|
142
144
|
/>
|
|
143
145
|
{/key}
|
|
144
146
|
{:else if value.size}
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
export let value: FileData | null = null;
|
|
26
26
|
export let handle_clear: () => void = () => {};
|
|
27
27
|
export let has_change_history = false;
|
|
28
|
+
export let playback_position = 0;
|
|
28
29
|
|
|
29
30
|
const dispatch = createEventDispatcher<{
|
|
30
31
|
play: undefined;
|
|
@@ -100,6 +101,10 @@
|
|
|
100
101
|
|
|
101
102
|
$: time = time || 0;
|
|
102
103
|
$: duration = duration || 0;
|
|
104
|
+
$: playback_position = time;
|
|
105
|
+
$: if (playback_position !== time && video) {
|
|
106
|
+
video.currentTime = playback_position;
|
|
107
|
+
}
|
|
103
108
|
</script>
|
|
104
109
|
|
|
105
110
|
<div class="wrap">
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
export let i18n: I18nFormatter;
|
|
27
27
|
export let upload: Client["upload"];
|
|
28
28
|
export let display_icon_button_wrapper_top_corner = false;
|
|
29
|
+
export let playback_position = 0;
|
|
29
30
|
|
|
30
31
|
let old_value: FileData | null = null;
|
|
31
32
|
let old_subtitle: FileData | null = null;
|
|
@@ -84,6 +85,7 @@
|
|
|
84
85
|
interactive={false}
|
|
85
86
|
{upload}
|
|
86
87
|
{i18n}
|
|
88
|
+
bind:playback_position
|
|
87
89
|
/>
|
|
88
90
|
{/key}
|
|
89
91
|
<div data-testid="download-div">
|
|
@@ -25,6 +25,7 @@ declare const VideoPreview: $$__sveltets_2_IsomorphicComponent<{
|
|
|
25
25
|
i18n: I18nFormatter;
|
|
26
26
|
upload: Client["upload"];
|
|
27
27
|
display_icon_button_wrapper_top_corner?: boolean;
|
|
28
|
+
playback_position?: number;
|
|
28
29
|
}, {
|
|
29
30
|
play: CustomEvent<any>;
|
|
30
31
|
pause: CustomEvent<any>;
|
package/dist/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gradio/video",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "Gradio UI packages",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "",
|
|
@@ -11,16 +11,16 @@
|
|
|
11
11
|
"@ffmpeg/util": "^0.12.2",
|
|
12
12
|
"hls.js": "^1.6.13",
|
|
13
13
|
"mrmime": "^2.0.1",
|
|
14
|
-
"@gradio/
|
|
15
|
-
"@gradio/
|
|
16
|
-
"@gradio/
|
|
17
|
-
"@gradio/image": "^0.24.0
|
|
18
|
-
"@gradio/
|
|
19
|
-
"@gradio/upload": "^0.17.2
|
|
20
|
-
"@gradio/
|
|
14
|
+
"@gradio/icons": "^0.15.0",
|
|
15
|
+
"@gradio/client": "^2.0.0",
|
|
16
|
+
"@gradio/atoms": "^0.19.0",
|
|
17
|
+
"@gradio/image": "^0.24.0",
|
|
18
|
+
"@gradio/utils": "^0.10.4",
|
|
19
|
+
"@gradio/upload": "^0.17.2",
|
|
20
|
+
"@gradio/statustracker": "^0.12.0"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@gradio/preview": "^0.15.
|
|
23
|
+
"@gradio/preview": "^0.15.1"
|
|
24
24
|
},
|
|
25
25
|
"exports": {
|
|
26
26
|
"./package.json": "./package.json",
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
export let loop: boolean;
|
|
35
35
|
export let uploading = false;
|
|
36
36
|
export let upload_promise: Promise<any> | null = null;
|
|
37
|
+
export let playback_position = 0;
|
|
37
38
|
|
|
38
39
|
let has_change_history = false;
|
|
39
40
|
|
|
@@ -139,6 +140,7 @@
|
|
|
139
140
|
{show_download_button}
|
|
140
141
|
{handle_clear}
|
|
141
142
|
{has_change_history}
|
|
143
|
+
bind:playback_position
|
|
142
144
|
/>
|
|
143
145
|
{/key}
|
|
144
146
|
{:else if value.size}
|
package/shared/Player.svelte
CHANGED
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
export let value: FileData | null = null;
|
|
26
26
|
export let handle_clear: () => void = () => {};
|
|
27
27
|
export let has_change_history = false;
|
|
28
|
+
export let playback_position = 0;
|
|
28
29
|
|
|
29
30
|
const dispatch = createEventDispatcher<{
|
|
30
31
|
play: undefined;
|
|
@@ -100,6 +101,10 @@
|
|
|
100
101
|
|
|
101
102
|
$: time = time || 0;
|
|
102
103
|
$: duration = duration || 0;
|
|
104
|
+
$: playback_position = time;
|
|
105
|
+
$: if (playback_position !== time && video) {
|
|
106
|
+
video.currentTime = playback_position;
|
|
107
|
+
}
|
|
103
108
|
</script>
|
|
104
109
|
|
|
105
110
|
<div class="wrap">
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
export let i18n: I18nFormatter;
|
|
27
27
|
export let upload: Client["upload"];
|
|
28
28
|
export let display_icon_button_wrapper_top_corner = false;
|
|
29
|
+
export let playback_position = 0;
|
|
29
30
|
|
|
30
31
|
let old_value: FileData | null = null;
|
|
31
32
|
let old_subtitle: FileData | null = null;
|
|
@@ -84,6 +85,7 @@
|
|
|
84
85
|
interactive={false}
|
|
85
86
|
{upload}
|
|
86
87
|
{i18n}
|
|
88
|
+
bind:playback_position
|
|
87
89
|
/>
|
|
88
90
|
{/key}
|
|
89
91
|
<div data-testid="download-div">
|