Skip to content

Commit

Permalink
Add ability to play videos
Browse files Browse the repository at this point in the history
  • Loading branch information
sindrig committed Oct 22, 2024
1 parent da80892 commit 86400e7
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 46 deletions.
109 changes: 64 additions & 45 deletions clock/src/controller/asset/Asset.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import Ruv from "./Ruv";
import controllerActions from "../../actions/controller";

import "./Asset.css";
import VideoPlayer from "./VideoPlayer";

class Asset extends Component {
static propTypes = {
Expand Down Expand Up @@ -60,7 +61,11 @@ class Asset extends Component {
if (sync && auth.isEmpty) {
return;
}
const typeNeedsManualRemove = asset.type !== assetTypes.URL;
const typesWithoutManualRemove = [assetTypes.URL, assetTypes.VIDEO];
const typeNeedsManualRemove = !typesWithoutManualRemove.includes(
asset.type,
);

if (time && !thumbnail && typeNeedsManualRemove) {
this.timeout = setTimeout(removeAssetAfterTimeout, time * 1000);
}
Expand Down Expand Up @@ -184,57 +189,71 @@ class Asset extends Component {
);
}

render() {
renderSub() {
const { asset, thumbnail } = this.props;
if (!asset) {
const { subIn, subOut } = asset;
if (!subIn || !subOut) {
console.log("No subin or subout", asset);
return null;
}
return (
<Substitution thumbnail={thumbnail}>
{[subIn, subOut].map((subAsset) =>
this.getPlayerAsset({
asset: subAsset,
widthMultiplier: 0.7,
includeBackground: false,
}),
)}
</Substitution>
);
}

if (asset.type === assetTypes.IMAGE) {
return (
<img
src={asset.url || asset.key}
alt={asset.key}
key={asset.key}
style={{ height: "100%", width: "100%" }}
/>
);
}
if (asset.type === assetTypes.URL) {
return this.renderUrl();
}
if (asset.type === assetTypes.RUV) {
return this.renderRuv();
}
if (
asset.type === assetTypes.PLAYER ||
asset.type === assetTypes.NO_IMAGE_PLAYER
) {
return this.getPlayerAsset({ asset, widthMultiplier: 1 });
render() {
const { asset, thumbnail, removeAssetAfterTimeout } = this.props;
if (!asset) {
return null;
}
if (asset.type === assetTypes.SUB) {
const { subIn, subOut } = asset;
if (!subIn || !subOut) {
console.log("No subin or subout", asset);

switch (asset.type) {
case assetTypes.IMAGE:
return (
<img
src={asset.url || asset.key}
alt={asset.key}
key={asset.key}
style={{ height: "100%", width: "100%" }}
/>
);
case assetTypes.VIDEO:
return (
<VideoPlayer
asset={asset}
onEnded={removeAssetAfterTimeout}
thumbnail={thumbnail}
/>
);

case assetTypes.URL:
return this.renderUrl();

case assetTypes.RUV:
return this.renderRuv();

case assetTypes.PLAYER:
case assetTypes.NO_IMAGE_PLAYER:
return this.getPlayerAsset({ asset, widthMultiplier: 1 });

case assetTypes.SUB:
return this.renderSub();

case assetTypes.FREE_TEXT:
return this.renderFreeText();

default:
console.error("No type for item ", asset);
return null;
}
return (
<Substitution thumbnail={thumbnail}>
{[subIn, subOut].map((subAsset) =>
this.getPlayerAsset({
asset: subAsset,
widthMultiplier: 0.7,
includeBackground: false,
}),
)}
</Substitution>
);
}
if (asset.type === assetTypes.FREE_TEXT) {
return this.renderFreeText();
}
console.error("No type for item ", asset);
return null;
}
}

Expand Down
1 change: 1 addition & 0 deletions clock/src/controller/asset/AssetTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export default {
PLAYER: "PLAYER",
NO_IMAGE_PLAYER: "NO_IMAGE_PLAYER",
IMAGE: "IMAGE",
VIDEO: "VIDEO",
SUB: "SUB",
FREE_TEXT: "FREE_TEXT",
};
42 changes: 42 additions & 0 deletions clock/src/controller/asset/VideoPlayer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React, { useRef, useEffect } from "react";
import PropTypes from "prop-types";

import { assetPropType } from "../../propTypes";

const VideoPlayer = ({
asset: { url, key },
thumbnail,
playbackSpeed = 1,
onEnded,
}) => {
const videoRef = useRef(null);

if (playbackSpeed !== 1) {
useEffect(() => {
if (videoRef.current && !thumbnail) {
videoRef.current.playbackRate = playbackSpeed; // Set the playback rate
}
}, [playbackSpeed, url || key]); // Update playback speed when it changes
}
return (
<div style={{ height: "100%", width: "100%", backgroundColor: "black" }}>
<video
ref={videoRef}
src={url || key}
autoPlay={!thumbnail}
loop={thumbnail}
muted={thumbnail}
onEnded={onEnded}
style={{ height: "100%", width: "100%" }}
/>
</div>
);
};
VideoPlayer.propTypes = {
asset: assetPropType.isRequired,
playbackSpeed: PropTypes.number.isRequired,
onEnded: PropTypes.func.isRequired,
thumbnail: PropTypes.bool,
};

export default VideoPlayer;
9 changes: 8 additions & 1 deletion clock/src/controller/media/ImageList.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import TrashIcon from "@rsuite/icons/Trash";

import "./ImageList.css";

const AssetTypeSuffixMap = {
mp4: assetTypes.VIDEO,
};

const ImageList = ({
prefix,
renderAsset,
Expand Down Expand Up @@ -81,12 +85,15 @@ const ImageList = ({
<div className="asset-image withborder" key={name}>
<div
onClick={() => {
const parts = name.split(".");
const suffix = parts[parts.length - 1];
const type = AssetTypeSuffixMap[suffix] || assetTypes.IMAGE;
const asset = {
// To be able to add the same image multiple times to the queue,
// we need to make the key unique
key: imageUrl + Date.now(),
url: imageUrl,
type: assetTypes.IMAGE,
type,
};
if (displayNow) {
renderAsset({ asset });
Expand Down

0 comments on commit 86400e7

Please sign in to comment.