diff --git a/clock/src/controller/asset/Asset.js b/clock/src/controller/asset/Asset.js
index 1300e1d9..0a4441ed 100644
--- a/clock/src/controller/asset/Asset.js
+++ b/clock/src/controller/asset/Asset.js
@@ -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 = {
@@ -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);
}
@@ -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 (
+
+ {[subIn, subOut].map((subAsset) =>
+ this.getPlayerAsset({
+ asset: subAsset,
+ widthMultiplier: 0.7,
+ includeBackground: false,
+ }),
+ )}
+
+ );
+ }
- if (asset.type === assetTypes.IMAGE) {
- return (
-
- );
- }
- 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 (
+
+ );
+ case assetTypes.VIDEO:
+ return (
+
+ );
+
+ 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 (
-
- {[subIn, subOut].map((subAsset) =>
- this.getPlayerAsset({
- asset: subAsset,
- widthMultiplier: 0.7,
- includeBackground: false,
- }),
- )}
-
- );
}
- if (asset.type === assetTypes.FREE_TEXT) {
- return this.renderFreeText();
- }
- console.error("No type for item ", asset);
- return null;
}
}
diff --git a/clock/src/controller/asset/AssetTypes.js b/clock/src/controller/asset/AssetTypes.js
index a855400d..0c93288c 100644
--- a/clock/src/controller/asset/AssetTypes.js
+++ b/clock/src/controller/asset/AssetTypes.js
@@ -4,6 +4,7 @@ export default {
PLAYER: "PLAYER",
NO_IMAGE_PLAYER: "NO_IMAGE_PLAYER",
IMAGE: "IMAGE",
+ VIDEO: "VIDEO",
SUB: "SUB",
FREE_TEXT: "FREE_TEXT",
};
diff --git a/clock/src/controller/asset/VideoPlayer.js b/clock/src/controller/asset/VideoPlayer.js
new file mode 100644
index 00000000..eaadae84
--- /dev/null
+++ b/clock/src/controller/asset/VideoPlayer.js
@@ -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 (
+
+
+
+ );
+};
+VideoPlayer.propTypes = {
+ asset: assetPropType.isRequired,
+ playbackSpeed: PropTypes.number.isRequired,
+ onEnded: PropTypes.func.isRequired,
+ thumbnail: PropTypes.bool,
+};
+
+export default VideoPlayer;
diff --git a/clock/src/controller/media/ImageList.js b/clock/src/controller/media/ImageList.js
index 7267a5db..9de89d10 100644
--- a/clock/src/controller/media/ImageList.js
+++ b/clock/src/controller/media/ImageList.js
@@ -10,6 +10,10 @@ import TrashIcon from "@rsuite/icons/Trash";
import "./ImageList.css";
+const AssetTypeSuffixMap = {
+ mp4: assetTypes.VIDEO,
+};
+
const ImageList = ({
prefix,
renderAsset,
@@ -81,12 +85,15 @@ const ImageList = ({
{
+ 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 });