Skip to content

Instantly share code, notes, and snippets.

@jamsea
Created January 26, 2024 06:21
Show Gist options
  • Save jamsea/b919bfb425cac4bc1f8a714ea006f363 to your computer and use it in GitHub Desktop.
Save jamsea/b919bfb425cac4bc1f8a714ea006f363 to your computer and use it in GitHub Desktop.
VCS Video Split Single Demo
import * as React from 'react';
import { Box, Video } from '#vcs-react/components';
import { useGrid } from '#vcs-react/hooks';
import * as layoutFuncs from '../layouts.js';
import VideoSingle from './VideoSingle.js';
import decorateVideoSplitItem from './overrides/decorateVideoSplitItem.js';
import { PositionCorner } from '../constants.js';
export default function AugmentedSplit(props) {
const { participantDescs = [] } = props;
const base = <VideoSplit {...props} />;
let pipOverlay;
if (participantDescs.length > 2) {
pipOverlay = <SimplePip participant={participantDescs[2]} />;
}
return (
<Box>
{base}
{pipOverlay}
</Box>
);
}
// a simple picture-in-picture with hardcoded settings
// using the same layout function as VideoPip.js
//
function SimplePip({ participant }) {
const { videoId, displayName = '', paused } = participant;
const pxPerGu = useGrid().pixelsPerGridUnit;
const pipSize_gu = 10;
const layoutProps = {
positionCorner: PositionCorner.TOP_RIGHT,
aspectRatio: 1,
height_gu: pipSize_gu,
margin_gu: 2,
};
const layout = [layoutFuncs.pip, layoutProps];
const videoStyle = {
cornerRadius_px: (pipSize_gu / 2) * pxPerGu, // mask to circle
};
const outlineStyle = {
...videoStyle,
strokeWidth_px: pxPerGu / 3, // the outline for the video
strokeColor: 'white',
};
return (
<Box id="pipOutline" style={outlineStyle} layout={layout}>
<Video id="pipVideo" src={videoId} scaleMode="fill" style={videoStyle} />
</Box>
);
}
// a row of picture-in-picture videos, using an inline layout function
//
function PipRow({ participantDescs }) {
const pxPerGu = useGrid().pixelsPerGridUnit;
const pipSize_gu = 6;
const margin_gu = 2;
const interval_gu = 1;
const videoStyle = {
cornerRadius_px: (pipSize_gu / 2) * pxPerGu, // mask to circle
};
const outlineStyle = {
...videoStyle,
strokeWidth_px: 2, // the outline for the video
strokeColor: 'rgba(255, 255, 210, 0.9)',
};
function rowLayoutFn(parentFrame, params) {
const { idx } = params;
let { x, y, w, h } = parentFrame;
const margin = margin_gu * pxPerGu;
const interval = interval_gu * pxPerGu;
w = h = pipSize_gu * pxPerGu;
x += margin + (interval + w) * idx;
y += parentFrame.h - margin - h;
return { x, y, w, h };
}
return participantDescs.map((pd, idx) => {
const { videoId } = pd;
return (
<Box key={idx} style={outlineStyle} layout={[rowLayoutFn, { idx }]}>
<Video src={videoId} scaleMode="fill" style={videoStyle} />
</Box>
);
});
}
// this is the original VideoSplit function from the baseline composition
//
function VideoSplit(props) {
const { participantDescs = [], margin_gu = 0, splitDirection } = props;
// Make sure we have exactly one or two boxes
const totalItems = Math.max(1, Math.min(participantDescs.length, 2));
let layoutFn;
switch (splitDirection) {
default:
layoutFn = layoutFuncs.splitAcrossLongerDimension;
break;
case 'horizontal':
layoutFn = layoutFuncs.splitHorizontal;
break;
case 'vertical':
layoutFn = layoutFuncs.splitVertical;
break;
}
function makeItem(itemIdx) {
const key = 'videosplit_item' + itemIdx;
const participant = participantDescs[itemIdx];
// override point for custom decorations on split videos.
// we use a VideoSingle component to actually render these,
// so get the decoration here and pass it as an override to VideoSingle.
const overrideDecoration = decorateVideoSplitItem(
itemIdx,
participant,
props
);
return (
<Box
key={key}
id={key}
layout={[layoutFn, { index: itemIdx, margin_gu, pos: 1 / totalItems }]}
>
<VideoSingle
enableParticipantOverride={true}
overrideParticipant={participant}
overrideDecoration={overrideDecoration}
{...props}
/>
</Box>
);
}
if (totalItems === 1) {
return <Box id="videosplit">{[makeItem(0)]}</Box>;
} else {
return <Box id="videosplit">{[makeItem(0), makeItem(1)]}</Box>;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment