@weirdfingers/baseboards 0.9.6 → 0.9.7
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.
- package/dist/index.js +560 -469
- package/dist/index.js.map +1 -1
- package/package.json +2 -5
- package/templates/README.md +0 -122
- package/templates/api/.env.example +0 -65
- package/templates/api/ARTIFACT_RESOLUTION_GUIDE.md +0 -148
- package/templates/api/Dockerfile +0 -32
- package/templates/api/README.md +0 -264
- package/templates/api/alembic/env.py +0 -114
- package/templates/api/alembic/script.py.mako +0 -28
- package/templates/api/alembic/versions/20250101_000000_initial_schema.py +0 -506
- package/templates/api/alembic/versions/20251022_174729_remove_provider_name_from_generations.py +0 -75
- package/templates/api/alembic/versions/20251023_165852_switch_to_declarative_base_and_mapping.py +0 -467
- package/templates/api/alembic/versions/20251202_000000_add_artifact_lineage.py +0 -134
- package/templates/api/alembic/versions/2025925_62735_add_seed_data_for_default_tenant.py +0 -88
- package/templates/api/alembic.ini +0 -36
- package/templates/api/config/generators.yaml +0 -237
- package/templates/api/config/storage_config.yaml +0 -26
- package/templates/api/docs/ADDING_GENERATORS.md +0 -409
- package/templates/api/docs/GENERATORS_API.md +0 -502
- package/templates/api/docs/MIGRATIONS.md +0 -472
- package/templates/api/docs/TESTING_LIVE_APIS.md +0 -417
- package/templates/api/docs/storage_providers.md +0 -337
- package/templates/api/pyproject.toml +0 -205
- package/templates/api/src/boards/__init__.py +0 -10
- package/templates/api/src/boards/api/app.py +0 -172
- package/templates/api/src/boards/api/auth.py +0 -75
- package/templates/api/src/boards/api/endpoints/__init__.py +0 -3
- package/templates/api/src/boards/api/endpoints/jobs.py +0 -76
- package/templates/api/src/boards/api/endpoints/setup.py +0 -505
- package/templates/api/src/boards/api/endpoints/sse.py +0 -129
- package/templates/api/src/boards/api/endpoints/storage.py +0 -155
- package/templates/api/src/boards/api/endpoints/tenant_registration.py +0 -296
- package/templates/api/src/boards/api/endpoints/uploads.py +0 -149
- package/templates/api/src/boards/api/endpoints/webhooks.py +0 -13
- package/templates/api/src/boards/auth/__init__.py +0 -15
- package/templates/api/src/boards/auth/adapters/__init__.py +0 -27
- package/templates/api/src/boards/auth/adapters/auth0.py +0 -220
- package/templates/api/src/boards/auth/adapters/base.py +0 -73
- package/templates/api/src/boards/auth/adapters/clerk.py +0 -172
- package/templates/api/src/boards/auth/adapters/jwt.py +0 -122
- package/templates/api/src/boards/auth/adapters/none.py +0 -102
- package/templates/api/src/boards/auth/adapters/oidc.py +0 -284
- package/templates/api/src/boards/auth/adapters/supabase.py +0 -110
- package/templates/api/src/boards/auth/context.py +0 -35
- package/templates/api/src/boards/auth/factory.py +0 -129
- package/templates/api/src/boards/auth/middleware.py +0 -221
- package/templates/api/src/boards/auth/provisioning.py +0 -129
- package/templates/api/src/boards/auth/tenant_extraction.py +0 -278
- package/templates/api/src/boards/cli.py +0 -354
- package/templates/api/src/boards/config.py +0 -131
- package/templates/api/src/boards/database/__init__.py +0 -7
- package/templates/api/src/boards/database/cli.py +0 -110
- package/templates/api/src/boards/database/connection.py +0 -292
- package/templates/api/src/boards/database/models.py +0 -19
- package/templates/api/src/boards/database/seed_data.py +0 -182
- package/templates/api/src/boards/dbmodels/__init__.py +0 -441
- package/templates/api/src/boards/generators/__init__.py +0 -57
- package/templates/api/src/boards/generators/artifact_resolution.py +0 -405
- package/templates/api/src/boards/generators/artifacts.py +0 -53
- package/templates/api/src/boards/generators/base.py +0 -144
- package/templates/api/src/boards/generators/implementations/__init__.py +0 -14
- package/templates/api/src/boards/generators/implementations/fal/__init__.py +0 -25
- package/templates/api/src/boards/generators/implementations/fal/audio/__init__.py +0 -23
- package/templates/api/src/boards/generators/implementations/fal/audio/beatoven_music_generation.py +0 -171
- package/templates/api/src/boards/generators/implementations/fal/audio/beatoven_sound_effect_generation.py +0 -167
- package/templates/api/src/boards/generators/implementations/fal/audio/chatterbox_text_to_speech.py +0 -176
- package/templates/api/src/boards/generators/implementations/fal/audio/chatterbox_tts_turbo.py +0 -195
- package/templates/api/src/boards/generators/implementations/fal/audio/elevenlabs_sound_effects_v2.py +0 -194
- package/templates/api/src/boards/generators/implementations/fal/audio/elevenlabs_tts_eleven_v3.py +0 -209
- package/templates/api/src/boards/generators/implementations/fal/audio/fal_elevenlabs_tts_turbo_v2_5.py +0 -206
- package/templates/api/src/boards/generators/implementations/fal/audio/fal_minimax_speech_26_hd.py +0 -237
- package/templates/api/src/boards/generators/implementations/fal/audio/minimax_music_v2.py +0 -173
- package/templates/api/src/boards/generators/implementations/fal/audio/minimax_speech_2_6_turbo.py +0 -221
- package/templates/api/src/boards/generators/implementations/fal/image/__init__.py +0 -63
- package/templates/api/src/boards/generators/implementations/fal/image/bytedance_seedream_v45_edit.py +0 -219
- package/templates/api/src/boards/generators/implementations/fal/image/clarity_upscaler.py +0 -220
- package/templates/api/src/boards/generators/implementations/fal/image/crystal_upscaler.py +0 -173
- package/templates/api/src/boards/generators/implementations/fal/image/fal_ideogram_character.py +0 -227
- package/templates/api/src/boards/generators/implementations/fal/image/flux_2.py +0 -203
- package/templates/api/src/boards/generators/implementations/fal/image/flux_2_edit.py +0 -230
- package/templates/api/src/boards/generators/implementations/fal/image/flux_2_pro.py +0 -204
- package/templates/api/src/boards/generators/implementations/fal/image/flux_2_pro_edit.py +0 -221
- package/templates/api/src/boards/generators/implementations/fal/image/flux_pro_kontext.py +0 -216
- package/templates/api/src/boards/generators/implementations/fal/image/flux_pro_ultra.py +0 -197
- package/templates/api/src/boards/generators/implementations/fal/image/gemini_25_flash_image.py +0 -177
- package/templates/api/src/boards/generators/implementations/fal/image/gemini_25_flash_image_edit.py +0 -208
- package/templates/api/src/boards/generators/implementations/fal/image/gpt_image_15_edit.py +0 -216
- package/templates/api/src/boards/generators/implementations/fal/image/gpt_image_1_5.py +0 -177
- package/templates/api/src/boards/generators/implementations/fal/image/gpt_image_1_edit_image.py +0 -182
- package/templates/api/src/boards/generators/implementations/fal/image/gpt_image_1_mini.py +0 -167
- package/templates/api/src/boards/generators/implementations/fal/image/ideogram_character_edit.py +0 -299
- package/templates/api/src/boards/generators/implementations/fal/image/ideogram_v2.py +0 -190
- package/templates/api/src/boards/generators/implementations/fal/image/imagen4_preview.py +0 -191
- package/templates/api/src/boards/generators/implementations/fal/image/imagen4_preview_fast.py +0 -179
- package/templates/api/src/boards/generators/implementations/fal/image/nano_banana.py +0 -183
- package/templates/api/src/boards/generators/implementations/fal/image/nano_banana_edit.py +0 -212
- package/templates/api/src/boards/generators/implementations/fal/image/nano_banana_pro.py +0 -179
- package/templates/api/src/boards/generators/implementations/fal/image/nano_banana_pro_edit.py +0 -226
- package/templates/api/src/boards/generators/implementations/fal/image/qwen_image.py +0 -249
- package/templates/api/src/boards/generators/implementations/fal/image/qwen_image_edit.py +0 -244
- package/templates/api/src/boards/generators/implementations/fal/image/reve_edit.py +0 -178
- package/templates/api/src/boards/generators/implementations/fal/image/reve_text_to_image.py +0 -155
- package/templates/api/src/boards/generators/implementations/fal/image/seedream_v45_text_to_image.py +0 -180
- package/templates/api/src/boards/generators/implementations/fal/utils.py +0 -61
- package/templates/api/src/boards/generators/implementations/fal/video/__init__.py +0 -77
- package/templates/api/src/boards/generators/implementations/fal/video/bytedance_seedance_v1_pro_text_to_video.py +0 -209
- package/templates/api/src/boards/generators/implementations/fal/video/creatify_lipsync.py +0 -161
- package/templates/api/src/boards/generators/implementations/fal/video/fal_bytedance_seedance_v1_pro_image_to_video.py +0 -222
- package/templates/api/src/boards/generators/implementations/fal/video/fal_minimax_hailuo_02_standard_text_to_video.py +0 -152
- package/templates/api/src/boards/generators/implementations/fal/video/fal_pixverse_lipsync.py +0 -197
- package/templates/api/src/boards/generators/implementations/fal/video/fal_sora_2_text_to_video.py +0 -173
- package/templates/api/src/boards/generators/implementations/fal/video/infinitalk.py +0 -221
- package/templates/api/src/boards/generators/implementations/fal/video/kling_video_ai_avatar_v2_pro.py +0 -168
- package/templates/api/src/boards/generators/implementations/fal/video/kling_video_ai_avatar_v2_standard.py +0 -159
- package/templates/api/src/boards/generators/implementations/fal/video/kling_video_v2_5_turbo_pro_image_to_video.py +0 -175
- package/templates/api/src/boards/generators/implementations/fal/video/kling_video_v2_5_turbo_pro_text_to_video.py +0 -168
- package/templates/api/src/boards/generators/implementations/fal/video/minimax_hailuo_2_3_pro_image_to_video.py +0 -153
- package/templates/api/src/boards/generators/implementations/fal/video/sora2_image_to_video.py +0 -172
- package/templates/api/src/boards/generators/implementations/fal/video/sora_2_image_to_video_pro.py +0 -175
- package/templates/api/src/boards/generators/implementations/fal/video/sora_2_text_to_video_pro.py +0 -163
- package/templates/api/src/boards/generators/implementations/fal/video/sync_lipsync_v2.py +0 -167
- package/templates/api/src/boards/generators/implementations/fal/video/sync_lipsync_v2_pro.py +0 -155
- package/templates/api/src/boards/generators/implementations/fal/video/veed_fabric_1_0.py +0 -180
- package/templates/api/src/boards/generators/implementations/fal/video/veed_lipsync.py +0 -174
- package/templates/api/src/boards/generators/implementations/fal/video/veo3.py +0 -194
- package/templates/api/src/boards/generators/implementations/fal/video/veo31.py +0 -190
- package/templates/api/src/boards/generators/implementations/fal/video/veo31_fast.py +0 -190
- package/templates/api/src/boards/generators/implementations/fal/video/veo31_fast_image_to_video.py +0 -191
- package/templates/api/src/boards/generators/implementations/fal/video/veo31_first_last_frame_to_video.py +0 -187
- package/templates/api/src/boards/generators/implementations/fal/video/veo31_image_to_video.py +0 -183
- package/templates/api/src/boards/generators/implementations/fal/video/veo31_reference_to_video.py +0 -172
- package/templates/api/src/boards/generators/implementations/fal/video/wan_25_preview_image_to_video.py +0 -212
- package/templates/api/src/boards/generators/implementations/fal/video/wan_25_preview_text_to_video.py +0 -208
- package/templates/api/src/boards/generators/implementations/fal/video/wan_pro_image_to_video.py +0 -158
- package/templates/api/src/boards/generators/implementations/kie/__init__.py +0 -11
- package/templates/api/src/boards/generators/implementations/kie/base.py +0 -316
- package/templates/api/src/boards/generators/implementations/kie/image/__init__.py +0 -3
- package/templates/api/src/boards/generators/implementations/kie/image/nano_banana_edit.py +0 -190
- package/templates/api/src/boards/generators/implementations/kie/utils.py +0 -98
- package/templates/api/src/boards/generators/implementations/kie/video/__init__.py +0 -8
- package/templates/api/src/boards/generators/implementations/kie/video/veo3.py +0 -161
- package/templates/api/src/boards/generators/implementations/openai/__init__.py +0 -1
- package/templates/api/src/boards/generators/implementations/openai/audio/__init__.py +0 -1
- package/templates/api/src/boards/generators/implementations/openai/audio/whisper.py +0 -69
- package/templates/api/src/boards/generators/implementations/openai/image/__init__.py +0 -1
- package/templates/api/src/boards/generators/implementations/openai/image/dalle3.py +0 -96
- package/templates/api/src/boards/generators/implementations/replicate/__init__.py +0 -1
- package/templates/api/src/boards/generators/implementations/replicate/image/__init__.py +0 -1
- package/templates/api/src/boards/generators/implementations/replicate/image/flux_pro.py +0 -88
- package/templates/api/src/boards/generators/implementations/replicate/video/__init__.py +0 -1
- package/templates/api/src/boards/generators/implementations/replicate/video/lipsync.py +0 -73
- package/templates/api/src/boards/generators/loader.py +0 -253
- package/templates/api/src/boards/generators/registry.py +0 -114
- package/templates/api/src/boards/generators/resolution.py +0 -632
- package/templates/api/src/boards/generators/testmods/class_gen.py +0 -34
- package/templates/api/src/boards/generators/testmods/import_side_effect.py +0 -35
- package/templates/api/src/boards/graphql/__init__.py +0 -7
- package/templates/api/src/boards/graphql/access_control.py +0 -136
- package/templates/api/src/boards/graphql/mutations/root.py +0 -148
- package/templates/api/src/boards/graphql/queries/root.py +0 -116
- package/templates/api/src/boards/graphql/resolvers/__init__.py +0 -8
- package/templates/api/src/boards/graphql/resolvers/auth.py +0 -12
- package/templates/api/src/boards/graphql/resolvers/board.py +0 -1053
- package/templates/api/src/boards/graphql/resolvers/generation.py +0 -666
- package/templates/api/src/boards/graphql/resolvers/generator.py +0 -50
- package/templates/api/src/boards/graphql/resolvers/lineage.py +0 -381
- package/templates/api/src/boards/graphql/resolvers/upload.py +0 -463
- package/templates/api/src/boards/graphql/resolvers/user.py +0 -25
- package/templates/api/src/boards/graphql/schema.py +0 -81
- package/templates/api/src/boards/graphql/types/board.py +0 -102
- package/templates/api/src/boards/graphql/types/generation.py +0 -166
- package/templates/api/src/boards/graphql/types/generator.py +0 -17
- package/templates/api/src/boards/graphql/types/user.py +0 -47
- package/templates/api/src/boards/jobs/repository.py +0 -153
- package/templates/api/src/boards/logging.py +0 -195
- package/templates/api/src/boards/middleware.py +0 -339
- package/templates/api/src/boards/progress/__init__.py +0 -4
- package/templates/api/src/boards/progress/models.py +0 -25
- package/templates/api/src/boards/progress/publisher.py +0 -64
- package/templates/api/src/boards/py.typed +0 -0
- package/templates/api/src/boards/redis_pool.py +0 -118
- package/templates/api/src/boards/storage/__init__.py +0 -52
- package/templates/api/src/boards/storage/base.py +0 -363
- package/templates/api/src/boards/storage/config.py +0 -187
- package/templates/api/src/boards/storage/factory.py +0 -288
- package/templates/api/src/boards/storage/implementations/__init__.py +0 -27
- package/templates/api/src/boards/storage/implementations/gcs.py +0 -340
- package/templates/api/src/boards/storage/implementations/local.py +0 -201
- package/templates/api/src/boards/storage/implementations/s3.py +0 -294
- package/templates/api/src/boards/storage/implementations/supabase.py +0 -218
- package/templates/api/src/boards/tenant_isolation.py +0 -446
- package/templates/api/src/boards/validation.py +0 -262
- package/templates/api/src/boards/workers/__init__.py +0 -1
- package/templates/api/src/boards/workers/actors.py +0 -274
- package/templates/api/src/boards/workers/cli.py +0 -125
- package/templates/api/src/boards/workers/context.py +0 -348
- package/templates/api/src/boards/workers/middleware.py +0 -58
- package/templates/api/src/py.typed +0 -0
- package/templates/compose.web.yaml +0 -35
- package/templates/compose.yaml +0 -116
- package/templates/docker/env.example +0 -23
- package/templates/web/.env.example +0 -28
- package/templates/web/Dockerfile +0 -51
- package/templates/web/components.json +0 -22
- package/templates/web/imageLoader.js +0 -18
- package/templates/web/next-env.d.ts +0 -5
- package/templates/web/next.config.js +0 -36
- package/templates/web/package.json +0 -41
- package/templates/web/postcss.config.mjs +0 -7
- package/templates/web/public/favicon.ico +0 -0
- package/templates/web/src/app/boards/[boardId]/page.tsx +0 -353
- package/templates/web/src/app/globals.css +0 -123
- package/templates/web/src/app/layout.tsx +0 -31
- package/templates/web/src/app/lineage/[generationId]/page.tsx +0 -235
- package/templates/web/src/app/page.tsx +0 -35
- package/templates/web/src/app/providers.tsx +0 -18
- package/templates/web/src/components/boards/ArtifactInputSlots.tsx +0 -206
- package/templates/web/src/components/boards/ArtifactPreview.tsx +0 -466
- package/templates/web/src/components/boards/GenerationGrid.tsx +0 -282
- package/templates/web/src/components/boards/GenerationInput.tsx +0 -370
- package/templates/web/src/components/boards/GeneratorSelector.tsx +0 -272
- package/templates/web/src/components/boards/UploadArtifact.tsx +0 -563
- package/templates/web/src/components/header.tsx +0 -32
- package/templates/web/src/components/theme-provider.tsx +0 -10
- package/templates/web/src/components/theme-toggle.tsx +0 -75
- package/templates/web/src/components/ui/alert-dialog.tsx +0 -157
- package/templates/web/src/components/ui/button.tsx +0 -58
- package/templates/web/src/components/ui/card.tsx +0 -92
- package/templates/web/src/components/ui/dropdown-menu.tsx +0 -200
- package/templates/web/src/components/ui/navigation-menu.tsx +0 -168
- package/templates/web/src/components/ui/toast.tsx +0 -128
- package/templates/web/src/components/ui/toaster.tsx +0 -35
- package/templates/web/src/components/ui/use-toast.ts +0 -187
- package/templates/web/src/hooks/useGeneratorMRU.ts +0 -57
- package/templates/web/src/lib/utils.ts +0 -6
- package/templates/web/tsconfig.json +0 -41
|
@@ -1,194 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Google Veo 3 text-to-video generator.
|
|
3
|
-
|
|
4
|
-
The most advanced AI video generation model in the world by Google, capable of
|
|
5
|
-
generating high-quality videos from text prompts with optional audio synthesis.
|
|
6
|
-
|
|
7
|
-
Based on Fal AI's fal-ai/veo3 model.
|
|
8
|
-
See: https://fal.ai/models/fal-ai/veo3
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
import os
|
|
12
|
-
from typing import Literal
|
|
13
|
-
|
|
14
|
-
from pydantic import BaseModel, Field
|
|
15
|
-
|
|
16
|
-
from ....base import BaseGenerator, GeneratorExecutionContext, GeneratorResult
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class Veo3Input(BaseModel):
|
|
20
|
-
"""Input schema for Google Veo 3 text-to-video generation."""
|
|
21
|
-
|
|
22
|
-
prompt: str = Field(description="The text prompt describing the video you want to generate")
|
|
23
|
-
aspect_ratio: Literal["9:16", "16:9", "1:1"] = Field(
|
|
24
|
-
default="16:9",
|
|
25
|
-
description="Aspect ratio of the generated video. If 1:1, video will be outpainted",
|
|
26
|
-
)
|
|
27
|
-
duration: Literal["4s", "6s", "8s"] = Field(
|
|
28
|
-
default="8s",
|
|
29
|
-
description="Duration of the generated video",
|
|
30
|
-
)
|
|
31
|
-
resolution: Literal["720p", "1080p"] = Field(
|
|
32
|
-
default="720p",
|
|
33
|
-
description="Resolution of the generated video",
|
|
34
|
-
)
|
|
35
|
-
generate_audio: bool = Field(
|
|
36
|
-
default=True,
|
|
37
|
-
description="Whether to generate audio for the video. If false, 50% less credits used",
|
|
38
|
-
)
|
|
39
|
-
enhance_prompt: bool = Field(
|
|
40
|
-
default=True,
|
|
41
|
-
description="Whether to enhance video generation",
|
|
42
|
-
)
|
|
43
|
-
auto_fix: bool = Field(
|
|
44
|
-
default=True,
|
|
45
|
-
description="Automatically attempt to fix prompts that fail content policy",
|
|
46
|
-
)
|
|
47
|
-
seed: int | None = Field(
|
|
48
|
-
default=None,
|
|
49
|
-
description="Seed value for reproducible generation",
|
|
50
|
-
)
|
|
51
|
-
negative_prompt: str | None = Field(
|
|
52
|
-
default=None,
|
|
53
|
-
description="Guidance text to exclude from generation",
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
class FalVeo3Generator(BaseGenerator):
|
|
58
|
-
"""Generator for text-to-video using Google Veo 3."""
|
|
59
|
-
|
|
60
|
-
name = "fal-veo3"
|
|
61
|
-
description = "Fal: Veo 3 - Google's most advanced AI video generation model"
|
|
62
|
-
artifact_type = "video"
|
|
63
|
-
|
|
64
|
-
def get_input_schema(self) -> type[Veo3Input]:
|
|
65
|
-
"""Return the input schema for this generator."""
|
|
66
|
-
return Veo3Input
|
|
67
|
-
|
|
68
|
-
async def generate(
|
|
69
|
-
self, inputs: Veo3Input, context: GeneratorExecutionContext
|
|
70
|
-
) -> GeneratorResult:
|
|
71
|
-
"""Generate video using fal.ai veo3."""
|
|
72
|
-
# Check for API key
|
|
73
|
-
if not os.getenv("FAL_KEY"):
|
|
74
|
-
raise ValueError("API configuration invalid. Missing FAL_KEY environment variable")
|
|
75
|
-
|
|
76
|
-
# Import fal_client
|
|
77
|
-
try:
|
|
78
|
-
import fal_client
|
|
79
|
-
except ImportError as e:
|
|
80
|
-
raise ImportError(
|
|
81
|
-
"fal.ai SDK is required for FalVeo3Generator. "
|
|
82
|
-
"Install with: pip install weirdfingers-boards[generators-fal]"
|
|
83
|
-
) from e
|
|
84
|
-
|
|
85
|
-
# Prepare arguments for fal.ai API
|
|
86
|
-
arguments = {
|
|
87
|
-
"prompt": inputs.prompt,
|
|
88
|
-
"aspect_ratio": inputs.aspect_ratio,
|
|
89
|
-
"duration": inputs.duration,
|
|
90
|
-
"resolution": inputs.resolution,
|
|
91
|
-
"generate_audio": inputs.generate_audio,
|
|
92
|
-
"enhance_prompt": inputs.enhance_prompt,
|
|
93
|
-
"auto_fix": inputs.auto_fix,
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
# Add optional parameters if provided
|
|
97
|
-
if inputs.seed is not None:
|
|
98
|
-
arguments["seed"] = inputs.seed
|
|
99
|
-
if inputs.negative_prompt is not None:
|
|
100
|
-
arguments["negative_prompt"] = inputs.negative_prompt
|
|
101
|
-
|
|
102
|
-
# Submit async job
|
|
103
|
-
handler = await fal_client.submit_async(
|
|
104
|
-
"fal-ai/veo3",
|
|
105
|
-
arguments=arguments,
|
|
106
|
-
)
|
|
107
|
-
|
|
108
|
-
# Store external job ID
|
|
109
|
-
await context.set_external_job_id(handler.request_id)
|
|
110
|
-
|
|
111
|
-
# Stream progress updates
|
|
112
|
-
from .....progress.models import ProgressUpdate
|
|
113
|
-
|
|
114
|
-
event_count = 0
|
|
115
|
-
async for event in handler.iter_events(with_logs=True):
|
|
116
|
-
event_count += 1
|
|
117
|
-
# Sample every 3rd event to avoid spam
|
|
118
|
-
if event_count % 3 == 0:
|
|
119
|
-
# Extract logs if available
|
|
120
|
-
logs = getattr(event, "logs", None)
|
|
121
|
-
if logs:
|
|
122
|
-
# Join log entries into a single message
|
|
123
|
-
if isinstance(logs, list):
|
|
124
|
-
message = " | ".join(str(log) for log in logs if log)
|
|
125
|
-
else:
|
|
126
|
-
message = str(logs)
|
|
127
|
-
|
|
128
|
-
if message:
|
|
129
|
-
await context.publish_progress(
|
|
130
|
-
ProgressUpdate(
|
|
131
|
-
job_id=handler.request_id,
|
|
132
|
-
status="processing",
|
|
133
|
-
progress=50.0,
|
|
134
|
-
phase="processing",
|
|
135
|
-
message=message,
|
|
136
|
-
)
|
|
137
|
-
)
|
|
138
|
-
|
|
139
|
-
# Get final result
|
|
140
|
-
result = await handler.get()
|
|
141
|
-
|
|
142
|
-
# Extract video from result
|
|
143
|
-
# Expected structure: {"video": {"url": "...", "content_type": "...", ...}}
|
|
144
|
-
video_data = result.get("video")
|
|
145
|
-
if not video_data:
|
|
146
|
-
raise ValueError("No video returned from fal.ai API")
|
|
147
|
-
|
|
148
|
-
video_url = video_data.get("url")
|
|
149
|
-
if not video_url:
|
|
150
|
-
raise ValueError("Video missing URL in fal.ai response")
|
|
151
|
-
|
|
152
|
-
# Determine video dimensions based on resolution and aspect ratio
|
|
153
|
-
if inputs.resolution == "720p":
|
|
154
|
-
if inputs.aspect_ratio == "16:9":
|
|
155
|
-
width, height = 1280, 720
|
|
156
|
-
elif inputs.aspect_ratio == "9:16":
|
|
157
|
-
width, height = 720, 1280
|
|
158
|
-
else: # 1:1
|
|
159
|
-
width, height = 720, 720
|
|
160
|
-
else: # 1080p
|
|
161
|
-
if inputs.aspect_ratio == "16:9":
|
|
162
|
-
width, height = 1920, 1080
|
|
163
|
-
elif inputs.aspect_ratio == "9:16":
|
|
164
|
-
width, height = 1080, 1920
|
|
165
|
-
else: # 1:1
|
|
166
|
-
width, height = 1080, 1080
|
|
167
|
-
|
|
168
|
-
# Parse duration from "8s" format
|
|
169
|
-
duration_seconds = int(inputs.duration.rstrip("s"))
|
|
170
|
-
|
|
171
|
-
# Store video result
|
|
172
|
-
artifact = await context.store_video_result(
|
|
173
|
-
storage_url=video_url,
|
|
174
|
-
format="mp4",
|
|
175
|
-
width=width,
|
|
176
|
-
height=height,
|
|
177
|
-
duration=duration_seconds,
|
|
178
|
-
output_index=0,
|
|
179
|
-
)
|
|
180
|
-
|
|
181
|
-
return GeneratorResult(outputs=[artifact])
|
|
182
|
-
|
|
183
|
-
async def estimate_cost(self, inputs: Veo3Input) -> float:
|
|
184
|
-
"""Estimate cost for this generation in USD.
|
|
185
|
-
|
|
186
|
-
Note: Pricing information not available in Fal documentation.
|
|
187
|
-
Using placeholder value that should be updated with actual pricing.
|
|
188
|
-
"""
|
|
189
|
-
# TODO: Update with actual pricing from Fal when available
|
|
190
|
-
# Base cost, with 50% reduction if audio is disabled
|
|
191
|
-
base_cost = 0.15 # Placeholder estimate
|
|
192
|
-
if not inputs.generate_audio:
|
|
193
|
-
return base_cost * 0.5
|
|
194
|
-
return base_cost
|
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Google Veo 3.1 text-to-video generator.
|
|
3
|
-
|
|
4
|
-
The most advanced AI video generation model in the world by Google, featuring
|
|
5
|
-
audio generation capabilities and enhanced quality over Veo 3.
|
|
6
|
-
|
|
7
|
-
Based on Fal AI's fal-ai/veo3.1 model.
|
|
8
|
-
See: https://fal.ai/models/fal-ai/veo3.1
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
import os
|
|
12
|
-
from typing import Literal
|
|
13
|
-
|
|
14
|
-
from pydantic import BaseModel, Field
|
|
15
|
-
|
|
16
|
-
from ....base import BaseGenerator, GeneratorExecutionContext, GeneratorResult
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class Veo31Input(BaseModel):
|
|
20
|
-
"""Input schema for Google Veo 3.1 text-to-video generation."""
|
|
21
|
-
|
|
22
|
-
prompt: str = Field(description="The text prompt describing the video you want to generate")
|
|
23
|
-
aspect_ratio: Literal["9:16", "16:9"] = Field(
|
|
24
|
-
default="16:9",
|
|
25
|
-
description="Aspect ratio of the generated video",
|
|
26
|
-
)
|
|
27
|
-
duration: Literal["4s", "6s", "8s"] = Field(
|
|
28
|
-
default="8s",
|
|
29
|
-
description="Duration of the generated video",
|
|
30
|
-
)
|
|
31
|
-
resolution: Literal["720p", "1080p"] = Field(
|
|
32
|
-
default="720p",
|
|
33
|
-
description="Resolution of the generated video",
|
|
34
|
-
)
|
|
35
|
-
generate_audio: bool = Field(
|
|
36
|
-
default=True,
|
|
37
|
-
description="Whether to generate audio for the video. If false, 50% less credits used",
|
|
38
|
-
)
|
|
39
|
-
enhance_prompt: bool = Field(
|
|
40
|
-
default=True,
|
|
41
|
-
description="Whether to enhance video generation quality",
|
|
42
|
-
)
|
|
43
|
-
auto_fix: bool = Field(
|
|
44
|
-
default=True,
|
|
45
|
-
description="Automatically attempt to rewrite prompts that fail content policy validation",
|
|
46
|
-
)
|
|
47
|
-
seed: int | None = Field(
|
|
48
|
-
default=None,
|
|
49
|
-
description="Seed value for reproducible generation",
|
|
50
|
-
)
|
|
51
|
-
negative_prompt: str | None = Field(
|
|
52
|
-
default=None,
|
|
53
|
-
description="Guidance text to exclude elements from generation",
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
class FalVeo31Generator(BaseGenerator):
|
|
58
|
-
"""Generator for text-to-video using Google Veo 3.1."""
|
|
59
|
-
|
|
60
|
-
name = "fal-veo31"
|
|
61
|
-
description = "Fal: Veo 3.1 - Google's most advanced AI video generation model with audio"
|
|
62
|
-
artifact_type = "video"
|
|
63
|
-
|
|
64
|
-
def get_input_schema(self) -> type[Veo31Input]:
|
|
65
|
-
"""Return the input schema for this generator."""
|
|
66
|
-
return Veo31Input
|
|
67
|
-
|
|
68
|
-
async def generate(
|
|
69
|
-
self, inputs: Veo31Input, context: GeneratorExecutionContext
|
|
70
|
-
) -> GeneratorResult:
|
|
71
|
-
"""Generate video using fal.ai veo3.1."""
|
|
72
|
-
# Check for API key
|
|
73
|
-
if not os.getenv("FAL_KEY"):
|
|
74
|
-
raise ValueError("API configuration invalid. Missing FAL_KEY environment variable")
|
|
75
|
-
|
|
76
|
-
# Import fal_client
|
|
77
|
-
try:
|
|
78
|
-
import fal_client
|
|
79
|
-
except ImportError as e:
|
|
80
|
-
raise ImportError(
|
|
81
|
-
"fal.ai SDK is required for FalVeo31Generator. "
|
|
82
|
-
"Install with: pip install weirdfingers-boards[generators-fal]"
|
|
83
|
-
) from e
|
|
84
|
-
|
|
85
|
-
# Prepare arguments for fal.ai API
|
|
86
|
-
arguments = {
|
|
87
|
-
"prompt": inputs.prompt,
|
|
88
|
-
"aspect_ratio": inputs.aspect_ratio,
|
|
89
|
-
"duration": inputs.duration,
|
|
90
|
-
"resolution": inputs.resolution,
|
|
91
|
-
"generate_audio": inputs.generate_audio,
|
|
92
|
-
"enhance_prompt": inputs.enhance_prompt,
|
|
93
|
-
"auto_fix": inputs.auto_fix,
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
# Add optional parameters if provided
|
|
97
|
-
if inputs.seed is not None:
|
|
98
|
-
arguments["seed"] = inputs.seed
|
|
99
|
-
if inputs.negative_prompt is not None:
|
|
100
|
-
arguments["negative_prompt"] = inputs.negative_prompt
|
|
101
|
-
|
|
102
|
-
# Submit async job
|
|
103
|
-
handler = await fal_client.submit_async(
|
|
104
|
-
"fal-ai/veo3.1",
|
|
105
|
-
arguments=arguments,
|
|
106
|
-
)
|
|
107
|
-
|
|
108
|
-
# Store external job ID
|
|
109
|
-
await context.set_external_job_id(handler.request_id)
|
|
110
|
-
|
|
111
|
-
# Stream progress updates
|
|
112
|
-
from .....progress.models import ProgressUpdate
|
|
113
|
-
|
|
114
|
-
event_count = 0
|
|
115
|
-
async for event in handler.iter_events(with_logs=True):
|
|
116
|
-
event_count += 1
|
|
117
|
-
# Sample every 3rd event to avoid spam
|
|
118
|
-
if event_count % 3 == 0:
|
|
119
|
-
# Extract logs if available
|
|
120
|
-
logs = getattr(event, "logs", None)
|
|
121
|
-
if logs:
|
|
122
|
-
# Join log entries into a single message
|
|
123
|
-
if isinstance(logs, list):
|
|
124
|
-
message = " | ".join(str(log) for log in logs if log)
|
|
125
|
-
else:
|
|
126
|
-
message = str(logs)
|
|
127
|
-
|
|
128
|
-
if message:
|
|
129
|
-
await context.publish_progress(
|
|
130
|
-
ProgressUpdate(
|
|
131
|
-
job_id=handler.request_id,
|
|
132
|
-
status="processing",
|
|
133
|
-
progress=50.0,
|
|
134
|
-
phase="processing",
|
|
135
|
-
message=message,
|
|
136
|
-
)
|
|
137
|
-
)
|
|
138
|
-
|
|
139
|
-
# Get final result
|
|
140
|
-
result = await handler.get()
|
|
141
|
-
|
|
142
|
-
# Extract video from result
|
|
143
|
-
# Expected structure: {"video": {"url": "...", "content_type": "...", ...}}
|
|
144
|
-
video_data = result.get("video")
|
|
145
|
-
if not video_data:
|
|
146
|
-
raise ValueError("No video returned from fal.ai API")
|
|
147
|
-
|
|
148
|
-
video_url = video_data.get("url")
|
|
149
|
-
if not video_url:
|
|
150
|
-
raise ValueError("Video missing URL in fal.ai response")
|
|
151
|
-
|
|
152
|
-
# Determine video dimensions based on resolution and aspect ratio
|
|
153
|
-
if inputs.resolution == "720p":
|
|
154
|
-
if inputs.aspect_ratio == "16:9":
|
|
155
|
-
width, height = 1280, 720
|
|
156
|
-
else: # 9:16
|
|
157
|
-
width, height = 720, 1280
|
|
158
|
-
else: # 1080p
|
|
159
|
-
if inputs.aspect_ratio == "16:9":
|
|
160
|
-
width, height = 1920, 1080
|
|
161
|
-
else: # 9:16
|
|
162
|
-
width, height = 1080, 1920
|
|
163
|
-
|
|
164
|
-
# Parse duration from "8s" format
|
|
165
|
-
duration_seconds = int(inputs.duration.rstrip("s"))
|
|
166
|
-
|
|
167
|
-
# Store video result
|
|
168
|
-
artifact = await context.store_video_result(
|
|
169
|
-
storage_url=video_url,
|
|
170
|
-
format="mp4",
|
|
171
|
-
width=width,
|
|
172
|
-
height=height,
|
|
173
|
-
duration=duration_seconds,
|
|
174
|
-
output_index=0,
|
|
175
|
-
)
|
|
176
|
-
|
|
177
|
-
return GeneratorResult(outputs=[artifact])
|
|
178
|
-
|
|
179
|
-
async def estimate_cost(self, inputs: Veo31Input) -> float:
|
|
180
|
-
"""Estimate cost for this generation in USD.
|
|
181
|
-
|
|
182
|
-
Note: Pricing information not available in Fal documentation.
|
|
183
|
-
Using placeholder value that should be updated with actual pricing.
|
|
184
|
-
"""
|
|
185
|
-
# TODO: Update with actual pricing from Fal when available
|
|
186
|
-
# Base cost, with 50% reduction if audio is disabled
|
|
187
|
-
base_cost = 0.15 # Placeholder estimate
|
|
188
|
-
if not inputs.generate_audio:
|
|
189
|
-
return base_cost * 0.5
|
|
190
|
-
return base_cost
|
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Google Veo 3.1 Fast text-to-video generator.
|
|
3
|
-
|
|
4
|
-
A faster, more cost-effective variant of Google's Veo 3.1 video generation model,
|
|
5
|
-
capable of generating high-quality videos from text prompts with optional audio synthesis.
|
|
6
|
-
|
|
7
|
-
Based on Fal AI's fal-ai/veo3.1/fast model.
|
|
8
|
-
See: https://fal.ai/models/fal-ai/veo3.1/fast
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
import os
|
|
12
|
-
from typing import Literal
|
|
13
|
-
|
|
14
|
-
from pydantic import BaseModel, Field
|
|
15
|
-
|
|
16
|
-
from ....base import BaseGenerator, GeneratorExecutionContext, GeneratorResult
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class Veo31FastInput(BaseModel):
|
|
20
|
-
"""Input schema for Google Veo 3.1 Fast text-to-video generation."""
|
|
21
|
-
|
|
22
|
-
prompt: str = Field(description="The text prompt describing the video you want to generate")
|
|
23
|
-
aspect_ratio: Literal["9:16", "16:9"] = Field(
|
|
24
|
-
default="16:9",
|
|
25
|
-
description="Aspect ratio of the generated video",
|
|
26
|
-
)
|
|
27
|
-
duration: Literal["4s", "6s", "8s"] = Field(
|
|
28
|
-
default="8s",
|
|
29
|
-
description="Duration of the generated video",
|
|
30
|
-
)
|
|
31
|
-
resolution: Literal["720p", "1080p"] = Field(
|
|
32
|
-
default="720p",
|
|
33
|
-
description="Resolution of the generated video",
|
|
34
|
-
)
|
|
35
|
-
generate_audio: bool = Field(
|
|
36
|
-
default=True,
|
|
37
|
-
description="Whether to generate audio for the video. If false, 33% less credits used",
|
|
38
|
-
)
|
|
39
|
-
enhance_prompt: bool = Field(
|
|
40
|
-
default=True,
|
|
41
|
-
description="Whether to enhance video generation",
|
|
42
|
-
)
|
|
43
|
-
auto_fix: bool = Field(
|
|
44
|
-
default=True,
|
|
45
|
-
description="Automatically attempt to fix prompts that fail content policy",
|
|
46
|
-
)
|
|
47
|
-
seed: int | None = Field(
|
|
48
|
-
default=None,
|
|
49
|
-
description="Seed value for reproducible generation",
|
|
50
|
-
)
|
|
51
|
-
negative_prompt: str | None = Field(
|
|
52
|
-
default=None,
|
|
53
|
-
description="Guidance text to exclude from generation",
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
class FalVeo31FastGenerator(BaseGenerator):
|
|
58
|
-
"""Generator for text-to-video using Google Veo 3.1 Fast."""
|
|
59
|
-
|
|
60
|
-
name = "fal-veo31-fast"
|
|
61
|
-
description = "Fal: Veo 3.1 Fast - Google's fast AI video generation model"
|
|
62
|
-
artifact_type = "video"
|
|
63
|
-
|
|
64
|
-
def get_input_schema(self) -> type[Veo31FastInput]:
|
|
65
|
-
"""Return the input schema for this generator."""
|
|
66
|
-
return Veo31FastInput
|
|
67
|
-
|
|
68
|
-
async def generate(
|
|
69
|
-
self, inputs: Veo31FastInput, context: GeneratorExecutionContext
|
|
70
|
-
) -> GeneratorResult:
|
|
71
|
-
"""Generate video using fal.ai veo3.1/fast."""
|
|
72
|
-
# Check for API key
|
|
73
|
-
if not os.getenv("FAL_KEY"):
|
|
74
|
-
raise ValueError("API configuration invalid. Missing FAL_KEY environment variable")
|
|
75
|
-
|
|
76
|
-
# Import fal_client
|
|
77
|
-
try:
|
|
78
|
-
import fal_client
|
|
79
|
-
except ImportError as e:
|
|
80
|
-
raise ImportError(
|
|
81
|
-
"fal.ai SDK is required for FalVeo31FastGenerator. "
|
|
82
|
-
"Install with: pip install weirdfingers-boards[generators-fal]"
|
|
83
|
-
) from e
|
|
84
|
-
|
|
85
|
-
# Prepare arguments for fal.ai API
|
|
86
|
-
arguments = {
|
|
87
|
-
"prompt": inputs.prompt,
|
|
88
|
-
"aspect_ratio": inputs.aspect_ratio,
|
|
89
|
-
"duration": inputs.duration,
|
|
90
|
-
"resolution": inputs.resolution,
|
|
91
|
-
"generate_audio": inputs.generate_audio,
|
|
92
|
-
"enhance_prompt": inputs.enhance_prompt,
|
|
93
|
-
"auto_fix": inputs.auto_fix,
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
# Add optional parameters if provided
|
|
97
|
-
if inputs.seed is not None:
|
|
98
|
-
arguments["seed"] = inputs.seed
|
|
99
|
-
if inputs.negative_prompt is not None:
|
|
100
|
-
arguments["negative_prompt"] = inputs.negative_prompt
|
|
101
|
-
|
|
102
|
-
# Submit async job
|
|
103
|
-
handler = await fal_client.submit_async(
|
|
104
|
-
"fal-ai/veo3.1/fast",
|
|
105
|
-
arguments=arguments,
|
|
106
|
-
)
|
|
107
|
-
|
|
108
|
-
# Store external job ID
|
|
109
|
-
await context.set_external_job_id(handler.request_id)
|
|
110
|
-
|
|
111
|
-
# Stream progress updates
|
|
112
|
-
from .....progress.models import ProgressUpdate
|
|
113
|
-
|
|
114
|
-
event_count = 0
|
|
115
|
-
async for event in handler.iter_events(with_logs=True):
|
|
116
|
-
event_count += 1
|
|
117
|
-
# Sample every 3rd event to avoid spam
|
|
118
|
-
if event_count % 3 == 0:
|
|
119
|
-
# Extract logs if available
|
|
120
|
-
logs = getattr(event, "logs", None)
|
|
121
|
-
if logs:
|
|
122
|
-
# Join log entries into a single message
|
|
123
|
-
if isinstance(logs, list):
|
|
124
|
-
message = " | ".join(str(log) for log in logs if log)
|
|
125
|
-
else:
|
|
126
|
-
message = str(logs)
|
|
127
|
-
|
|
128
|
-
if message:
|
|
129
|
-
await context.publish_progress(
|
|
130
|
-
ProgressUpdate(
|
|
131
|
-
job_id=handler.request_id,
|
|
132
|
-
status="processing",
|
|
133
|
-
progress=50.0,
|
|
134
|
-
phase="processing",
|
|
135
|
-
message=message,
|
|
136
|
-
)
|
|
137
|
-
)
|
|
138
|
-
|
|
139
|
-
# Get final result
|
|
140
|
-
result = await handler.get()
|
|
141
|
-
|
|
142
|
-
# Extract video from result
|
|
143
|
-
# Expected structure: {"video": {"url": "...", "content_type": "...", ...}}
|
|
144
|
-
video_data = result.get("video")
|
|
145
|
-
if not video_data:
|
|
146
|
-
raise ValueError("No video returned from fal.ai API")
|
|
147
|
-
|
|
148
|
-
video_url = video_data.get("url")
|
|
149
|
-
if not video_url:
|
|
150
|
-
raise ValueError("Video missing URL in fal.ai response")
|
|
151
|
-
|
|
152
|
-
# Determine video dimensions based on resolution and aspect ratio
|
|
153
|
-
if inputs.resolution == "720p":
|
|
154
|
-
if inputs.aspect_ratio == "16:9":
|
|
155
|
-
width, height = 1280, 720
|
|
156
|
-
else: # 9:16
|
|
157
|
-
width, height = 720, 1280
|
|
158
|
-
else: # 1080p
|
|
159
|
-
if inputs.aspect_ratio == "16:9":
|
|
160
|
-
width, height = 1920, 1080
|
|
161
|
-
else: # 9:16
|
|
162
|
-
width, height = 1080, 1920
|
|
163
|
-
|
|
164
|
-
# Parse duration from "8s" format
|
|
165
|
-
duration_seconds = int(inputs.duration.rstrip("s"))
|
|
166
|
-
|
|
167
|
-
# Store video result
|
|
168
|
-
artifact = await context.store_video_result(
|
|
169
|
-
storage_url=video_url,
|
|
170
|
-
format="mp4",
|
|
171
|
-
width=width,
|
|
172
|
-
height=height,
|
|
173
|
-
duration=duration_seconds,
|
|
174
|
-
output_index=0,
|
|
175
|
-
)
|
|
176
|
-
|
|
177
|
-
return GeneratorResult(outputs=[artifact])
|
|
178
|
-
|
|
179
|
-
async def estimate_cost(self, inputs: Veo31FastInput) -> float:
|
|
180
|
-
"""Estimate cost for this generation in USD.
|
|
181
|
-
|
|
182
|
-
Note: Pricing information not available in Fal documentation.
|
|
183
|
-
Using placeholder value that should be updated with actual pricing.
|
|
184
|
-
"""
|
|
185
|
-
# TODO: Update with actual pricing from Fal when available
|
|
186
|
-
# Base cost, with 33% reduction if audio is disabled
|
|
187
|
-
base_cost = 0.10 # Placeholder estimate for fast variant
|
|
188
|
-
if not inputs.generate_audio:
|
|
189
|
-
return base_cost * 0.67 # 33% discount
|
|
190
|
-
return base_cost
|