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
Media elements improvements #8203
Changes from all commits
e7ec9da
8396ef5
cdef7b9
2065a4d
d5f5e67
22e1d2b
7dcd853
b8e1eaa
a54605d
dd723c7
a24eb2c
944c79a
2b62e18
ff72890
a9d2e33
dff537e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -41,7 +41,7 @@ export default function Video({ | |||
|
||||
/* Element may contain "url" or "data" property. */ | ||||
|
||||
const { type, url, startTime, subtitles } = element | ||||
const { type, url, startTime, subtitles, endTime, loop } = element | ||||
|
||||
// Handle startTime changes | ||||
useEffect(() => { | ||||
|
@@ -55,7 +55,6 @@ export default function Video({ | |||
|
||||
const setStartTime: () => void = () => { | ||||
if (videoNode) { | ||||
// setStartTime | ||||
videoNode.currentTime = element.startTime | ||||
} | ||||
} | ||||
|
@@ -71,12 +70,82 @@ export default function Video({ | |||
} | ||||
}, [element]) | ||||
|
||||
// Stop the video at 'endTime' and handle loop | ||||
useEffect(() => { | ||||
const videoNode = videoRef.current | ||||
if (!videoNode) return | ||||
|
||||
// Flag to avoid calling 'videoNode.pause()' multiple times | ||||
let stoppedByEndTime = false | ||||
|
||||
const handleTimeUpdate = (): void => { | ||||
if (endTime > 0 && videoNode.currentTime >= endTime) { | ||||
if (loop) { | ||||
// If loop is true and we reached 'endTime', reset to 'startTime' | ||||
videoNode.currentTime = startTime || 0 | ||||
videoNode.play() | ||||
} else if (!stoppedByEndTime) { | ||||
stoppedByEndTime = true | ||||
videoNode.pause() | ||||
} | ||||
} | ||||
} | ||||
|
||||
if (endTime > 0) { | ||||
videoNode.addEventListener("timeupdate", handleTimeUpdate) | ||||
} | ||||
|
||||
return () => { | ||||
if (videoNode && endTime > 0) { | ||||
videoNode.removeEventListener("timeupdate", handleTimeUpdate) | ||||
} | ||||
} | ||||
}, [endTime, loop, startTime]) | ||||
|
||||
// Handle looping the video | ||||
useEffect(() => { | ||||
const videoNode = videoRef.current | ||||
if (!videoNode) return | ||||
|
||||
// Loop the video when it has ended | ||||
const handleVideoEnd = (): void => { | ||||
if (loop) { | ||||
videoNode.currentTime = startTime || 0 // Reset to startTime or to the start if not specified | ||||
videoNode.play() | ||||
} | ||||
} | ||||
|
||||
videoNode.addEventListener("ended", handleVideoEnd) | ||||
|
||||
return () => { | ||||
if (videoNode) { | ||||
videoNode.removeEventListener("ended", handleVideoEnd) | ||||
} | ||||
} | ||||
}, [loop, startTime]) | ||||
|
||||
const getYoutubeSrc = (url: string): string => { | ||||
const { startTime } = element | ||||
if (startTime) { | ||||
return `${url}?start=${startTime}` | ||||
const { startTime, endTime, loop } = element | ||||
const youtubeUrl = new URL(url) | ||||
|
||||
if (startTime && !isNaN(startTime)) { | ||||
youtubeUrl.searchParams.append("start", startTime.toString()) | ||||
} | ||||
|
||||
if (endTime && !isNaN(endTime)) { | ||||
youtubeUrl.searchParams.append("end", endTime.toString()) | ||||
} | ||||
|
||||
if (loop) { | ||||
youtubeUrl.searchParams.append("loop", "1") | ||||
// When using the loop parameter, YouTube requires the playlist parameter to be set to the same video ID | ||||
const videoId = youtubeUrl.pathname.split("/").pop() | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does that work for all the different types of youtube URLs? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It should work with different youtube URLs, because we standardize URL on the backend streamlit/lib/streamlit/elements/media.py Line 268 in e1960fb
|
||||
|
||||
if (videoId) { | ||||
youtubeUrl.searchParams.append("playlist", videoId) | ||||
} | ||||
} | ||||
return url | ||||
return youtubeUrl.toString() | ||||
} | ||||
|
||||
/* Is this a YouTube link? If so we need a fancier tag. | ||||
|
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.
interesting :) didn't know this trick 👍