mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-09 22:31:41 +00:00
fix(vertex-ai): map veo video size to resolution
This commit is contained in:
parent
cc8e128d53
commit
1e4b30e4ed
4 changed files with 78 additions and 9 deletions
|
|
@ -91,6 +91,13 @@ class VertexAIVideoConfig(BaseVideoConfig, VertexBase):
|
|||
3. Extract video data (base64) from response
|
||||
"""
|
||||
|
||||
_OPENAI_VIDEO_SIZE_TO_ASPECT_RATIO: dict[str, str] = {
|
||||
"1280x720": "16:9",
|
||||
"1920x1080": "16:9",
|
||||
"720x1280": "9:16",
|
||||
"1080x1920": "9:16",
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
BaseVideoConfig.__init__(self)
|
||||
VertexBase.__init__(self)
|
||||
|
|
@ -133,6 +140,8 @@ class VertexAIVideoConfig(BaseVideoConfig, VertexBase):
|
|||
- prompt → prompt (in instances)
|
||||
- input_reference → image (in instances)
|
||||
- size → aspectRatio (e.g., "1280x720" → "16:9")
|
||||
- size → resolution when inferable ("1280x720"/"720x1280" → "720p",
|
||||
"1920x1080"/"1080x1920" → "1080p"); skipped if ``resolution`` is already set
|
||||
- seconds → durationSeconds (defaults to 4 seconds if not provided)
|
||||
"""
|
||||
mapped_params: Final[dict[str, Any]] = {}
|
||||
|
|
@ -147,6 +156,9 @@ class VertexAIVideoConfig(BaseVideoConfig, VertexBase):
|
|||
if "parameters" in video_create_optional_params:
|
||||
mapped_params["parameters"] = video_create_optional_params["parameters"]
|
||||
|
||||
if "resolution" in video_create_optional_params:
|
||||
mapped_params["resolution"] = video_create_optional_params["resolution"]
|
||||
|
||||
# Map size to aspectRatio
|
||||
if "size" in video_create_optional_params:
|
||||
size: Final = video_create_optional_params["size"]
|
||||
|
|
@ -154,6 +166,15 @@ class VertexAIVideoConfig(BaseVideoConfig, VertexBase):
|
|||
aspect_ratio: Final = self._convert_size_to_aspect_ratio(size)
|
||||
if aspect_ratio:
|
||||
mapped_params["aspectRatio"] = aspect_ratio
|
||||
nested_params: Final = video_create_optional_params.get("parameters")
|
||||
has_resolution = "resolution" in mapped_params or (
|
||||
isinstance(nested_params, dict)
|
||||
and nested_params.get("resolution") is not None
|
||||
)
|
||||
if not has_resolution:
|
||||
inferred_resolution = self._convert_size_to_resolution(size)
|
||||
if inferred_resolution is not None:
|
||||
mapped_params["resolution"] = inferred_resolution
|
||||
|
||||
# Map seconds to durationSeconds, default to 4 seconds (matching OpenAI)
|
||||
if "seconds" in video_create_optional_params:
|
||||
|
|
@ -177,14 +198,21 @@ class VertexAIVideoConfig(BaseVideoConfig, VertexBase):
|
|||
if not size:
|
||||
return None
|
||||
|
||||
aspect_ratio_map: Final = {
|
||||
"1280x720": "16:9",
|
||||
"1920x1080": "16:9",
|
||||
"720x1280": "9:16",
|
||||
"1080x1920": "9:16",
|
||||
}
|
||||
return self._OPENAI_VIDEO_SIZE_TO_ASPECT_RATIO.get(size, "16:9")
|
||||
|
||||
return aspect_ratio_map.get(size, "16:9")
|
||||
def _convert_size_to_resolution(self, size: str) -> str | None:
|
||||
if not size or size not in self._OPENAI_VIDEO_SIZE_TO_ASPECT_RATIO:
|
||||
return None
|
||||
try:
|
||||
width, height = size.split("x", 1)
|
||||
smaller_edge = min(int(width), int(height))
|
||||
except (ValueError, TypeError):
|
||||
return None
|
||||
if smaller_edge == 720:
|
||||
return "720p"
|
||||
if smaller_edge == 1080:
|
||||
return "1080p"
|
||||
return None
|
||||
|
||||
def validate_environment(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -39352,7 +39352,8 @@
|
|||
"output_cost_per_second_1080p": 0.08,
|
||||
"source": "https://cloud.google.com/gemini-enterprise-agent-platform/generative-ai/pricing#veo",
|
||||
"supported_modalities": [
|
||||
"text"
|
||||
"text",
|
||||
"image"
|
||||
],
|
||||
"supported_output_modalities": [
|
||||
"video"
|
||||
|
|
|
|||
|
|
@ -39352,7 +39352,8 @@
|
|||
"output_cost_per_second_1080p": 0.08,
|
||||
"source": "https://cloud.google.com/gemini-enterprise-agent-platform/generative-ai/pricing#veo",
|
||||
"supported_modalities": [
|
||||
"text"
|
||||
"text",
|
||||
"image"
|
||||
],
|
||||
"supported_output_modalities": [
|
||||
"video"
|
||||
|
|
|
|||
|
|
@ -153,6 +153,7 @@ class TestVertexAIVideoConfig:
|
|||
assert info["max_input_tokens"] == 1024
|
||||
assert info["output_cost_per_second"] == 0.05
|
||||
assert info["output_cost_per_second_1080p"] == 0.08
|
||||
assert info["supported_modalities"] == ["text", "image"]
|
||||
|
||||
def test_veo_31_lite_provider_routing_from_local_model_map(
|
||||
self, monkeypatch: pytest.MonkeyPatch
|
||||
|
|
@ -284,6 +285,44 @@ class TestVertexAIVideoConfig:
|
|||
|
||||
assert mapped["durationSeconds"] == 8
|
||||
assert mapped["aspectRatio"] == "16:9"
|
||||
assert mapped["resolution"] == "720p"
|
||||
|
||||
def test_map_openai_size_to_1080p_resolution(self):
|
||||
mapped = self.config.map_openai_params(
|
||||
video_create_optional_params={"size": "1920x1080"},
|
||||
model=VEO_31_LITE_VERTEX_MODEL,
|
||||
drop_params=False,
|
||||
)
|
||||
|
||||
assert mapped["aspectRatio"] == "16:9"
|
||||
assert mapped["resolution"] == "1080p"
|
||||
|
||||
def test_map_openai_size_does_not_override_provider_resolution(self):
|
||||
mapped = self.config.map_openai_params(
|
||||
video_create_optional_params={
|
||||
"size": "1920x1080",
|
||||
"parameters": {"resolution": "720p"},
|
||||
},
|
||||
model=VEO_31_LITE_VERTEX_MODEL,
|
||||
drop_params=False,
|
||||
)
|
||||
|
||||
assert mapped["aspectRatio"] == "16:9"
|
||||
assert "resolution" not in mapped
|
||||
assert mapped["parameters"] == {"resolution": "720p"}
|
||||
|
||||
def test_map_openai_size_does_not_override_direct_resolution(self):
|
||||
mapped = self.config.map_openai_params(
|
||||
video_create_optional_params={
|
||||
"size": "1920x1080",
|
||||
"resolution": "720p",
|
||||
},
|
||||
model=VEO_31_LITE_VERTEX_MODEL,
|
||||
drop_params=False,
|
||||
)
|
||||
|
||||
assert mapped["aspectRatio"] == "16:9"
|
||||
assert mapped["resolution"] == "720p"
|
||||
|
||||
def test_map_openai_params_default_duration(self):
|
||||
"""Test that durationSeconds is omitted when not provided."""
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue