Skip to content

Commit

Permalink
🐛 (video) Parse youtube start time query param
Browse files Browse the repository at this point in the history
Closes #1589
  • Loading branch information
baptisteArno committed Jun 24, 2024
1 parent 9c27ca9 commit b10383e
Show file tree
Hide file tree
Showing 8 changed files with 42 additions and 5 deletions.
18 changes: 18 additions & 0 deletions apps/docs/editor/blocks/bubbles/video.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,21 @@ The Video bubble block allows you to display a video to your user. You can paste
></video>
</Tab>
</Tabs>

## Video service detection

When you paste a video URL, Typbot will automatically detect the video service and parse it with the proper iframe settings. It currently works with:

- YouTube (video and shorts)
- Vimeo
- TikTok
- Gumlet
- OneDrive

Feel free to [suggest a missing service in the feedback board](https://feedback.typebot.io/).

For missing services, you can instead add an Embed bubble and paste the iframe code.

### Limitations

- YouTube clips are not supported as we can't transform it to embed URL automatically. To embed a YouTube clip, you can use the [Embed bubble](/editor/blocks/bubbles/embed) and paste the iframe code that can be found in Youtube under the "Share" > "Embed" button.
2 changes: 1 addition & 1 deletion packages/embeds/js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@typebot.io/js",
"version": "0.2.91",
"version": "0.2.92",
"description": "Javascript library to display typebots on your website",
"type": "module",
"main": "dist/index.js",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,9 @@ export const VideoBubble = (props: Props) => {
embedBaseUrls[
props.content?.type as EmbeddableVideoBubbleContentType
]
}/${props.content?.id}`}
}/${props.content?.id ?? ''}${
props.content?.queryParamsStr ?? ''
}`}
class={'w-full h-full'}
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen
Expand Down
2 changes: 1 addition & 1 deletion packages/embeds/nextjs/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@typebot.io/nextjs",
"version": "0.2.91",
"version": "0.2.92",
"description": "Convenient library to display typebots on your Next.js website",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion packages/embeds/react/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@typebot.io/react",
"version": "0.2.91",
"version": "0.2.92",
"description": "Convenient library to display typebots on your React app",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
6 changes: 5 additions & 1 deletion packages/schemas/features/blocks/bubbles/video/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ export const verticalVideoSuggestionSize = {

const youtubeBaseUrl = 'https://www.youtube.com/embed'
export const youtubeRegex =
/youtube\.com\/(watch\?v=|shorts\/)([\w-]+)|youtu\.be\/([\w-]+)/
/youtube\.com\/(watch\?v=|shorts\/)([\w-]+)|youtu\.be\/([\w-]+)(\?.+)/

export const youtubeEmbedParamsMap = {
t: 'start',
}

const vimeoBaseUrl = 'https://player.vimeo.com/video'
export const vimeoRegex = /vimeo\.com\/(\d+)/
Expand Down
12 changes: 12 additions & 0 deletions packages/schemas/features/blocks/bubbles/video/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
tiktokRegex,
gumletRegex,
oneDriveRegex,
youtubeEmbedParamsMap,
} from './constants'
import { VideoBubbleBlock } from './schema'

Expand All @@ -16,6 +17,7 @@ export const parseVideoUrl = (
type: VideoBubbleContentType
url: string
id?: string
queryParamsStr?: string
videoSizeSuggestion?: Pick<
NonNullable<VideoBubbleBlock['content']>,
'aspectRatio' | 'maxWidth'
Expand All @@ -24,12 +26,22 @@ export const parseVideoUrl = (
if (youtubeRegex.test(url)) {
const match = url.match(youtubeRegex)
const id = match?.at(2) ?? match?.at(3)
const queryParams = match?.at(4)
? new URLSearchParams(match.at(4))
: undefined
Object.entries(youtubeEmbedParamsMap).forEach(([key, value]) => {
if (queryParams?.has(key)) {
queryParams.set(value, queryParams.get(key)!)
queryParams.delete(key)
}
})
const parsedUrl = match?.at(0) ?? url
if (!id) return { type: VideoBubbleContentType.URL, url: parsedUrl }
return {
type: VideoBubbleContentType.YOUTUBE,
url: parsedUrl,
id,
queryParamsStr: queryParams ? '?' + queryParams.toString() : undefined,
videoSizeSuggestion: url.includes('shorts')
? verticalVideoSuggestionSize
: horizontalVideoSuggestionSize,
Expand Down
1 change: 1 addition & 0 deletions packages/schemas/features/blocks/bubbles/video/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const videoBubbleContentSchema = z.object({
height: z.number().or(variableStringSchema).optional(),
aspectRatio: z.string().optional(),
maxWidth: z.string().optional(),
queryParamsStr: z.string().optional(),
})

export const videoBubbleBlockSchema = blockBaseSchema.merge(
Expand Down

0 comments on commit b10383e

Please sign in to comment.