@twick/studio 0.15.23 → 0.15.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,6 +2,10 @@ import { ProjectJSON, VideoElement } from '@twick/timeline';
2
2
  import { ICaptionGenerationPollingResponse, ICaptionGenerationService, CaptionEntry } from '../types';
3
3
 
4
4
  declare class GenerateCaptionsService implements ICaptionGenerationService {
5
+ /**
6
+ * Compatibility wrapper for legacy Studio caption service flow.
7
+ * New AI workflows should prefer @twick/workflow directly.
8
+ */
5
9
  videoElement: VideoElement | null;
6
10
  projectJSON: ProjectJSON | null;
7
11
  generateSubtiltesApi: (videoUrl: string) => Promise<string>;
package/dist/index.js CHANGED
@@ -4907,141 +4907,13 @@ function CaptionsPanelContainer() {
4907
4907
  const captionsPanelProps = useCaptionsPanel();
4908
4908
  return /* @__PURE__ */ jsxRuntime.jsx(CaptionsPanel, { ...captionsPanelProps });
4909
4909
  }
4910
- const FAL_IMAGE_ENDPOINTS = [
4911
- {
4912
- provider: "fal",
4913
- endpointId: "fal-ai/flux-pro/kontext",
4914
- label: "FLUX.1 Kontext [pro]",
4915
- description: "Professional image generation with context-aware editing",
4916
- popularity: 5,
4917
- category: "image",
4918
- inputAsset: ["image"],
4919
- availableDimensions: [
4920
- { width: 1024, height: 1024, label: "1024x1024 (1:1)" },
4921
- { width: 1024, height: 576, label: "1024x576 (16:9)" },
4922
- { width: 576, height: 1024, label: "576x1024 (9:16)" }
4923
- ]
4924
- },
4925
- {
4926
- provider: "fal",
4927
- endpointId: "fal-ai/flux/dev",
4928
- label: "FLUX.1 [dev]",
4929
- description: "High-quality image generation",
4930
- popularity: 5,
4931
- category: "image",
4932
- minSteps: 1,
4933
- maxSteps: 50,
4934
- defaultSteps: 28,
4935
- minGuidanceScale: 1,
4936
- maxGuidanceScale: 20,
4937
- defaultGuidanceScale: 3.5,
4938
- hasSeed: true
4939
- },
4940
- {
4941
- provider: "fal",
4942
- endpointId: "fal-ai/flux/schnell",
4943
- label: "FLUX.1 [schnell]",
4944
- description: "Ultra-fast image generation",
4945
- popularity: 4,
4946
- category: "image",
4947
- defaultSteps: 4,
4948
- availableDimensions: [
4949
- { width: 1024, height: 1024, label: "1024x1024 (1:1)" },
4950
- { width: 1024, height: 576, label: "1024x576 (16:9)" },
4951
- { width: 576, height: 1024, label: "576x1024 (9:16)" }
4952
- ]
4953
- },
4954
- {
4955
- provider: "fal",
4956
- endpointId: "fal-ai/gemini-25-flash-image",
4957
- label: "Gemini 2.5 Flash Image",
4958
- description: "Rapid text-to-image generation",
4959
- popularity: 5,
4960
- category: "image",
4961
- availableDimensions: [
4962
- { width: 1024, height: 1024, label: "1024x1024 (1:1)" },
4963
- { width: 1024, height: 768, label: "1024x768 (4:3)" },
4964
- { width: 768, height: 1024, label: "768x1024 (3:4)" },
4965
- { width: 1024, height: 576, label: "1024x576 (16:9)" },
4966
- { width: 576, height: 1024, label: "576x1024 (9:16)" }
4967
- ]
4968
- },
4969
- {
4970
- provider: "fal",
4971
- endpointId: "fal-ai/ideogram/v3",
4972
- label: "Ideogram V3",
4973
- description: "Advanced text-to-image with superior text rendering",
4974
- popularity: 5,
4975
- category: "image",
4976
- hasSeed: true,
4977
- hasNegativePrompt: true
4978
- }
4979
- ];
4980
- const FAL_VIDEO_ENDPOINTS = [
4981
- {
4982
- provider: "fal",
4983
- endpointId: "fal-ai/veo3",
4984
- label: "Veo 3",
4985
- description: "Google Veo 3 text-to-video",
4986
- popularity: 5,
4987
- category: "video",
4988
- availableDurations: [4, 6, 8],
4989
- defaultDuration: 8,
4990
- availableDimensions: [
4991
- { width: 576, height: 1024, label: "576x1024 (9:16)" },
4992
- { width: 1024, height: 576, label: "1024x576 (16:9)" },
4993
- { width: 1024, height: 1024, label: "1024x1024 (1:1)" }
4994
- ]
4995
- },
4996
- {
4997
- provider: "fal",
4998
- endpointId: "fal-ai/veo3/fast",
4999
- label: "Veo 3 Fast",
5000
- description: "Accelerated Veo 3 text-to-video",
5001
- popularity: 5,
5002
- category: "video",
5003
- availableDurations: [4, 6, 8],
5004
- defaultDuration: 8,
5005
- availableDimensions: [
5006
- { width: 576, height: 1024, label: "576x1024 (9:16)" },
5007
- { width: 1024, height: 576, label: "1024x576 (16:9)" },
5008
- { width: 1024, height: 1024, label: "1024x1024 (1:1)" }
5009
- ]
5010
- },
5011
- {
5012
- provider: "fal",
5013
- endpointId: "fal-ai/veo3/image-to-video",
5014
- label: "Veo 3 Image-to-Video",
5015
- description: "Animate images with Veo 3",
5016
- popularity: 5,
5017
- category: "video",
5018
- inputAsset: ["image"],
5019
- availableDurations: [8],
5020
- defaultDuration: 8
5021
- },
5022
- {
5023
- provider: "fal",
5024
- endpointId: "fal-ai/kling-video/v2.5-turbo/pro/text-to-video",
5025
- label: "Kling 2.5 Turbo Pro",
5026
- description: "Text-to-video with fluid motion",
5027
- popularity: 5,
5028
- category: "video",
5029
- availableDurations: [5, 10],
5030
- defaultDuration: 5,
5031
- availableDimensions: [
5032
- { width: 1024, height: 576, label: "1024x576 (16:9)" },
5033
- { width: 576, height: 1024, label: "576x1024 (9:16)" },
5034
- { width: 1024, height: 1024, label: "1024x1024 (1:1)" }
5035
- ]
5036
- }
5037
- ];
5038
4910
  const DEFAULT_IMAGE_DURATION = 5;
5039
4911
  function GenerateMediaPanelContainer({
5040
4912
  videoResolution,
5041
4913
  addElement,
5042
4914
  studioConfig
5043
4915
  }) {
5044
- var _a;
4916
+ var _a, _b, _c;
5045
4917
  const { getCurrentTime } = livePlayer.useLivePlayerContext();
5046
4918
  const [tab, setTab] = react.useState("image");
5047
4919
  const [prompt2, setPrompt] = react.useState("");
@@ -5052,8 +4924,12 @@ function GenerateMediaPanelContainer({
5052
4924
  const imageService = studioConfig == null ? void 0 : studioConfig.imageGenerationService;
5053
4925
  const videoService = studioConfig == null ? void 0 : studioConfig.videoGenerationService;
5054
4926
  const hasAnyService = !!imageService || !!videoService;
5055
- const endpoints = tab === "image" ? FAL_IMAGE_ENDPOINTS : FAL_VIDEO_ENDPOINTS;
5056
- const defaultEndpointId = ((_a = endpoints[0]) == null ? void 0 : _a.endpointId) ?? "";
4927
+ const imageModels = ((_a = imageService == null ? void 0 : imageService.getAvailableModels) == null ? void 0 : _a.call(imageService)) ?? [];
4928
+ const videoModels = ((_b = videoService == null ? void 0 : videoService.getAvailableModels) == null ? void 0 : _b.call(videoService)) ?? [];
4929
+ const endpoints = tab === "image" ? imageModels : videoModels;
4930
+ const defaultEndpointId = ((_c = endpoints[0]) == null ? void 0 : _c.endpointId) ?? "";
4931
+ const selectedEndpoint = endpoints.find((endpoint) => endpoint.endpointId === selectedEndpointId) ?? endpoints[0];
4932
+ const selectedProvider = selectedEndpoint == null ? void 0 : selectedEndpoint.provider;
5057
4933
  react.useEffect(() => {
5058
4934
  if (!selectedEndpointId && defaultEndpointId) {
5059
4935
  setSelectedEndpointId(defaultEndpointId);
@@ -5115,9 +4991,16 @@ function GenerateMediaPanelContainer({
5115
4991
  setStatus("Starting...");
5116
4992
  try {
5117
4993
  const endpointId = selectedEndpointId || defaultEndpointId;
4994
+ const provider = selectedProvider;
4995
+ if (!endpointId || !provider) {
4996
+ setError("No model is configured for this tab");
4997
+ setIsGenerating(false);
4998
+ setStatus(null);
4999
+ return;
5000
+ }
5118
5001
  if (tab === "image" && imageService) {
5119
5002
  const requestId = await imageService.generateImage({
5120
- provider: "fal",
5003
+ provider,
5121
5004
  endpointId,
5122
5005
  prompt: prompt2.trim()
5123
5006
  });
@@ -5127,7 +5010,7 @@ function GenerateMediaPanelContainer({
5127
5010
  }
5128
5011
  } else if (tab === "video" && videoService) {
5129
5012
  const requestId = await videoService.generateVideo({
5130
- provider: "fal",
5013
+ provider,
5131
5014
  endpointId,
5132
5015
  prompt: prompt2.trim()
5133
5016
  });
@@ -5149,7 +5032,8 @@ function GenerateMediaPanelContainer({
5149
5032
  defaultEndpointId,
5150
5033
  imageService,
5151
5034
  videoService,
5152
- pollStatus
5035
+ pollStatus,
5036
+ selectedProvider
5153
5037
  ]);
5154
5038
  if (!hasAnyService) {
5155
5039
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "panel-container", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "empty-state-text", children: "Image and video generation require configuration. Add imageGenerationService and videoGenerationService to StudioConfig." }) });