mirror of
https://github.com/storytold/artcraft.git
synced 2026-10-21 17:28:24 -04:00
Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6ef31554b8 | ||
|
|
e2face36aa | ||
|
|
f9c43c2f5a | ||
|
|
933399e15c | ||
|
|
6667c70ead | ||
|
|
90c172f038 |
+4
-4
@@ -37,10 +37,10 @@ pub async fn enqueue_veo_2_image_to_video_webhook<U: IntoUrl, V: IntoUrl>(
|
||||
) -> Result<WebhookResponse, FalErrorPlus> {
|
||||
let duration = match args.duration {
|
||||
Veo2Duration::Default => None,
|
||||
Veo2Duration::FiveSeconds => Some("5".to_string()),
|
||||
Veo2Duration::SixSeconds => Some("6".to_string()),
|
||||
Veo2Duration::SevenSeconds => Some("7".to_string()),
|
||||
Veo2Duration::EightSeconds => Some("8".to_string()),
|
||||
Veo2Duration::FiveSeconds => Some("5s".to_string()),
|
||||
Veo2Duration::SixSeconds => Some("6s".to_string()),
|
||||
Veo2Duration::SevenSeconds => Some("7s".to_string()),
|
||||
Veo2Duration::EightSeconds => Some("8s".to_string()),
|
||||
};
|
||||
|
||||
let aspect_ratio = match args.aspect_ratio {
|
||||
|
||||
@@ -14,7 +14,20 @@ export interface JobMaybeResult {
|
||||
entity_type: string;
|
||||
maybe_public_bucket_media_path: string;
|
||||
maybe_successfully_completed_at: string;
|
||||
media_links?: JobMediaLinks;
|
||||
}
|
||||
|
||||
export interface JobMediaLinks {
|
||||
cdn_url: string;
|
||||
maybe_thumbnail_template?: string;
|
||||
maybe_video_previews?: JobMediaLinksVideoPreviews;
|
||||
}
|
||||
|
||||
export interface JobMediaLinksVideoPreviews {
|
||||
still: string;
|
||||
animated: string;
|
||||
}
|
||||
|
||||
export interface JobRequest {
|
||||
inference_category: string;
|
||||
maybe_model_title: string;
|
||||
|
||||
@@ -66,7 +66,7 @@ import {
|
||||
removeImageDropListener,
|
||||
} from "@storyteller/ui-gallery-modal";
|
||||
import {
|
||||
imageGenerationModels,
|
||||
instructiveImageEditModels,
|
||||
ModelCategory,
|
||||
// ModelCategory,
|
||||
ModelSelector,
|
||||
@@ -536,7 +536,7 @@ export const PageEditor = () => {
|
||||
|
||||
<div className="absolute bottom-6 left-6 z-20 flex items-center gap-2">
|
||||
<ModelSelector
|
||||
items={imageGenerationModels}
|
||||
items={instructiveImageEditModels}
|
||||
category={ModelCategory.Editor3D}
|
||||
panelTitle="Select Model"
|
||||
panelClassName="min-w-[280px]"
|
||||
|
||||
@@ -10,11 +10,13 @@ import { JobsApi } from "~/Classes/ApiManager/JobsApi";
|
||||
import { toast } from "@storyteller/ui-toaster";
|
||||
import { ActiveJob } from "~/pages/PageEnigma/models";
|
||||
import { IsJobPollingDisabled } from "~/flags/DevConsoleFlags";
|
||||
|
||||
// TODO ensure we de-dupe all this extra code.
|
||||
interface CompletedItem {
|
||||
token: string;
|
||||
maybe_title: string;
|
||||
public_bucket_path: string;
|
||||
public_bucket_path: string; // TODO: STOP USING THIS.
|
||||
maybe_media_links_thumbnail?: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
@@ -140,6 +142,12 @@ export function Activity() {
|
||||
maybe_title: job.request?.maybe_model_title || "Image Generation",
|
||||
public_bucket_path:
|
||||
job.maybe_result?.maybe_public_bucket_media_path || "",
|
||||
maybe_media_links_thumbnail: ((job) => {
|
||||
// Try the video thumbnail first, then the regular thumbnail.
|
||||
const maybeVideoThumb = job.maybe_result?.media_links?.maybe_video_previews?.animated;
|
||||
const maybeGenericThumb = (job.maybe_result?.media_links?.maybe_thumbnail_template || "").replace("{WIDTH}", "500");
|
||||
return maybeVideoThumb || maybeGenericThumb;
|
||||
})(job),
|
||||
updated_at: job.updated_at || new Date().toISOString(),
|
||||
}));
|
||||
|
||||
|
||||
+8
-3
@@ -12,6 +12,7 @@ interface Props {
|
||||
updated_at: string;
|
||||
public_bucket_path: string;
|
||||
maybe_style_name?: string;
|
||||
maybe_media_links_thumbnail?: string;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -21,9 +22,13 @@ export function CompletedCard({ job }: Props) {
|
||||
const cdnOrigin = GetCdnOrigin();
|
||||
const mediaPath = job?.public_bucket_path || "";
|
||||
const downloadLink = `${cdnOrigin}${mediaPath}`;
|
||||
const imageUrl = downloadLink;
|
||||
//const imageUrl = downloadLink;
|
||||
const fullImageUrl = downloadLink;
|
||||
|
||||
// NB: Try to use the thumbnail instead of the link to the full asset.
|
||||
// Passing around full asset URLs and putting them into image tags is causing CORS errors if those assets are not images.
|
||||
const thumbnailUrl = job?.maybe_media_links_thumbnail;
|
||||
|
||||
if (!job) return null;
|
||||
|
||||
return (
|
||||
@@ -36,11 +41,11 @@ export function CompletedCard({ job }: Props) {
|
||||
<div className="flex aspect-square h-14 w-14 justify-center overflow-hidden rounded-lg border border-[#A9A9A9]/50 bg-black/60">
|
||||
<img
|
||||
src={
|
||||
loadError ? "/resources/images/movie-placeholder.png" : imageUrl
|
||||
loadError ? "/resources/images/movie-placeholder.png" : thumbnailUrl
|
||||
}
|
||||
className="h-full w-full object-cover"
|
||||
alt={job.maybe_title ?? "unknown"}
|
||||
crossOrigin="anonymous"
|
||||
//crossOrigin="anonymous"
|
||||
onError={() => setLoadError(true)}
|
||||
loading="lazy"
|
||||
/>
|
||||
|
||||
@@ -110,6 +110,7 @@ export const GalleryDraggableItem: React.FC<GalleryDraggableItemProps> = ({
|
||||
</div>
|
||||
) : (
|
||||
<img
|
||||
data-gallery-draggable-1="true"
|
||||
ref={imgRef}
|
||||
src={item.thumbnail}
|
||||
alt={item.label}
|
||||
@@ -177,6 +178,7 @@ export const GalleryDraggableItem: React.FC<GalleryDraggableItemProps> = ({
|
||||
</div>
|
||||
) : (
|
||||
<img
|
||||
data-gallery-draggable-2="true"
|
||||
ref={imgRef}
|
||||
src={item.thumbnail}
|
||||
alt={item.label}
|
||||
|
||||
@@ -153,6 +153,7 @@ export const GalleryModal = React.memo(
|
||||
|
||||
const handleImageError = useCallback(
|
||||
(url: string) => {
|
||||
console.error(`Failed to load gallery modal image: ${url}`);
|
||||
failedImageUrls.add(url);
|
||||
},
|
||||
[failedImageUrls]
|
||||
@@ -234,7 +235,7 @@ export const GalleryModal = React.memo(
|
||||
label: item.maybe_title || "Image Generation",
|
||||
thumbnail:
|
||||
item.media_class === "video"
|
||||
? item.media_links.maybe_video_previews.still
|
||||
? item.media_links.maybe_video_previews.animated
|
||||
: item.media_class === "dimensional"
|
||||
? item.cover_image?.maybe_cover_image_public_bucket_url
|
||||
: item.media_links.maybe_thumbnail_template?.replace(
|
||||
|
||||
@@ -86,6 +86,8 @@ export function LightboxModal({
|
||||
) : mediaClass === "video" ? (
|
||||
<video
|
||||
controls
|
||||
loop={true}
|
||||
autoPlay={true}
|
||||
className="h-full w-full object-contain"
|
||||
onLoadedData={() => setMediaLoaded(true)}
|
||||
>
|
||||
@@ -94,6 +96,7 @@ export function LightboxModal({
|
||||
</video>
|
||||
) : (
|
||||
<img
|
||||
data-lightbox-modal="true"
|
||||
src={imageTagImageUrl}
|
||||
alt={imageAlt}
|
||||
className="h-full w-full object-contain"
|
||||
@@ -134,7 +137,7 @@ export function LightboxModal({
|
||||
//});
|
||||
let result = await EnqueueImageTo3dObject({
|
||||
image_media_token: mediaId,
|
||||
model: EnqueueImageTo3dObjectModel.Hunyuan3d2,
|
||||
model: EnqueueImageTo3dObjectModel.Hunyuan3d2_0,
|
||||
});
|
||||
//e.stopPropagation();
|
||||
//await onAddToSceneClicked(downloadUrl, mediaId);
|
||||
|
||||
@@ -89,7 +89,25 @@ export const allModels = {
|
||||
// badges: [{ label: "25 sec.", icon: <FontAwesomeIcon icon={faClock} /> }],
|
||||
//},
|
||||
],
|
||||
// These models are used for 2D and 3D editing and scene building.
|
||||
instructiveImageEdits: [
|
||||
{
|
||||
label: "GPT-4o",
|
||||
icon: <FontAwesomeIcon icon={faImage} className="h-4 w-4" />,
|
||||
description: "High quality model",
|
||||
badges: [{ label: "2 min.", icon: <FontAwesomeIcon icon={faClock} /> }],
|
||||
modelInfo: IMAGE_MODELS.gpt_image_1,
|
||||
},
|
||||
{
|
||||
label: "FLUX.1 Kontext",
|
||||
icon: <FontAwesomeIcon icon={faImage} className="h-4 w-4" />,
|
||||
description: "Fast and high-quality model",
|
||||
badges: [{ label: "20 sec.", icon: <FontAwesomeIcon icon={faClock} /> }],
|
||||
modelInfo: IMAGE_MODELS.gpt_image_1, // TODO: Wrong metadata!
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const videoGenerationModels: ModelList = allModels.video;
|
||||
export const imageGenerationModels: ModelList = allModels.image;
|
||||
export const instructiveImageEditModels: ModelList = allModels.instructiveImageEdits;
|
||||
|
||||
@@ -21,6 +21,8 @@ export interface EnqueueImageTo3dObjectRequest {
|
||||
|
||||
export enum EnqueueImageTo3dObjectModel {
|
||||
Hunyuan3d2 = "hunyuan_3d_2",
|
||||
Hunyuan3d2_0 = "hunyuan_3d_2_0",
|
||||
Hunyuan3d2_1 = "hunyuan_3d_2_1",
|
||||
}
|
||||
|
||||
export interface EnqueueImageTo3dObjectError extends CommandResult {
|
||||
|
||||
Reference in New Issue
Block a user