feat: Add VideoRendererBlock for rendering videos

This commit adds a new `VideoRendererBlock` component to the `autogpt_builder` module. The `VideoRendererBlock` is responsible for rendering videos based on the provided video URL. It supports both YouTube videos and direct video URLs.

The `CustomNode` component in the `CustomNode.tsx` file has been updated to handle the new `VideoRendererBlock` component. When the `block_id` matches the ID of the `VideoRendererBlock`, the video is rendered using an iframe for YouTube videos or a video tag for direct video URLs.

This change improves the rendering capabilities of the application by allowing the display of videos within the UI.
This commit is contained in:
Toran Bruce Richards 2024-08-14 11:29:44 +01:00
parent 5af960ae3b
commit d534b63f45
3 changed files with 96 additions and 28 deletions

View File

@ -24,6 +24,7 @@ import NodeHandle from "./NodeHandle";
import { CustomEdgeData } from "./CustomEdge";
import { NodeGenericInputField } from "./node-input-components";
import ArtifactRenderer from './ArtifactRenderer';
import VideoRendererBlock from './VideoRendererBlock';
type ParsedKey = { key: string; index?: number };
@ -280,36 +281,38 @@ const CustomNode: FC<NodeProps<CustomNodeData>> = ({ data, id }) => {
console.log("CustomNode renderOutput, full data:", data);
console.log("CustomNode renderOutput, output_data:", data.output_data);
if (data.block_id === "7a8b9c0d-1e2f-3g4h-5i6j-7k8l9m0n1o2p" && data.output_data && data.output_data.artifact_data) {
console.log("Rendering artifact:", data.output_data.artifact_data);
return <ArtifactRenderer artifactData={data.output_data.artifact_data} />;
} else {
return (
<div className="node-output" onClick={handleOutputClick}>
<p>
<strong>Status:</strong>{" "}
{typeof data.status === "object"
? JSON.stringify(data.status)
: data.status || "N/A"}
</p>
<p>
<strong>Output Data:</strong>{" "}
{(() => {
const outputText =
typeof data.output_data === "object"
? JSON.stringify(data.output_data)
: data.output_data;
switch (data.block_id) {
case "7a8b9c0d-1e2f-3g4h-5i6j-7k8l9m0n1o2p":
return <ArtifactRenderer artifactData={data.output_data.artifact_data} />;
case "a92a0017-2390-425f-b5a8-fb3c50c81400":
return <VideoRendererBlock data={data} />;
default:
return (
<div className="node-output" onClick={handleOutputClick}>
<p>
<strong>Status:</strong>{" "}
{typeof data.status === "object"
? JSON.stringify(data.status)
: data.status || "N/A"}
</p>
<p>
<strong>Output Data:</strong>{" "}
{(() => {
const outputText =
typeof data.output_data === "object"
? JSON.stringify(data.output_data)
: data.output_data;
if (!outputText) return "No output data";
if (!outputText) return "No output data";
return outputText.length > 100
? `${outputText.slice(0, 100)}... Press To Read More`
: outputText;
})()}
</p>
</div>
);
}
return outputText.length > 100
? `${outputText.slice(0, 100)}... Press To Read More`
: outputText;
})()}
</p>
</div>
);
}
};
return (

View File

@ -0,0 +1,45 @@
import React from 'react';
interface VideoRendererProps {
data: any;
}
const VideoRendererBlock: React.FC<VideoRendererProps> = ({ data }) => {
// Extract video URL from the correct location in the data structure
const videoUrl = data.hardcodedValues?.video_url ||
(Array.isArray(data.output_data?.video_url) && data.output_data.video_url[0]);
if (!videoUrl || typeof videoUrl !== 'string') {
return <div>Invalid or missing video URL</div>;
}
const getYouTubeVideoId = (url: string) => {
const regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#&?]*).*/;
const match = url.match(regExp);
return (match && match[7].length === 11) ? match[7] : null;
};
const videoId = getYouTubeVideoId(videoUrl);
return (
<div style={{ width: '100%', padding: '10px' }}>
{videoId ? (
<iframe
width="100%"
height="315"
src={`https://www.youtube.com/embed/${videoId}`}
frameBorder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen
></iframe>
) : (
<video controls width="100%" height="315">
<source src={videoUrl} type="video/mp4" />
Your browser does not support the video tag.
</video>
)}
</div>
);
};
export default VideoRendererBlock;

View File

@ -0,0 +1,20 @@
from autogpt_server.data.block import Block, BlockCategory, BlockOutput, BlockSchema
from autogpt_server.data.model import SchemaField
class VideoRendererBlock(Block):
class Input(BlockSchema):
video_url: str = SchemaField(description="The URL of the video to be rendered.")
class Output(BlockSchema):
video_url: str = SchemaField(description="The URL of the video to be rendered.")
def __init__(self):
super().__init__(
id="a92a0017-2390-425f-b5a8-fb3c50c81400",
description="Renders a video from a given URL within the block.",
input_schema=VideoRendererBlock.Input,
output_schema=VideoRendererBlock.Output
)
def run(self, input_data: Input) -> BlockOutput:
yield "video_url", input_data.video_url