Skip to content

Commit e0403c4

Browse files
authored
Merge pull request #1874 from dev-protocol/feat/short-video-controlled
feat: update VideoFetch to use short-video-controlled
2 parents 2cfeec5 + 2b1323d commit e0403c4

File tree

2 files changed

+205
-30
lines changed

2 files changed

+205
-30
lines changed

src/ui/svelte/VideoFetch.svelte

Lines changed: 102 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
export let url
77
export let posterUrl
88
export let videoClass
9+
export let isControlled = false
910
11+
let isPaused = true
1012
let videoElement
1113
let mediaSource
1214
let sourceBuffers = {}
@@ -22,6 +24,7 @@
2224
onMount(() => {
2325
if (!url) return
2426
27+
isPaused = true
2528
mediaSource = new MediaSource()
2629
videoElement.src = URL.createObjectURL(mediaSource)
2730
mediaSource.addEventListener('sourceopen', onSourceOpen)
@@ -76,7 +79,11 @@
7679
7780
// Start MP4Box file processing
7881
mp4boxfile.start()
79-
videoElement.value?.play().catch((e) => console.error('Play error:', e))
82+
83+
if (!isControlled) {
84+
// If controlled, then it will play when clicked.
85+
togglePlay()
86+
}
8087
}
8188
8289
// Fired when a media segment is ready
@@ -158,7 +165,9 @@
158165
mp4boxfile.flush()
159166
maybeEndOfStream()
160167
// Start playback after all data is processed
161-
videoElement.play().catch((e) => console.error('Play error:', e))
168+
if (!isControlled) {
169+
togglePlay()
170+
}
162171
return
163172
}
164173
@@ -208,16 +217,96 @@
208217
}
209218
}
210219
}
220+
221+
function togglePlay() {
222+
if (!videoElement) {
223+
return
224+
}
225+
226+
if (videoElement?.paused) {
227+
videoElement
228+
?.play()
229+
.then(() => {
230+
isPaused = false
231+
})
232+
.catch((e) => console.error('Play error:', e))
233+
} else {
234+
videoElement?.pause()
235+
isPaused = true
236+
}
237+
}
211238
</script>
212239
213-
<video
214-
bind:this={videoElement}
215-
controlsList="nodownload"
216-
loop
217-
autoplay
218-
muted
219-
poster={posterUrl}
220-
class={videoClass}
221-
>
222-
<track kind="captions" />
223-
</video>
240+
<!-- svelte-ignore a11y_no_static_element_interactions -->
241+
<div class="relative m-0 h-full w-full cursor-pointer p-0">
242+
<video
243+
bind:this={videoElement}
244+
controlsList="nodownload"
245+
autoplay={!isControlled}
246+
muted
247+
loop
248+
poster={posterUrl}
249+
class={videoClass}
250+
>
251+
<track kind="captions" />
252+
</video>
253+
<!-- svelte-ignore a11y_consider_explicit_label -->
254+
<!-- svelte-ignore a11y_click_events_have_key_events -->
255+
{#if isControlled}
256+
<button
257+
type="button"
258+
class="absolute inset-0 m-auto flex size-1/2 items-center justify-center text-white opacity-60"
259+
on:click|preventDefault={togglePlay}
260+
>
261+
{#if isPaused}
262+
<svg
263+
class="h-full w-full"
264+
viewBox="0 0 49 56"
265+
fill="none"
266+
xmlns="http://www.w3.org/2000/svg"
267+
>
268+
<path
269+
d="M44.5 27.134C45.1667 27.5189 45.1667 28.4811 44.5 28.866L5.5 51.3827C4.83333 51.7676 4 51.2865 4 50.5167L4 5.48334C4 4.71354 4.83333 4.23241 5.5 4.61731L44.5 27.134Z"
270+
fill="white"
271+
/>
272+
<path
273+
d="M6.5 53.1147L45.5 30.5981C47.5 29.4434 47.5 26.5566 45.5 25.4019L6.5 2.88526C4.5 1.73056 2 3.17393 2 5.48334L2 50.5167C2 52.8261 4.49999 54.2694 6.5 53.1147Z"
274+
stroke="black"
275+
stroke-opacity="0.1"
276+
stroke-width="4"
277+
/>
278+
</svg>
279+
{:else}
280+
<svg
281+
class="h-full w-full"
282+
viewBox="0 0 56 56"
283+
fill="none"
284+
xmlns="http://www.w3.org/2000/svg"
285+
>
286+
<rect x="17" y="15" width="6" height="25" rx="1" fill="white" />
287+
<rect
288+
x="15"
289+
y="13"
290+
width="10"
291+
height="29"
292+
rx="3"
293+
stroke="black"
294+
stroke-opacity="0.1"
295+
stroke-width="4"
296+
/>
297+
<rect x="33" y="15" width="6" height="25" rx="1" fill="white" />
298+
<rect
299+
x="31"
300+
y="13"
301+
width="10"
302+
height="29"
303+
rx="3"
304+
stroke="black"
305+
stroke-opacity="0.1"
306+
stroke-width="4"
307+
/>
308+
</svg>
309+
{/if}
310+
</button>
311+
{/if}
312+
</div>

src/ui/vue/VideoFetch.vue

Lines changed: 103 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,29 @@
11
<script setup>
2-
import { onMounted, useTemplateRef } from 'vue'
32
import MP4Box from 'mp4box'
3+
import { onMounted, ref, useTemplateRef } from 'vue'
44
55
const props = defineProps({
6+
isControlled: {
7+
type: Boolean,
8+
default: false,
9+
required: true,
10+
},
611
url: {
712
type: String,
813
required: true,
914
},
1015
posterUrl: {
11-
type: String,
1216
default: '',
17+
type: String,
1318
},
1419
videoClass: {
15-
type: String,
1620
default: '',
21+
type: String,
1722
},
1823
})
1924
2025
// Refs and variables
26+
let isPaused = ref(true)
2127
const videoElement = useTemplateRef(`videoElement`)
2228
let mediaSource = null
2329
let sourceBuffers = {}
@@ -33,6 +39,7 @@ let isDownloading = false
3339
onMounted(() => {
3440
if (!props.url) return
3541
42+
isPaused.value = true
3643
mediaSource = new MediaSource()
3744
videoElement.value.src = URL.createObjectURL(mediaSource)
3845
mediaSource.addEventListener('sourceopen', onSourceOpen)
@@ -87,7 +94,11 @@ function setupMp4Box() {
8794
8895
// Start MP4Box file processing
8996
mp4boxfile.start()
90-
videoElement.value?.play().catch((e) => console.error('Play error:', e))
97+
98+
if (!props.isControlled) {
99+
// If controlled, then it will play when clicked.
100+
togglePlay()
101+
}
91102
}
92103
93104
// Fired when a media segment is ready
@@ -162,8 +173,10 @@ function downloadChunk() {
162173
if (nextRangeStart >= totalFileSize) {
163174
mp4boxfile.flush()
164175
maybeEndOfStream()
165-
// Start playback after all data is processed
166-
videoElement.value?.play().catch((e) => console.error('Play error:', e))
176+
if (!props.isControlled) {
177+
// If controlled, then it will play when clicked.
178+
togglePlay()
179+
}
167180
return
168181
}
169182
@@ -211,18 +224,91 @@ function maybeEndOfStream() {
211224
}
212225
}
213226
}
227+
228+
function togglePlay() {
229+
if (!videoElement.value) {
230+
return
231+
}
232+
233+
if (videoElement.value?.paused) {
234+
videoElement.value
235+
?.play()
236+
.then(() => {
237+
isPaused.value = false
238+
})
239+
.catch((e) => console.error('Play error:', e))
240+
} else {
241+
videoElement.value?.pause()
242+
isPaused.value = true
243+
}
244+
}
214245
</script>
215246
216247
<template>
217-
<video
218-
ref="videoElement"
219-
controlsList="nodownload"
220-
autoplay
221-
muted
222-
loop
223-
:poster="posterUrl"
224-
:class="videoClass"
225-
>
226-
<track kind="captions" />
227-
</video>
248+
<div class="relative m-0 h-full w-full cursor-pointer p-0">
249+
<video
250+
ref="videoElement"
251+
controlsList="nodownload"
252+
:autoplay="!isControlled"
253+
muted
254+
loop
255+
:poster="posterUrl"
256+
:class="videoClass"
257+
>
258+
<track kind="captions" />
259+
</video>
260+
<div
261+
v-if="isControlled"
262+
class="absolute inset-0 m-auto flex size-1/2 items-center justify-center text-white opacity-60"
263+
@click.stop.prevent="togglePlay"
264+
>
265+
<svg
266+
v-if="isPaused"
267+
className="w-full h-full"
268+
viewBox="0 0 49 56"
269+
fill="none"
270+
xmlns="http://www.w3.org/2000/svg"
271+
>
272+
<path
273+
d="M44.5 27.134C45.1667 27.5189 45.1667 28.4811 44.5 28.866L5.5 51.3827C4.83333 51.7676 4 51.2865 4 50.5167L4 5.48334C4 4.71354 4.83333 4.23241 5.5 4.61731L44.5 27.134Z"
274+
fill="white"
275+
/>
276+
<path
277+
d="M6.5 53.1147L45.5 30.5981C47.5 29.4434 47.5 26.5566 45.5 25.4019L6.5 2.88526C4.5 1.73056 2 3.17393 2 5.48334L2 50.5167C2 52.8261 4.49999 54.2694 6.5 53.1147Z"
278+
stroke="black"
279+
stroke-opacity="0.1"
280+
stroke-width="4"
281+
/>
282+
</svg>
283+
<svg
284+
v-else
285+
viewBox="0 0 56 56"
286+
fill="none"
287+
xmlns="http://www.w3.org/2000/svg"
288+
>
289+
<rect x="17" y="15" width="6" height="25" rx="1" fill="white" />
290+
<rect
291+
x="15"
292+
y="13"
293+
width="10"
294+
height="29"
295+
rx="3"
296+
stroke="black"
297+
stroke-opacity="0.1"
298+
stroke-width="4"
299+
/>
300+
<rect x="33" y="15" width="6" height="25" rx="1" fill="white" />
301+
<rect
302+
x="31"
303+
y="13"
304+
width="10"
305+
height="29"
306+
rx="3"
307+
stroke="black"
308+
stroke-opacity="0.1"
309+
stroke-width="4"
310+
/>
311+
</svg>
312+
</div>
313+
</div>
228314
</template>

0 commit comments

Comments
 (0)