Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 58 additions & 1 deletion apps/web/__tests__/unit/share-video-metadata.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ describe("share video metadata", () => {
name: "Product demo",
sourceType: "desktopMP4",
webUrl: "https://cap.so",
width: null,
height: null,
advertiseIframelyPlayer: true,
});

Expand Down Expand Up @@ -84,7 +86,7 @@ describe("share video metadata", () => {
rel: "iframely player",
url: "https://cap.so/embed/video123",
type: "text/html",
media: "(aspect-ratio: 16/9)",
media: "(aspect-ratio: 1280/720)",
},
],
});
Expand All @@ -99,11 +101,66 @@ describe("share video metadata", () => {
name: "Product demo",
sourceType: "desktopMP4",
webUrl: "https://cap.so",
width: null,
height: null,
});

expect(metadata.icons).toBeUndefined();
});

it.each([
[1080, 1920],
[1920, 1080],
[1440, 1080],
])(
"preserves %ix%i recording dimensions in link previews",
(width, height) => {
const metadata = buildShareVideoMetadata({
videoId: "video123",
name: "Product demo",
sourceType: "desktopMP4",
webUrl: "https://cap.so",
width,
height,
advertiseIframelyPlayer: true,
});

expect(metadata.openGraph).toMatchObject({
videos: [{ width, height }],
});
expect(metadata.twitter).toMatchObject({
players: { width, height },
});
expect(metadata.icons).toMatchObject({
other: [{ media: `(aspect-ratio: ${width}/${height})` }],
});
},
);

it.each([
[null, null],
[1080, null],
[null, 1920],
[0, 1920],
[1080, 0],
])("uses default dimensions when %s x %s is incomplete", (width, height) => {
const metadata = buildShareVideoMetadata({
videoId: "video123",
name: "Product demo",
sourceType: "desktopMP4",
webUrl: "https://cap.so",
width,
height,
});

expect(metadata.openGraph).toMatchObject({
videos: [{ width: 1280, height: 720 }],
});
expect(metadata.twitter).toMatchObject({
players: { width: 1280, height: 720 },
});
});

it.each([
["MediaConvert", "master"],
["local", "master"],
Expand Down
2 changes: 2 additions & 0 deletions apps/web/app/embed/[videoId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ export async function generateMetadata(
videoId,
name: video.name,
sourceType: video.source.type,
width: Option.getOrNull(video.width),
height: Option.getOrNull(video.height),
webUrl: buildEnv.NEXT_PUBLIC_WEB_URL,
}),
robots: "index, follow",
Expand Down
2 changes: 2 additions & 0 deletions apps/web/app/s/[videoId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,8 @@ export async function generateMetadata(
videoId,
name: video.name,
sourceType: video.source.type,
width: Option.getOrNull(video.width),
height: Option.getOrNull(video.height),
webUrl,
canonicalWebUrl: buildEnv.NEXT_PUBLIC_WEB_URL,
advertiseIframelyPlayer: shouldAdvertiseIframelyPlayer,
Expand Down
18 changes: 13 additions & 5 deletions apps/web/lib/share-video-metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export type ShareVideoMetadataInput = {
name: string;
sourceType: ShareVideoSourceType;
webUrl: string;
width: number | null;
height: number | null;
/**
* Two surfaces only answer on the default Cap origin: `proxy.ts` redirects
* `/embed/` away from a custom domain, and `parseCapShareUrl` accepts share
Expand Down Expand Up @@ -79,6 +81,8 @@ export const buildShareVideoMetadata = ({
webUrl,
canonicalWebUrl,
advertiseIframelyPlayer = false,
width,
height,
}: ShareVideoMetadataInput): Metadata => {
const urls = getShareVideoUrls({
videoId,
Expand All @@ -88,6 +92,10 @@ export const buildShareVideoMetadata = ({
});
const title = `${name} | Cap Recording`;
const description = "Watch this video on Cap";
const hasDimensions =
width != null && height != null && width > 0 && height > 0;
const playerWidth = hasDimensions ? width : PLAYER_WIDTH;
const playerHeight = hasDimensions ? height : PLAYER_HEIGHT;

return {
title,
Expand All @@ -100,7 +108,7 @@ export const buildShareVideoMetadata = ({
rel: "iframely player",
url: urls.playerUrl,
type: "text/html",
media: "(aspect-ratio: 16/9)",
media: `(aspect-ratio: ${playerWidth}/${playerHeight})`,
},
],
},
Expand Down Expand Up @@ -142,8 +150,8 @@ export const buildShareVideoMetadata = ({
{
url: urls.streamUrl,
secureUrl: urls.streamUrl,
width: PLAYER_WIDTH,
height: PLAYER_HEIGHT,
width: playerWidth,
height: playerHeight,
type: urls.streamContentType,
},
],
Expand All @@ -156,8 +164,8 @@ export const buildShareVideoMetadata = ({
players: {
playerUrl: urls.playerUrl,
streamUrl: urls.streamUrl,
width: PLAYER_WIDTH,
height: PLAYER_HEIGHT,
width: playerWidth,
height: playerHeight,
},
},
other: {
Expand Down
Loading