Source: Dreamverse repo at will/integrate-public-fastvideo @ ec8ef92.
Cross-repo move; original history retained in archived Dreamverse repo.
Per .agents/memory/dreamverse-integration/integration-plan.md Phase 2.
* PRODUCT files moved to apps/dreamverse/server/: main.py, config.py,
video_generation.py, session/controller.py, session/messages.py,
routes/presets.py + 5 product test files + product prompts.
* GENERIC-PENDING shims carried (replaced in Phase 4/5): runtime.py,
utils.py, prompt_safety.py, rewrite_prompt_payload.py,
routes/health.py, prompt_enhancer.py.
* Imports rewritten: gpu_pool/worker_ipc/session_init_image/session_logger
now import from fastvideo.entrypoints.streaming.* public modules.
* Public streaming compatibility aliases added for the migrated product
controller: GPUSlot/get_available_gpus, MediaChunk/MediaComplete,
cleanup_session_init_image, and SessionEventLogger.
* Path rewrites: _APP_ROOT/"apps"/"web" -> _APP_ROOT/"web" in config.py.
* GPU marker: test_realtime_stress.py and test_session_logging.py
marked @pytest.mark.gpu (skip-by-default in CI).
* New: apps/dreamverse/server/tests/test_import_contract.py — AST gate
forbidding fastvideo.{pipelines,models,layers,worker,fastvideo_args}.
Generic-merged files NOT copied (already on public FastVideo):
gpu_pool.py, av_streaming.py, worker_ipc.py, mock_server.py,
session_init_image.py, session_logger.py.
Co-authored-by: Junda (David) Su <90978028+Davids048@users.noreply.github.com>
Co-authored-by: Matthew Noto <99706358+RandNMR73@users.noreply.github.com>
Co-authored-by: XOR-op <17672363+XOR-op@users.noreply.github.com>
Co-authored-by: Zhang Peiyuan <42993249+jzhang38@users.noreply.github.com>
276 lines
8.7 KiB
Python
276 lines
8.7 KiB
Python
import os
|
|
from pathlib import Path
|
|
|
|
_REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
_SERVER_ROOT = Path(__file__).resolve().parent
|
|
_PROMPTS_ROOT = _SERVER_ROOT / "prompts"
|
|
_PROMPTS_LOCAL_ROOT = _SERVER_ROOT / "prompts.local"
|
|
_APP_ROOT = _REPO_ROOT
|
|
|
|
|
|
def _resolve_frontend_root() -> Path:
|
|
for candidate in (
|
|
_APP_ROOT / "web",
|
|
_APP_ROOT / "prod-ui",
|
|
):
|
|
if candidate.is_dir():
|
|
return candidate
|
|
return _APP_ROOT / "web"
|
|
|
|
|
|
FRONTEND_ROOT = _resolve_frontend_root()
|
|
_CLIENT_PROMPTS_ROOT = FRONTEND_ROOT / "prompts"
|
|
_CLIENT_PROMPTS_LOCAL_ROOT = FRONTEND_ROOT / "prompts.local"
|
|
FRONTEND_STATIC_DIR_CANDIDATES = tuple(str(FRONTEND_ROOT / dirname) for dirname in ("out", "dist"))
|
|
|
|
# Model registry
|
|
MODEL_REGISTRY = {
|
|
"fast-ltx2": {
|
|
"name": "FastLTX2",
|
|
"model_path": "FastVideo/LTX2-Distilled-Diffusers",
|
|
"config_model_path": "FastVideo/LTX2-Distilled-Diffusers",
|
|
},
|
|
"fast-ltx23": {
|
|
"name": "FastLTX23",
|
|
"model_path": "FastVideo/LTX-2.3-Distilled-Diffusers",
|
|
"config_model_path": "FastVideo/LTX-2.3-Distilled-Diffusers",
|
|
},
|
|
}
|
|
|
|
DEFAULT_MODEL_ID = "fast-ltx2"
|
|
|
|
# Active model configuration
|
|
MODEL_CONFIG = MODEL_REGISTRY[DEFAULT_MODEL_ID]
|
|
|
|
# Generation limits
|
|
SESSION_TIMEOUT_SECONDS = 300
|
|
|
|
# Frame settings
|
|
NUM_FRAMES = 121
|
|
FRAME_HEIGHT = 1088
|
|
FRAME_WIDTH = 1920
|
|
NUM_INFERENCE_STEPS = 5
|
|
JPEG_QUALITY = 100
|
|
BATCH_SIZE = 3
|
|
|
|
# Streaming mode:
|
|
# - legacy_jpeg: send frame_batch JSON payloads with base64 JPEGs
|
|
# - av_fmp4: send muxed fMP4 binary chunks over WebSocket
|
|
STREAM_MODE = os.getenv("STREAM_MODE", "av_fmp4").strip().lower()
|
|
|
|
|
|
def _env_int(name: str, default: int) -> int:
|
|
value = os.getenv(name)
|
|
if value is None:
|
|
return default
|
|
try:
|
|
return int(value)
|
|
except ValueError:
|
|
return default
|
|
|
|
|
|
def _env_float(name: str, default: float) -> float:
|
|
value = os.getenv(name)
|
|
if value is None:
|
|
return default
|
|
try:
|
|
return float(value)
|
|
except ValueError:
|
|
return default
|
|
|
|
|
|
def _env_bool(name: str, default: bool) -> bool:
|
|
value = os.getenv(name)
|
|
if value is None:
|
|
return default
|
|
normalized = value.strip().lower()
|
|
if normalized in {"1", "true", "yes", "on"}:
|
|
return True
|
|
if normalized in {"0", "false", "no", "off"}:
|
|
return False
|
|
return default
|
|
|
|
|
|
def _env_choice(name: str, default: str, allowed: tuple[str, ...]) -> str:
|
|
value = os.getenv(name)
|
|
normalized = default.strip().lower() if value is None else value.strip().lower()
|
|
if normalized in allowed:
|
|
return normalized
|
|
allowed_values = ", ".join(allowed)
|
|
raise RuntimeError(f"Invalid {name}: {normalized!r}. Expected one of {allowed_values}.")
|
|
|
|
|
|
def _env_csv(name: str, default: str) -> list[str]:
|
|
raw = os.getenv(name, default)
|
|
values = [item.strip() for item in raw.split(",")]
|
|
unique_values: list[str] = []
|
|
for value in values:
|
|
if not value or value in unique_values:
|
|
continue
|
|
unique_values.append(value)
|
|
return unique_values
|
|
|
|
|
|
def _required_env(*names: str) -> str:
|
|
for name in names:
|
|
value = os.getenv(name)
|
|
if not isinstance(value, str):
|
|
continue
|
|
normalized = value.strip()
|
|
if normalized:
|
|
return normalized
|
|
joined_names = ", ".join(names)
|
|
raise RuntimeError(f"Missing required environment variable: one of {joined_names}")
|
|
|
|
|
|
def _optional_env(*names: str) -> str | None:
|
|
for name in names:
|
|
value = os.getenv(name)
|
|
if not isinstance(value, str):
|
|
continue
|
|
normalized = value.strip()
|
|
if normalized:
|
|
return normalized
|
|
return None
|
|
|
|
|
|
DEVTOOLS_ENABLED = _env_bool("FASTVIDEO_ENABLE_DEVTOOLS", False)
|
|
PROMPT_SAFETY_ENABLED = _env_bool("FASTVIDEO_ENABLE_PROMPT_SAFETY", False)
|
|
|
|
|
|
def _resolve_devtools_paths(
|
|
default_path: Path,
|
|
overlay_path: Path,
|
|
env_name: str | None = None,
|
|
) -> tuple[str, str | None]:
|
|
env_value = os.getenv(env_name) if env_name else None
|
|
if isinstance(env_value, str) and env_value.strip():
|
|
return env_value.strip(), None
|
|
if DEVTOOLS_ENABLED:
|
|
return str(overlay_path), str(default_path)
|
|
return str(default_path), None
|
|
|
|
|
|
# Prompt LLM configuration.
|
|
PROMPT_SUPPORTED_PROVIDERS = (
|
|
"cerebras",
|
|
"groq",
|
|
)
|
|
if os.getenv("FASTVIDEO_PROMPT_PROVIDER") is not None:
|
|
_env_choice(
|
|
"FASTVIDEO_PROMPT_PROVIDER",
|
|
"cerebras",
|
|
PROMPT_SUPPORTED_PROVIDERS,
|
|
)
|
|
PROMPT_PROVIDER = "cerebras"
|
|
PROMPT_PROVIDER_RUNTIME_STAGES = (("cerebras", "groq"), )
|
|
PROMPT_PROVIDER_PRIORITY = (
|
|
"cerebras",
|
|
"groq",
|
|
)
|
|
PROMPT_PROVIDER_API_KEY_NAMES = {
|
|
"cerebras": ("CEREBRAS_API_KEY", ),
|
|
"groq": ("GROQ_API_KEY", ),
|
|
}
|
|
PROMPT_API_KEYS = {
|
|
provider: _optional_env(*PROMPT_PROVIDER_API_KEY_NAMES[provider])
|
|
for provider in PROMPT_SUPPORTED_PROVIDERS
|
|
}
|
|
PROMPT_API_BASE_URLS = {
|
|
"cerebras": (os.getenv("FASTVIDEO_PROMPT_CEREBRAS_API_BASE_URL", "").strip() or None),
|
|
"groq": (os.getenv(
|
|
"FASTVIDEO_PROMPT_GROQ_API_BASE_URL",
|
|
"https://api.groq.com/openai/v1",
|
|
).strip() or None),
|
|
}
|
|
PROMPT_API_KEY = PROMPT_API_KEYS[PROMPT_PROVIDER]
|
|
PROMPT_API_BASE_URL = PROMPT_API_BASE_URLS[PROMPT_PROVIDER]
|
|
PROMPT_MODEL = (os.getenv("FASTVIDEO_PROMPT_MODEL", "gpt-oss-120b").strip() or "gpt-oss-120b")
|
|
_PROMPT_CEREBRAS_REQUEST_MODEL = (os.getenv("FASTVIDEO_PROMPT_CEREBRAS_MODEL", PROMPT_MODEL).strip() or PROMPT_MODEL)
|
|
PROMPT_PROVIDER_MODELS = {
|
|
"cerebras": _PROMPT_CEREBRAS_REQUEST_MODEL,
|
|
"groq": (os.getenv(
|
|
"FASTVIDEO_PROMPT_GROQ_MODEL",
|
|
f"openai/{PROMPT_MODEL}",
|
|
).strip() or f"openai/{PROMPT_MODEL}"),
|
|
}
|
|
PROMPT_REWRITE_MODEL = PROMPT_MODEL
|
|
PROMPT_REWRITE_MODEL_OPTIONS = [PROMPT_REWRITE_MODEL]
|
|
PROMPT_TIMEOUT_MS = 20000
|
|
PROMPT_HTTP_TIMEOUT_MS = 3000
|
|
PROMPT_INITIAL_STAGE_TIMEOUT_MS = 1500
|
|
PROMPT_TEMPERATURE = 1.0
|
|
PROMPT_MAX_COMPLETION_TOKENS = 3000
|
|
(
|
|
PROMPT_ENHANCE_SYSTEM_PROMPT_PATH,
|
|
PROMPT_ENHANCE_SYSTEM_PROMPT_FALLBACK_PATH,
|
|
) = _resolve_devtools_paths(
|
|
_PROMPTS_ROOT / "next_segment_system_prompt.md",
|
|
_PROMPTS_LOCAL_ROOT / "next_segment_system_prompt.md",
|
|
"FASTVIDEO_PROMPT_ENHANCE_SYSTEM_PROMPT_PATH",
|
|
)
|
|
(
|
|
PROMPT_AUTO_SYSTEM_PROMPT_PATH,
|
|
PROMPT_AUTO_SYSTEM_PROMPT_FALLBACK_PATH,
|
|
) = _resolve_devtools_paths(
|
|
_PROMPTS_ROOT / "auto_extension_system_prompt.md",
|
|
_PROMPTS_LOCAL_ROOT / "auto_extension_system_prompt.md",
|
|
"FASTVIDEO_PROMPT_AUTO_SYSTEM_PROMPT_PATH",
|
|
)
|
|
(
|
|
PROMPT_REWRITE_ALL_SYSTEM_PROMPT_PATH,
|
|
PROMPT_REWRITE_ALL_SYSTEM_PROMPT_FALLBACK_PATH,
|
|
) = _resolve_devtools_paths(
|
|
_PROMPTS_ROOT / "rewrite_window_system_prompt.md",
|
|
_PROMPTS_LOCAL_ROOT / "rewrite_window_system_prompt.md",
|
|
"FASTVIDEO_PROMPT_REWRITE_ALL_SYSTEM_PROMPT_PATH",
|
|
)
|
|
(
|
|
PROMPT_REWRITE_USER_SYSTEM_PROMPT_PATH,
|
|
PROMPT_REWRITE_USER_SYSTEM_PROMPT_FALLBACK_PATH,
|
|
) = _resolve_devtools_paths(
|
|
_PROMPTS_ROOT / "rewrite_user_system_prompt.md",
|
|
_PROMPTS_LOCAL_ROOT / "rewrite_user_system_prompt.md",
|
|
"FASTVIDEO_PROMPT_REWRITE_USER_SYSTEM_PROMPT_PATH",
|
|
)
|
|
(
|
|
CURATED_PRESETS_FILE_PATH,
|
|
CURATED_PRESETS_FALLBACK_FILE_PATH,
|
|
) = _resolve_devtools_paths(
|
|
_CLIENT_PROMPTS_ROOT / "selected_ltx2_continuation_story_presets.json",
|
|
_CLIENT_PROMPTS_LOCAL_ROOT / "selected_ltx2_continuation_story_presets.json",
|
|
"FASTVIDEO_CURATED_PRESETS_FILE_PATH",
|
|
)
|
|
PROMPT_REWRITE_LOG_PATH = os.getenv(
|
|
"FASTVIDEO_PROMPT_REWRITE_LOG_PATH",
|
|
str(_SERVER_ROOT / "outputs" / "prompt_rewrite.jsonl"),
|
|
).strip()
|
|
PROMPT_ENHANCE_LOG_PATH = os.getenv(
|
|
"FASTVIDEO_PROMPT_ENHANCE_LOG_PATH",
|
|
str(_SERVER_ROOT / "outputs" / "prompt_enhance.jsonl"),
|
|
).strip()
|
|
PROMPT_AUTO_EXTENSION_LOG_PATH = os.getenv(
|
|
"FASTVIDEO_PROMPT_AUTO_EXTENSION_LOG_PATH",
|
|
str(_SERVER_ROOT / "outputs" / "prompt_auto_extension.jsonl"),
|
|
).strip()
|
|
SESSION_LOG_ROOT = os.getenv(
|
|
"FASTVIDEO_SESSION_LOG_ROOT",
|
|
str(_SERVER_ROOT / "outputs" / "session_logs"),
|
|
).strip()
|
|
|
|
# Auto extension behavior.
|
|
# Sleep is used as idle backoff when no prompt source is available.
|
|
PROMPT_AUTO_SLEEP_MS = _env_int("FASTVIDEO_PROMPT_AUTO_SLEEP_MS", 120)
|
|
PROMPT_AUTO_TIMEOUT_MS = _env_int("FASTVIDEO_PROMPT_AUTO_TIMEOUT_MS", 1800)
|
|
GENERATION_SEGMENT_CAP = max(0, _env_int("FASTVIDEO_GENERATION_SEGMENT_CAP", 6))
|
|
|
|
# Startup warmup behavior. Warmup compiles segment 1 and segment 2 inference
|
|
# paths before the worker is considered ready for serving.
|
|
STARTUP_WARMUP_ENABLED = _env_bool("FASTVIDEO_ENABLE_STARTUP_WARMUP", True)
|
|
STARTUP_WARMUP_PROMPT = os.getenv(
|
|
"FASTVIDEO_STARTUP_WARMUP_PROMPT",
|
|
("A cinematic drone shot over coastal cliffs at sunrise, "
|
|
"golden light, gentle ocean waves, ultra detailed"),
|
|
).strip()
|
|
STARTUP_WARMUP_TIMEOUT_SECONDS = max(1, _env_int("FASTVIDEO_STARTUP_WARMUP_TIMEOUT_SECONDS", 2400))
|