diff --git a/litellm/videos/__init__.py b/litellm/videos/__init__.py index 716add5f5d7..9fb66d7557a 100644 --- a/litellm/videos/__init__.py +++ b/litellm/videos/__init__.py @@ -1,16 +1,24 @@ """Video generation and management functions for LiteLLM.""" from .main import ( - avideo_generation, - video_generation, - avideo_list, - video_list, - avideo_status, - video_status, avideo_content, - video_content, + avideo_create_character, + avideo_edit, + avideo_extension, + avideo_generation, + avideo_get_character, + avideo_list, avideo_remix, + avideo_status, + video_content, + video_create_character, + video_edit, + video_extension, + video_generation, + video_get_character, + video_list, video_remix, + video_status, ) __all__ = [ @@ -24,4 +32,12 @@ __all__ = [ "video_content", "avideo_remix", "video_remix", + "avideo_create_character", + "video_create_character", + "avideo_get_character", + "video_get_character", + "avideo_edit", + "video_edit", + "avideo_extension", + "video_extension", ] diff --git a/litellm/videos/main.py b/litellm/videos/main.py index f6c9bb00576..a86f1d7dcea 100644 --- a/litellm/videos/main.py +++ b/litellm/videos/main.py @@ -15,6 +15,7 @@ from litellm.main import base_llm_http_handler from litellm.types.router import GenericLiteLLMParams from litellm.types.utils import CallTypes, FileTypes from litellm.types.videos.main import ( + CharacterObject, VideoCreateOptionalRequestParams, VideoObject, ) @@ -1090,3 +1091,522 @@ def video_status( # noqa: PLR0915 completion_kwargs=local_vars, extra_kwargs=kwargs, ) + + +@client +async def avideo_create_character( + name: str, + video: Any, + timeout=600, + custom_llm_provider=None, + extra_headers: Optional[Dict[str, Any]] = None, + extra_query: Optional[Dict[str, Any]] = None, + extra_body: Optional[Dict[str, Any]] = None, + **kwargs, +) -> CharacterObject: + """ + Asynchronously create a character from an uploaded video file. + Maps to POST /v1/videos/characters + """ + local_vars = locals() + try: + loop = asyncio.get_event_loop() + kwargs["async_call"] = True + + if custom_llm_provider is None: + custom_llm_provider = "openai" + + func = partial( + video_create_character, + name=name, + video=video, + timeout=timeout, + custom_llm_provider=custom_llm_provider, + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + **kwargs, + ) + + ctx = contextvars.copy_context() + func_with_context = partial(ctx.run, func) + init_response = await loop.run_in_executor(None, func_with_context) + + if asyncio.iscoroutine(init_response): + response = await init_response + else: + response = init_response + + return response + except Exception as e: + raise litellm.exception_type( + model="", + custom_llm_provider=custom_llm_provider, + original_exception=e, + completion_kwargs=local_vars, + extra_kwargs=kwargs, + ) + + +@client +def video_create_character( + name: str, + video: Any, + timeout=600, + custom_llm_provider=None, + extra_headers: Optional[Dict[str, Any]] = None, + extra_query: Optional[Dict[str, Any]] = None, + extra_body: Optional[Dict[str, Any]] = None, + **kwargs, +) -> Union[CharacterObject, Coroutine[Any, Any, CharacterObject]]: + """ + Create a character from an uploaded video file. + Maps to POST /v1/videos/characters + """ + local_vars = locals() + try: + litellm_logging_obj: LiteLLMLoggingObj = kwargs.pop("litellm_logging_obj") # type: ignore + litellm_call_id: Optional[str] = kwargs.get("litellm_call_id", None) + _is_async = kwargs.pop("async_call", False) is True + + mock_response = kwargs.get("mock_response", None) + if mock_response is not None: + if isinstance(mock_response, str): + mock_response = json.loads(mock_response) + return CharacterObject(**mock_response) + + if custom_llm_provider is None: + custom_llm_provider = "openai" + + litellm_params = GenericLiteLLMParams(**kwargs) + + provider_config: Optional[BaseVideoConfig] = ProviderConfigManager.get_provider_video_config( + model=None, + provider=litellm.LlmProviders(custom_llm_provider), + ) + + if provider_config is None: + raise ValueError(f"video create character is not supported for {custom_llm_provider}") + + local_vars.update(kwargs) + request_params: Dict = {"name": name} + + litellm_logging_obj.update_environment_variables( + model="", + user=kwargs.get("user"), + optional_params=dict(request_params), + litellm_params={"litellm_call_id": litellm_call_id, **request_params}, + custom_llm_provider=custom_llm_provider, + ) + + litellm_logging_obj.call_type = CallTypes.video_create_character.value + + return base_llm_http_handler.video_create_character_handler( + name=name, + video=video, + video_provider_config=provider_config, + custom_llm_provider=custom_llm_provider, + litellm_params=litellm_params, + logging_obj=litellm_logging_obj, + extra_headers=extra_headers, + timeout=timeout or DEFAULT_REQUEST_TIMEOUT, + _is_async=_is_async, + client=kwargs.get("client"), + ) + + except Exception as e: + raise litellm.exception_type( + model="", + custom_llm_provider=custom_llm_provider, + original_exception=e, + completion_kwargs=local_vars, + extra_kwargs=kwargs, + ) + + +@client +async def avideo_get_character( + character_id: str, + timeout=600, + custom_llm_provider=None, + extra_headers: Optional[Dict[str, Any]] = None, + extra_query: Optional[Dict[str, Any]] = None, + extra_body: Optional[Dict[str, Any]] = None, + **kwargs, +) -> CharacterObject: + """ + Asynchronously retrieve a character by ID. + Maps to GET /v1/videos/characters/{character_id} + """ + local_vars = locals() + try: + loop = asyncio.get_event_loop() + kwargs["async_call"] = True + + func = partial( + video_get_character, + character_id=character_id, + timeout=timeout, + custom_llm_provider=custom_llm_provider, + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + **kwargs, + ) + + ctx = contextvars.copy_context() + func_with_context = partial(ctx.run, func) + init_response = await loop.run_in_executor(None, func_with_context) + + if asyncio.iscoroutine(init_response): + response = await init_response + else: + response = init_response + + return response + except Exception as e: + raise litellm.exception_type( + model="", + custom_llm_provider=custom_llm_provider, + original_exception=e, + completion_kwargs=local_vars, + extra_kwargs=kwargs, + ) + + +@client +def video_get_character( + character_id: str, + timeout=600, + custom_llm_provider=None, + extra_headers: Optional[Dict[str, Any]] = None, + extra_query: Optional[Dict[str, Any]] = None, + extra_body: Optional[Dict[str, Any]] = None, + **kwargs, +) -> Union[CharacterObject, Coroutine[Any, Any, CharacterObject]]: + """ + Retrieve a character by ID. + Maps to GET /v1/videos/characters/{character_id} + """ + local_vars = locals() + try: + litellm_logging_obj: LiteLLMLoggingObj = kwargs.pop("litellm_logging_obj") # type: ignore + litellm_call_id: Optional[str] = kwargs.get("litellm_call_id", None) + _is_async = kwargs.pop("async_call", False) is True + + mock_response = kwargs.get("mock_response", None) + if mock_response is not None: + if isinstance(mock_response, str): + mock_response = json.loads(mock_response) + return CharacterObject(**mock_response) + + if custom_llm_provider is None: + custom_llm_provider = "openai" + + litellm_params = GenericLiteLLMParams(**kwargs) + + provider_config: Optional[BaseVideoConfig] = ProviderConfigManager.get_provider_video_config( + model=None, + provider=litellm.LlmProviders(custom_llm_provider), + ) + + if provider_config is None: + raise ValueError(f"video get character is not supported for {custom_llm_provider}") + + local_vars.update(kwargs) + request_params: Dict = {"character_id": character_id} + + litellm_logging_obj.update_environment_variables( + model="", + user=kwargs.get("user"), + optional_params=dict(request_params), + litellm_params={"litellm_call_id": litellm_call_id, **request_params}, + custom_llm_provider=custom_llm_provider, + ) + + litellm_logging_obj.call_type = CallTypes.video_get_character.value + + return base_llm_http_handler.video_get_character_handler( + character_id=character_id, + video_provider_config=provider_config, + custom_llm_provider=custom_llm_provider, + litellm_params=litellm_params, + logging_obj=litellm_logging_obj, + extra_headers=extra_headers, + timeout=timeout or DEFAULT_REQUEST_TIMEOUT, + _is_async=_is_async, + client=kwargs.get("client"), + ) + + except Exception as e: + raise litellm.exception_type( + model="", + custom_llm_provider=custom_llm_provider, + original_exception=e, + completion_kwargs=local_vars, + extra_kwargs=kwargs, + ) + + +@client +async def avideo_edit( + video_id: str, + prompt: str, + timeout=600, + custom_llm_provider=None, + extra_headers: Optional[Dict[str, Any]] = None, + extra_query: Optional[Dict[str, Any]] = None, + extra_body: Optional[Dict[str, Any]] = None, + **kwargs, +) -> VideoObject: + """ + Asynchronously create a video edit job. + Maps to POST /v1/videos/edits + """ + local_vars = locals() + try: + loop = asyncio.get_event_loop() + kwargs["async_call"] = True + + func = partial( + video_edit, + video_id=video_id, + prompt=prompt, + timeout=timeout, + custom_llm_provider=custom_llm_provider, + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + **kwargs, + ) + + ctx = contextvars.copy_context() + func_with_context = partial(ctx.run, func) + init_response = await loop.run_in_executor(None, func_with_context) + + if asyncio.iscoroutine(init_response): + response = await init_response + else: + response = init_response + + return response + except Exception as e: + raise litellm.exception_type( + model="", + custom_llm_provider=custom_llm_provider, + original_exception=e, + completion_kwargs=local_vars, + extra_kwargs=kwargs, + ) + + +@client +def video_edit( + video_id: str, + prompt: str, + timeout=600, + custom_llm_provider=None, + extra_headers: Optional[Dict[str, Any]] = None, + extra_query: Optional[Dict[str, Any]] = None, + extra_body: Optional[Dict[str, Any]] = None, + **kwargs, +) -> Union[VideoObject, Coroutine[Any, Any, VideoObject]]: + """ + Create a video edit job. + Maps to POST /v1/videos/edits + """ + local_vars = locals() + try: + litellm_logging_obj: LiteLLMLoggingObj = kwargs.pop("litellm_logging_obj") # type: ignore + litellm_call_id: Optional[str] = kwargs.get("litellm_call_id", None) + _is_async = kwargs.pop("async_call", False) is True + + mock_response = kwargs.get("mock_response", None) + if mock_response is not None: + if isinstance(mock_response, str): + mock_response = json.loads(mock_response) + return VideoObject(**mock_response) + + if custom_llm_provider is None: + decoded = decode_video_id_with_provider(video_id) + custom_llm_provider = decoded.get("custom_llm_provider") or "openai" + + litellm_params = GenericLiteLLMParams(**kwargs) + + provider_config: Optional[BaseVideoConfig] = ProviderConfigManager.get_provider_video_config( + model=None, + provider=litellm.LlmProviders(custom_llm_provider), + ) + + if provider_config is None: + raise ValueError(f"video edit is not supported for {custom_llm_provider}") + + local_vars.update(kwargs) + request_params: Dict = {"video_id": video_id, "prompt": prompt} + + litellm_logging_obj.update_environment_variables( + model="", + user=kwargs.get("user"), + optional_params=dict(request_params), + litellm_params={"litellm_call_id": litellm_call_id, **request_params}, + custom_llm_provider=custom_llm_provider, + ) + + litellm_logging_obj.call_type = CallTypes.video_edit.value + + return base_llm_http_handler.video_edit_handler( + prompt=prompt, + video_id=video_id, + video_provider_config=provider_config, + custom_llm_provider=custom_llm_provider, + litellm_params=litellm_params, + logging_obj=litellm_logging_obj, + extra_headers=extra_headers, + extra_body=extra_body, + timeout=timeout or DEFAULT_REQUEST_TIMEOUT, + _is_async=_is_async, + client=kwargs.get("client"), + ) + + except Exception as e: + raise litellm.exception_type( + model="", + custom_llm_provider=custom_llm_provider, + original_exception=e, + completion_kwargs=local_vars, + extra_kwargs=kwargs, + ) + + +@client +async def avideo_extension( + video_id: str, + prompt: str, + seconds: str, + timeout=600, + custom_llm_provider=None, + extra_headers: Optional[Dict[str, Any]] = None, + extra_query: Optional[Dict[str, Any]] = None, + extra_body: Optional[Dict[str, Any]] = None, + **kwargs, +) -> VideoObject: + """ + Asynchronously create a video extension. + Maps to POST /v1/videos/extensions + """ + local_vars = locals() + try: + loop = asyncio.get_event_loop() + kwargs["async_call"] = True + + func = partial( + video_extension, + video_id=video_id, + prompt=prompt, + seconds=seconds, + timeout=timeout, + custom_llm_provider=custom_llm_provider, + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + **kwargs, + ) + + ctx = contextvars.copy_context() + func_with_context = partial(ctx.run, func) + init_response = await loop.run_in_executor(None, func_with_context) + + if asyncio.iscoroutine(init_response): + response = await init_response + else: + response = init_response + + return response + except Exception as e: + raise litellm.exception_type( + model="", + custom_llm_provider=custom_llm_provider, + original_exception=e, + completion_kwargs=local_vars, + extra_kwargs=kwargs, + ) + + +@client +def video_extension( + video_id: str, + prompt: str, + seconds: str, + timeout=600, + custom_llm_provider=None, + extra_headers: Optional[Dict[str, Any]] = None, + extra_query: Optional[Dict[str, Any]] = None, + extra_body: Optional[Dict[str, Any]] = None, + **kwargs, +) -> Union[VideoObject, Coroutine[Any, Any, VideoObject]]: + """ + Create a video extension. + Maps to POST /v1/videos/extensions + """ + local_vars = locals() + try: + litellm_logging_obj: LiteLLMLoggingObj = kwargs.pop("litellm_logging_obj") # type: ignore + litellm_call_id: Optional[str] = kwargs.get("litellm_call_id", None) + _is_async = kwargs.pop("async_call", False) is True + + mock_response = kwargs.get("mock_response", None) + if mock_response is not None: + if isinstance(mock_response, str): + mock_response = json.loads(mock_response) + return VideoObject(**mock_response) + + if custom_llm_provider is None: + decoded = decode_video_id_with_provider(video_id) + custom_llm_provider = decoded.get("custom_llm_provider") or "openai" + + litellm_params = GenericLiteLLMParams(**kwargs) + + provider_config: Optional[BaseVideoConfig] = ProviderConfigManager.get_provider_video_config( + model=None, + provider=litellm.LlmProviders(custom_llm_provider), + ) + + if provider_config is None: + raise ValueError(f"video extension is not supported for {custom_llm_provider}") + + local_vars.update(kwargs) + request_params: Dict = {"video_id": video_id, "prompt": prompt, "seconds": seconds} + + litellm_logging_obj.update_environment_variables( + model="", + user=kwargs.get("user"), + optional_params=dict(request_params), + litellm_params={"litellm_call_id": litellm_call_id, **request_params}, + custom_llm_provider=custom_llm_provider, + ) + + litellm_logging_obj.call_type = CallTypes.video_extension.value + + return base_llm_http_handler.video_extension_handler( + prompt=prompt, + video_id=video_id, + seconds=seconds, + video_provider_config=provider_config, + custom_llm_provider=custom_llm_provider, + litellm_params=litellm_params, + logging_obj=litellm_logging_obj, + extra_headers=extra_headers, + extra_body=extra_body, + timeout=timeout or DEFAULT_REQUEST_TIMEOUT, + _is_async=_is_async, + client=kwargs.get("client"), + ) + + except Exception as e: + raise litellm.exception_type( + model="", + custom_llm_provider=custom_llm_provider, + original_exception=e, + completion_kwargs=local_vars, + extra_kwargs=kwargs, + )